usePosition
usePosition is the positioning binding Popover and Tooltip use. It wraps
Floating UI and keeps a floating element anchored to
a reference element, updating on scroll and resize.
Signature
import { usePosition } from '@hono-preact/ui';
function usePosition(opts: UsePositionOptions): PositionState;
interface UsePositionOptions {
open: boolean;
anchorRef: RefObject<HTMLElement>;
floatingRef: RefObject<HTMLElement>;
arrowRef?: RefObject<HTMLElement>;
side?: 'top' | 'right' | 'bottom' | 'left'; // default 'bottom'
align?: 'start' | 'center' | 'end'; // default 'center'
offset?: number; // gap in px, default 8
}
interface PositionState {
side: 'top' | 'right' | 'bottom' | 'left';
align: 'start' | 'center' | 'end';
arrowX: number | null;
arrowY: number | null;
}
Options
| Option | Type | Default | Notes |
|---|
open | boolean | none | Positioning runs only while open. |
anchorRef | RefObject | none | The reference element. |
floatingRef | RefObject | none | The element being positioned. |
arrowRef | RefObject | optional | Enables arrow positioning. |
side | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | Preferred side. |
align | 'start' | 'center' | 'end' | 'center' | Alignment along the side. |
offset | number | 8 | Gap in pixels. |
Returns
| Field | Type | Description |
|---|
side | 'top' | 'right' | 'bottom' | 'left' | Resolved side after collision handling. |
align | 'start' | 'center' | 'end' | Resolved alignment. |
arrowX | number | null | Arrow x offset in px, or null. |
arrowY | number | null | Arrow y offset in px, or null. |
Example
import { usePosition } from '@hono-preact/ui';
import { useRef } from 'preact/hooks';
function Anchored({ open }: { open: boolean }) {
const anchorRef = useRef<HTMLButtonElement>(null);
const floatingRef = useRef<HTMLDivElement>(null);
const { side, align } = usePosition({
open,
anchorRef,
floatingRef,
side: 'bottom',
align: 'center',
offset: 8,
});
return (
<>
<button ref={anchorRef}>Anchor</button>
{open ? (
<div ref={floatingRef} data-side={side} data-align={align}>
floating
</div>
) : null}
</>
);
}