hono-preact

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

OptionTypeDefaultNotes
openbooleannonePositioning runs only while open.
anchorRefRefObjectnoneThe reference element.
floatingRefRefObjectnoneThe element being positioned.
arrowRefRefObjectoptionalEnables arrow positioning.
side'top' | 'right' | 'bottom' | 'left''bottom'Preferred side.
align'start' | 'center' | 'end''center'Alignment along the side.
offsetnumber8Gap in pixels.

Returns

FieldTypeDescription
side'top' | 'right' | 'bottom' | 'left'Resolved side after collision handling.
align'start' | 'center' | 'end'Resolved alignment.
arrowXnumber | nullArrow x offset in px, or null.
arrowYnumber | nullArrow 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}
    </>
  );
}