@hozo/behaviors
v0.2.0
Published
Universal runtime behaviors substrate (LiveRegion, Portal, DismissableLayer, FocusScope, RovingFocus, FloatingPositioner) for Hozo.
Downloads
396
Maintainers
Readme
@hozo/behaviors
Universal headless runtime behaviors and positioning primitives for Hozo.
These primitives provide the essential interaction mechanics — focus management, outside click handling, keyboard navigation, collision-aware floating positioning, disclosure states, phonetic reading control, and hover delay groups — on both Web and React Native.
Included Behaviors
1. Hover & Tooltip Mechanics
useHoverTrigger: Headless hook managing hover, keyboard focus, Escape dismissal, and mobile long-press triggers. Monitors pointer movement against safe polygons to avoid flickering.TooltipGroupProvider/useTooltipGroup: Warmup and cooldown delay state machine for sibling tooltips (e.g. toolbars). Opens with an intentional delay (openDelay, default 700ms) on first hover, then switches instantly (0ms) between adjacent tools until the cooldown timer (skipDelayDuration, default 300ms) expires.computeSafePolygon/isPointInPolygon: Pure ray-casting geometric calculation creating a dynamic safe bridge between the pointer on the trigger and the floating content rectangle (e.g. HoverCards with buttons), allowing diagonal cursor travel without accidental dismissals.@hozo/patternsTooltipcomposes these headless pieces and owns the rendered widget.
2. Focus & Keyboard Management
FocusScope: Universal focus containment (tab trapping), initial auto-focus target resolution, and focus restoration to opener element on unmount.RovingFocusGroup/useRovingItem: WAI-ARIA rovingtabIndexmanager for toolbars, menus, tablists, radio groups, and tree views, supporting horizontal/vertical orientations and wrap-around.useTypeahead: Predictive keyboard navigation matching query prefixes with loop prevention and reset timeout.
3. Layers, Portals & Dismissals
DismissableLayer: Outside pointerdown/press dismissal and Escape key handling with proper nested stacking order.Portal/PortalHost/PortalProvider: Universal React Portal rendering across Web DOM (document.bodyor custom node) and React Native root hierarchies with siblinginertcoordination.- Dialog foundations: focus scope, dismissable layers, and portals remain here; the rendered
Dialog/HozoDialogcomponent is owned by@hozo/patterns.
4. Floating Anchoring & Positioning
FloatingPositioner/useFloatingPosition: Zero-dependency floating positioning supporting 12 placements, auto-flip, shift overflow boundary constraints, arrow offset clamping,matchAnchorWidthfor selects, andreferenceHiddentracking.
5. Screen Reader Announcements
LiveRegion/useAnnounce: Universal polite and assertive screen reader live announcements with queued vocalization.
Usage Example
import { useState } from 'react'
import {
FloatingPositioner,
DismissableLayer,
FocusScope,
Portal,
useHoverTrigger,
} from '@hozo/behaviors'
export function HoverPreview() {
const [open, setOpen] = useState(false)
const { triggerProps, contentProps } = useHoverTrigger({
open,
onOpenChange: setOpen,
openDelay: 400,
closeDelay: 200,
})
return (
<>
<button type="button" {...triggerProps}>
Hover or Focus me
</button>
{open && (
<Portal>
<DismissableLayer onDismiss={() => setOpen(false)}>
<FocusScope trapFocus={false}>
<FloatingPositioner placement="top">
<div {...contentProps}>Accessible contextual card</div>
</FloatingPositioner>
</FocusScope>
</DismissableLayer>
</Portal>
)}
</>
)
}Part of Hozo, a Rust-powered universal UI compiler and accessibility-first layer for React Native. Most applications install @hozo/core and one build integration; see Getting started. Source and issues: github.com/iray-tno/hozo.
