-
Notifications
You must be signed in to change notification settings - Fork 80
/
A11ySheet.tsx
69 lines (59 loc) · 1.51 KB
/
A11ySheet.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import { useRef, type PropsWithChildren } from 'react';
import { type OverlayTriggerState } from 'react-stately';
import { Sheet } from 'react-modal-sheet';
import {
FocusScope,
useDialog,
useOverlay,
useModal,
OverlayProvider,
} from 'react-aria';
type SheetProps = {
state: OverlayTriggerState;
label: string;
};
export function A11ySheet({
state, label, children, ...rest
}: PropsWithChildren<SheetProps>) {
return (
<Sheet {...rest} isOpen={state.isOpen} onClose={state.close}>
<OverlayProvider>
<FocusScope contain autoFocus restoreFocus>
<A11ySheetContent state={state} label={label}>
{children}
</A11ySheetContent>
</FocusScope>
</OverlayProvider>
</Sheet>
);
}
const A11ySheetContent = ({
state,
label,
children,
}: PropsWithChildren<SheetProps>) => {
const a11yProps = useA11ySheet(state, label);
return (
<>
<Sheet.Container {...a11yProps}>
<Sheet.Header />
<Sheet.Content>{children}</Sheet.Content>
</Sheet.Container>
<Sheet.Backdrop />
</>
);
};
const useA11ySheet = (state: OverlayTriggerState, label: string) => {
const ref = useRef<HTMLDivElement>(null);
const dialog = useDialog({ 'aria-label': label }, ref);
const overlay = useOverlay(
{ onClose: state.close, isOpen: true, isDismissable: true },
ref
);
useModal();
return {
ref,
...overlay.overlayProps,
...dialog.dialogProps,
} as any; // HACK: fix type conflicts with Framer Motion
};