/
SimpleExample.tsx
95 lines (90 loc) · 2.99 KB
/
SimpleExample.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import {
CSSProperties,
ReactElement,
useCallback,
useRef,
useState,
} from "react";
import { Button } from "@react-md/button";
import { TextIconSpacing } from "@react-md/icon";
import { List, ListItem } from "@react-md/list";
import { ArrowDropDownSVGIcon } from "@react-md/material-icons";
import { Overlay } from "@react-md/overlay";
import { Typography } from "@react-md/typography";
import { getFixedPosition, ScrollListener, useToggle } from "@react-md/utils";
import styles from "./SimpleExample.module.scss";
export default function SimpleExample(): ReactElement {
const [visible, , hide, toggle] = useToggle(false);
const [style, setStyle] = useState<CSSProperties | undefined>();
const buttonRef = useRef<HTMLButtonElement | null>(null);
const listRef = useRef<HTMLUListElement | null>(null);
const updatePosition = useCallback(() => {
setStyle(
getFixedPosition({
container: buttonRef.current,
element: listRef.current,
}).style
);
}, []);
const listRefCB = useCallback((list: HTMLUListElement | null) => {
listRef.current = list;
updatePosition();
// only want to call this once on mount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div className={styles.container}>
<Button
id="portal-button"
theme="secondary"
themeType="outline"
aria-haspopup="true"
aria-expanded={visible}
onClick={toggle}
ref={buttonRef}
>
<TextIconSpacing icon={<ArrowDropDownSVGIcon />} iconAfter>
Options...
</TextIconSpacing>
</Button>
<Overlay
id="portal-menu-overlay"
className={styles.overlay}
visible={visible}
onRequestClose={hide}
>
<List
role="menu"
id="portal-menu"
aria-labelledby="portal-button"
tabIndex={-1}
ref={listRefCB}
style={style}
className={styles.menu}
onClick={(event) => {
if (event.currentTarget !== event.target) {
hide();
}
}}
>
<ScrollListener onScroll={updatePosition} />
{Array.from({ length: 6 }).map((_, i) => (
<ListItem id={`menu-item-${i}`} key={i} role="menuitem">
{`Option ${i + 1}`}
</ListItem>
))}
</List>
</Overlay>
<Typography>
In condimentum ultrices metus ut viverra. In faucibus erat eu massa
tincidunt finibus. Donec eget quam venenatis, venenatis arcu sed, mollis
tellus. Mauris massa nunc, condimentum quis nisi vel, fermentum
pellentesque est. Pellentesque varius rhoncus dui. Donec suscipit
gravida justo eu pharetra. Donec suscipit neque a orci bibendum, a
consectetur ipsum finibus. Aenean est ligula, aliquet ut nunc vitae,
volutpat pharetra tortor. Cras ipsum mi, posuere eu diam a, cursus
euismod mi. Ut vitae eros nibh.
</Typography>
</div>
);
}