Ornament
Floating navigation rail that auto-expands on hover or focus to reveal labels alongside icons.
Import
import { Ornament, useOrnament } from '@/components/ornament'Anatomy
The module exposes one namespace object. Ornament is the root provider — it owns orientation plus the shared isFocused / isPressed state that the rail uses to drive its expand-on-focus animation. All visual leaves are flat siblings on the namespace.
<Ornament orientation="vertical">
<Ornament.Tabs>
<Ornament.Tab isActive>
<Ornament.TabIcon icon={<HomeIcon data-slot="icon" />} />
<Ornament.TabLabel>Home</Ornament.TabLabel>
</Ornament.Tab>
<Ornament.Tab>
<Ornament.TabIcon icon={<PeopleIcon data-slot="icon" />} />
<Ornament.TabLabel>People</Ornament.TabLabel>
</Ornament.Tab>
</Ornament.Tabs>
</Ornament>- Ornament / Ornament.Root: Headless provider. Holds
orientation,isFocused, andisPressedand renders no DOM of its own. - Ornament.Tabs: The frosted
Surfacethat contains tabs. Renders withrole="tablist", animates betweencollapsedandexpandedmotion variants, and lays children out as a row or column based onorientation. - Ornament.Tab: An interactive
Buttonstyled for the rail. Wires its focus and press handlers into the provider so the surface can react. PassisActiveto render the selected style. - Ornament.TabIcon: Wrapper around the leading icon. Pass any node via the
iconprop; child icons should setdata-slot="icon"so the built-in size/opacity rules apply. - Ornament.TabLabel: Trailing text revealed when the rail is expanded. Strings are rendered with the standard line-clamped style; nodes are passed through untouched.
- useOrnament: Hook for advanced consumers (e.g. a custom tab implementation outside the visual frame) that need to read
orientationor driveisFocused/isPressedthemselves.
Usage
Orientation
orientation controls both the rail layout (column vs row) and the surface track direction. Default is vertical.
<Ornament orientation="horizontal">
<Ornament.Tabs>
<Ornament.Tab>
<Ornament.TabIcon icon={<SearchIcon data-slot="icon" />} />
<Ornament.TabLabel>Search</Ornament.TabLabel>
</Ornament.Tab>
</Ornament.Tabs>
</Ornament>Active state
isActive flips the underlying Button variant from secondary to default and exposes data-active="true" on the element for downstream styling.
<Ornament.Tab isActive>
<Ornament.TabIcon icon={<EnvironmentsIcon data-slot="icon" />} />
<Ornament.TabLabel>Environments</Ornament.TabLabel>
</Ornament.Tab>Custom labels
Ornament.TabLabel accepts strings (rendered with the default truncation style) or arbitrary nodes (rendered as-is) so you can add badges, counters, or shortcuts.
<Ornament.TabLabel>
<span className="flex items-center gap-2">
Inbox
<span className="rounded-full bg-white/20 px-2 text-xs">12</span>
</span>
</Ornament.TabLabel>Driving state from outside the rail
When something outside the visible frame needs to reflect rail focus or press state, read it from the provider with useOrnament.
import { useOrnament } from '@/components/ornament'
function OrnamentShadow() {
const { isFocused } = useOrnament()
return <div data-focused={isFocused} />
}Example
import { Ornament } from '@/components/ornament'
import { AppStoreIcon, EnvironmentsIcon, PeopleIcon } from '@/components/icons'
export default function OrnamentExample() {
return (
<Ornament>
<Ornament.Tabs>
<Ornament.Tab isActive>
<Ornament.TabIcon icon={<AppStoreIcon data-slot="icon" />} />
<Ornament.TabLabel>Home</Ornament.TabLabel>
</Ornament.Tab>
<Ornament.Tab>
<Ornament.TabIcon icon={<PeopleIcon data-slot="icon" />} />
<Ornament.TabLabel>People</Ornament.TabLabel>
</Ornament.Tab>
<Ornament.Tab>
<Ornament.TabIcon icon={<EnvironmentsIcon data-slot="icon" />} />
<Ornament.TabLabel>Environments</Ornament.TabLabel>
</Ornament.Tab>
</Ornament.Tabs>
</Ornament>
)
}API Reference
Ornament (Ornament.Root)
The callable Ornament is Ornament.Root — a headless provider. It only forwards its children inside the context.
Prop
Type
Ornament.Tabs
Renders the frosted rail surface (role="tablist"). Accepts standard React.HTMLAttributes<HTMLDivElement> in addition to children. Layout follows orientation from the root.
Ornament.Tab
Renders a styled Button. Beyond the table below, the tab forwards normal <button> HTML attributes (onClick, disabled, aria-*, className, etc.). Focus and pointer handlers are composed with the provider's internal handlers, so user-supplied callbacks still fire.
Prop
Type
Ornament.TabIcon
Wraps the leading icon. Beyond the table below, it accepts standard React.HTMLAttributes<HTMLDivElement> (className, style, etc.).
Prop
Type
Ornament.TabLabel
Trailing label revealed when the rail expands.
Prop
Type
useOrnament
Hook for reading the rail context. Throws when called outside an <Ornament> root.
Prop
Type