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

useFocusReturn#

useFocusReturn is the focus management Popover uses. When an overlay opens it moves focus into the popup; when it closes it returns focus to wherever it was before. It is not a focus trap: tab order flows out of the popup into the rest of the page, which is what a non-modal overlay wants.

Demo#

Close it (Escape or a button) and focus returns to the trigger.

Example#

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

function Panel({ open }: { open: boolean }) {
  const popupRef = useRef<HTMLDivElement>(null);
  useFocusReturn({ open, popupRef });
  return open ? (
    <div ref={popupRef}>
      <button>First</button>
      <button>Second</button>
    </div>
  ) : null;
}

Signature#

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

function useFocusReturn(opts: UseFocusReturnOptions): void;

interface UseFocusReturnOptions {
  open: boolean;
  popupRef: RefObject<HTMLElement>;
  initialFocusRef?: RefObject<HTMLElement>; // defaults to first focusable, then popup
}

Options#

OptionTypeDefaultNotes
openbooleannoneFocus moves in when this becomes true and returns when it falls.
popupRefRefObjectnoneThe popup; focus moves into it on open.
initialFocusRefRefObjectoptionalElement to focus first, instead of the first focusable.

On open it focuses initialFocusRef, else the first focusable element in the popup, else the popup itself. On close it returns focus to the element that was focused when the overlay opened (usually the trigger). It does not trap focus, so pair it with a dismissal mechanism such as useDismiss.