diff options
Diffstat (limited to 'src/components/ButtonMenu.tsx')
| -rw-r--r-- | src/components/ButtonMenu.tsx | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/components/ButtonMenu.tsx b/src/components/ButtonMenu.tsx new file mode 100644 index 0000000..6a2b73e --- /dev/null +++ b/src/components/ButtonMenu.tsx @@ -0,0 +1,42 @@ +import type { ComponentChildren } from 'preact'; +import { useEffect, useRef, useId } from 'preact/hooks'; +import { useSignal, batch } from '@preact/signals'; +import Button from './Button.tsx'; +import Menu from './Menu.tsx'; +import './ButtonMenu.css'; + +export interface ButtonMenuProps { + children: ComponentChildren; + label: string; +} + +const ButtonMenu = ({ children, label }: ButtonMenuProps) => { + const id = useId(); + const ref = useRef(null); + const x = useSignal(0); + const y = useSignal(0); + + const updateRect = () => batch(() => { + const rect = ref.current?.getBoundingClientRect(); + if (!rect) return; + x.value = rect.x; + y.value = rect.y + rect.height + 1; + }); + useEffect(updateRect, [ref.current]); + + return ( + <div + class="__ButtonMenu" + ref={ref} + onScroll={updateRect} + style={`--anchor-x: ${x}px; --anchor-y: ${y}px;`} + > + <Button kind="ghost" popoverTarget={id}>{label}</Button> + <Menu id={id} popover="auto"> + {children} + </Menu> + </div> + ); +}; + +export default ButtonMenu; |
