Line data Source code
1 : import * as React from 'react';
2 : import { XIcon } from '../ui/foundations/symbol_icon.js';
3 :
4 : import { Portal } from '../ui/foundations/portal.js';
5 : import { ButtonVariant, IconButton } from '../ui/foundations/button.js';
6 : import { useOverlay } from '../ui/foundations/overlay.js';
7 : import { useFocusTrap } from '../ui/foundations/focus.js';
8 : import * as styles from './session_navigation_drawer.module.css';
9 :
10 : interface Props {
11 : open: boolean;
12 : onClose: () => void;
13 : returnFocusRef: React.RefObject<HTMLElement | null>;
14 : children: React.ReactNode;
15 : }
16 :
17 1 : export const SessionNavigationDrawer: React.FC<Props> = (props) => {
18 1 : const closeButtonRef = React.useRef<HTMLButtonElement>(null);
19 1 : const overlayRef = useOverlay({
20 1 : onEscape: props.onClose,
21 1 : onClickOutside: props.onClose,
22 1 : returnFocusRef: props.returnFocusRef,
23 1 : initialFocusRef: closeButtonRef,
24 1 : });
25 1 : useFocusTrap({
26 1 : containerRef: overlayRef as React.RefObject<HTMLElement>,
27 1 : initialFocusRef: closeButtonRef as React.RefObject<HTMLElement>,
28 1 : disabled: !props.open,
29 1 : });
30 :
31 1 : if (!props.open) return null;
32 1 : return (
33 1 : <Portal>
34 1 : <div>
35 1 : <div className={styles.backdrop} aria-hidden="true" />
36 1 : <aside ref={overlayRef} className={styles.drawer} role="dialog" aria-modal="true" aria-label="Session workbench">
37 1 : <header className={styles.header}>
38 1 : <IconButton ref={closeButtonRef} variant={ButtonVariant.Invisible} aria-label="Close session workbench" onClick={props.onClose}>
39 1 : <XIcon />
40 1 : </IconButton>
41 1 : </header>
42 1 : <div className={styles.body}>{props.children}</div>
43 1 : </aside>
44 1 : </div>
45 1 : </Portal>
46 : );
47 1 : };
|