hono-preact
Overview
Quick Start
The Route Table
Layouts & Nesting
Adding Pages
Active Links
Server Loaders
Loading States
Reloading Data
Prefetching
Streaming
Live Loaders
Realtime Channels
Server Actions
Validation
Optimistic UI
View Transitions
Middleware
CSRF Protection
CLI
Vite Config
Project Structure
Composing Hono Middleware
WebSockets
Rooms & Presence
renderPage
Link Prefetch
Build & Deploy
Overview
Dialog
Popover
Tooltip
Menu
Context Menu
Select
Combobox
Toast
renderElement
useControllableState
mergeRefs
useListNavigation
useTypeahead
useListboxSelection
usePosition
usePositioner
useDismiss
useFocusReturn
useSafeArea
usePresence

useDismiss#

useDismiss registers an open overlay with a shared dismissal stack. Pressing Escape or pressing outside the overlay dismisses the topmost registered layer, so nested overlays close one at a time, innermost first.

See also: useFocusReturn, usePosition, useSafeArea.

Demo#

Example#

import { useDismiss } from 'hono-preact-ui';
import { useRef } from 'preact/hooks';

function Panel({ open, onClose }: { open: boolean; onClose: () => void }) {
  const ref = useRef<HTMLDivElement>(null);
  useDismiss({
    enabled: open,
    refs: [ref],
    onDismiss: onClose,
  });
  return open ? <div ref={ref}>panel</div> : null;
}

Signature#

import { useDismiss } from 'hono-preact-ui';

function useDismiss(opts: UseDismissOptions): void;

interface UseDismissOptions {
  enabled: boolean; // typically the open state
  refs: RefObject<HTMLElement>[]; // elements treated as inside (no outside-press)
  escape?: boolean; // default true
  outsidePress?: boolean; // default true
  id?: string; // dismiss-tree node id (nested menus); omit for a single-node layer
  parentId?: string | null; // parent node id for submenu coordination
  onDismiss: (reason: 'escape' | 'outside-press') => void;
}

Options#

OptionTypeDefaultNotes
enabledbooleannoneRegister only while open.
refsRefObject[]noneElements treated as inside (no outside-press).
escapebooleantrueDismiss on Escape.
outsidePressbooleantrueDismiss on an outside pointer press.
idstringoptionalDismiss-tree node id for nested menus; omit for a single-node layer (Popover / Tooltip).
parentIdstring | nulloptionalParent node's id for submenu coordination; omit at the tree root.
onDismiss(reason) => voidnoneCalled with 'escape' or 'outside-press'.

The listeners are document-level and capture-phase, attached once and shared across every registered layer, so adding overlays does not multiply listeners.