This repository was archived by the owner on Jun 13, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathDropdownContainer.tsx
More file actions
105 lines (94 loc) · 2.35 KB
/
DropdownContainer.tsx
File metadata and controls
105 lines (94 loc) · 2.35 KB
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
96
97
98
99
100
101
102
103
104
105
import React, {
ReactChild,
RefObject,
useCallback,
useEffect,
useRef,
useState,
} from 'react';
const getDropDownStyle = (
buttonRef: RefObject<HTMLButtonElement>,
contentsRef: RefObject<HTMLDivElement>,
alignLeft?: boolean,
padding?: number,
) => {
if (!buttonRef.current || !contentsRef.current) {
return undefined;
}
const main = buttonRef.current?.getBoundingClientRect();
const contents = contentsRef.current?.getBoundingClientRect();
return {
left: main.x + (alignLeft ? -contents.width + main.width : 0),
top: main.y + main.height + (padding || 4),
minWidth: main.width,
};
};
const DropdownContainer = (props: {
className?: string;
space?: number;
alignLeft?: boolean;
dontCollapse?: boolean;
onClick?: () => void;
children: ReactChild[] | ReactChild;
}) => {
const [isExtended, setExtended] = useState(false);
const buttonRef = useRef<HTMLButtonElement>(null);
const contentsRef = useRef<HTMLDivElement>(null);
const [pos, setPos] = useState<
| {
left: number;
top: number;
minWidth: number;
}
| undefined
>(undefined);
const clickListener = useCallback(() => {
setExtended(false);
}, []);
useEffect(() => {
setPos(
getDropDownStyle(buttonRef, contentsRef, props.alignLeft, props.space),
);
if (!props.dontCollapse) {
window.addEventListener('click', clickListener);
return () => {
window.removeEventListener('click', clickListener);
};
}
}, [
isExtended,
clickListener,
props.alignLeft,
props.space,
props.dontCollapse,
]);
const [first, ...children] = React.Children.toArray(props.children);
return (
<>
<button
className={props.className}
ref={buttonRef}
type="button"
onClick={(event) => {
setExtended(!isExtended);
// prevent the click event from bubbling up to event that will close the drawer
event.stopPropagation();
props.onClick && props.onClick();
}}
>
{first}
</button>
{isExtended && (
<div
ref={contentsRef}
hidden={!pos}
className="fixed w-max h-max z-20 flex flex-col"
style={{ ...pos, marginLeft: 0 }}
>
{children}
</div>
)}
</>
);
};
export default DropdownContainer;