Components#
hono-preact ships a set of headless, accessible UI primitives that lean on the
platform: the native <dialog> element and top layer, a battle-tested positioning
library, and a thin ARIA, keyboard, and collection layer on top. The popup
components (Popover, Tooltip, Menu, Select, Combobox) promote their surfaces into
the top layer with the Popover API and require it; Dialog builds on the native
<dialog> element. Positioning is computed in JavaScript, so CSS anchor
positioning is not used.
What's here#
The reference is grouped as the library grows:
- Overlays: Dialog, Popover, Tooltip, Menu, Context Menu, Select, Combobox, Toast.
- Building blocks: Listbox, the mid-level part set for command palettes and custom listboxes.
- Foundations: the shared primitives the components build on: the render-prop and ref helpers (renderElement, mergeRefs), controlled state (useControllableState), and the overlay building blocks for positioning, dismissal, and focus return (usePosition, useDismiss, useFocusReturn).
Conventions#
Every part follows the same two contracts, so what you learn on one component transfers to the rest.
Data attributes are the styling contract. Boolean states are
presence-style: the attribute is present (with an empty value) when the state
holds and absent otherwise, so CSS selects on [data-highlighted],
[data-selected], [data-disabled], [data-expanded], [data-swiping],
[data-front], [data-placeholder], or [data-empty] without comparing
values (in Tailwind, the bare data-highlighted: variant). The one valued
attribute is the open lifecycle enum data-state="open" | "closed", which
carries two states so exit transitions can target [data-state='closed'].
Positioning parts additionally reflect their resolved placement as
data-side and data-align.
Customization goes through render. Every part accepts a render prop
(see renderElement): a string retags the
element, a VNode is cloned with the part's props merged in, and a function
receives the merged props plus the part's state (Select.Option passes
{ selected, disabled, highlighted }, ContextMenu.Trigger passes
{ open }, and so on). children are plain content; parts do not take
children-as-function.