9 additions, 3 changes, and 4 fixes.
A surface that slides in from any edge and swipes away, built on Base UI's drawer primitive.
The vertical row primitive: a title with optional description, leading and trailing slots, a drill-in chevron, grouped sections with titles, and href rows that route through RoadieLinkProvider.
The Oztix logo in a fixed brand colour, with normal, mark and wordmark variants.
The application frame.
Gives any bounded region a consistent custom scrollbar.
A placeholder that holds the space content will occupy while it loads.
A short label that appears beside a control on hover or keyboard focus, built on Base UI's tooltip primitive.
hideLabel to Badge.It shrinks the badge to a dot, sized by size and painted by intent and emphasis, and keeps the label visually hidden so screen readers still announce it. It implies indicator, and indicatorPulse pulses the dot.
SeeBadge
Drawer, a surface that slides in from any edge and swipes away, built on Base UI's drawer primitive.Core gains the motion-drawer utility, which drives a drawer's edge transition and tracks Base UI's live swipe offset.
SeeDrawer
List, the vertical row primitive: a title with optional description, leading and trailing slots, a drill-in chevron, grouped sections with titles, and href rows that route through RoadieLinkProvider.A row's description is announced as its description rather than as part of its name, the leading and trailing slots carry data-slot, and List.GroupTitle is an <h2> whose level render changes, such as render={<h3 />}.
Logo, the Oztix logo in a fixed brand colour, with normal, mark and wordmark variants.product pairs the mark with a product name as live text, such as <Logo product='Studio' />, and a size prop (xs–xl, default md) scales the whole logo by its height. The lockup is always left to right, so right-to-left pages never mirror it.
SeeLogo
Navigator and Pane, the application frame.Navigator is one navigation model at every size: floating capsules down the
side from md, with a brand (the Oztix Logo by default), pinned items and an
optional expanded state with labels, and a floating tab bar on phones. An item
always links to its declared href, so tapping a top-level item goes to that
destination's root wherever you were inside it. Items declare placement and
visibilityPriority; whatever doesn't fit folds into a generated More pane. A
destination's pages open in a generated list pane declared with
Navigator.Secondary, optionally searchable, and an item can own a
Navigator.Menu instead. Navigator.Primary must be a direct child of
Navigator. Every other child of Navigator, parallel-route slots included,
renders inside the panes row, so a toaster or banner belongs outside
Navigator or in a Pane.
Pane is a scrolling column with sticky chrome, a collapse-on-scroll header
and a stack position when panes share a screen. A bare Pane is a detail
(column defaults to 'detail'), so give a root pane column='list'. tabBar
sets what the phone tab bar does while the pane is top, and depth is only for
a pane rendered out of document order. Roadie derives depth from render order
otherwise, on the server too. Navigator lays panes out as columns from its
own width (two from 46.25rem, three from 76rem) and stacks them below that. Full
columns need container style queries, in Chrome 111, Safari 18 and Firefox 151.
Older browsers get the top pane, with the root beside it from 46.25rem. A
stacked pane that mounts as the new top slides in like one that was already
there, so a route-driven detail pane animates on a push; a first
paint, hydration and reduced motion never slide. A pop moves the pane behind,
which slides back as the one above it is removed; the pane being left is not
animated out. Swapping a sibling cuts. A commit that replaces a pane with
another at the same depth, leaving the stack the shape it was, is not a push.
Switching top-level item cuts too, whatever stack the incoming route draws. A
Navigator.Secondary with overview draws every one of its routes in one
pane, so a step between its pages has no pane of its own to move. The page
being left is copied into an inert document and slid away while the arriving
one comes over it. That copy is the one in the frame, and only an overview
step makes one. Pane.Search is a pill search field with a Cancel.
Pane and Pane.Body each hold a Suspense boundary, so a suspension inside a
pane stops at the pane and its header stays on screen. Either boundary holds the frame's pending indicator
automatically while it waits, but a transition into a suspending child of the
same pane keeps the old content on screen instead of showing a fallback, so
that case reports nothing automatic; usePendingNavigation's start/stop
covers it, and pending on Pane covers a wait Roadie can't see at all, such
as a fetch without Suspense. A route's loading.tsx is optional; it only buys
Next's partial prefetch. The indicator itself is app-wide, one glow for the
whole frame. After 150ms with nothing changed yet, it fills with a slowly
turning gradient of three Oztix colours behind the panes and the nav, and on a
phone the panes pull back and round their corners to show it. It goes when the
destination lands, and a navigation faster than 150ms shows nothing.
RoadieLinkProvider marks a plain click on the internal href of any Roadie
surface that takes one, and takes pendingIndicator={false} to turn it off.
A pane takes its scroll down against the browser's own id for the history entry
it is on, so going back or forward through history puts every pane where it was.
Going forward, the pane the navigation arrives at starts at the top and the pane
it leaves keeps its place. The top of the stack is the deepest reached pane, so
the pane a route drilled from keeps its scroll. Scroll restoration reads no URL
and writes no history state. It reads navigation.currentEntry.key, and where an engine has no Navigation API panes
keep starting at the top.
Pane.Header keeps backHref as a real routed link, but a plain Back or Close
click now traverses browser history when the immediately previous
same-document entry matches its origin, path and query. That preserves the
parent's mounted state and avoids adding a duplicate parent entry. Direct loads,
reloads, unrelated history, modified clicks and browsers without the Navigation
API keep following the canonical link normally.
Also ships Navigator.ExpandToggle, Navigator.SecondaryPane and
Navigator.SecondaryItems, with useNavigatorSecondary for reading a
destination's items outside the generated pane. showList and showMore put
the list and More in the URL; expandedFromDocument pairs with
getNavigatorExpandedScript from @oztix/roadie-core/navigator.
Add ScrollArea, which gives any bounded region a consistent custom scrollbar.
SeeScrollArea
Skeleton, a placeholder that holds the space content will occupy while it loads.One component with a shape variant: text is a line at the inherited line height, block is a panel, circle is an avatar. Width and height come from Tailwind utilities, so a paragraph or a list row is several Skeletons in a grid. The root is aria-hidden and carries data-slot='skeleton'.
Core adds the --duration-ambient (1800ms) and --duration-sweep (2400ms)
tokens, the --sheen-shade and --sheen-highlight colours, the
animate-pulse-subtle utility, and animate-shimmer, which crosses a surface
with a highlight over that pulse. The highlight is anchored to the viewport, so
every element wearing the class shares one sweep whatever its size, and it is
the lighter of the two tones in both themes. Under prefers-reduced-motion the
highlight is dropped and the pulse resolves to a static tint.
SeeSkeleton
Tooltip, a short label that appears beside a control on hover or keyboard focus, built on Base UI's tooltip primitive.Tooltip.Content takes side, align and sideOffset directly, emphasis switches between the strong chip (the default; give Tooltip.Content an intent class to colour it) and the floating popover surface, and Tooltip.Provider groups tooltips so moving between neighbours is instant.
SeeTooltip
animate-pop-tap — a 200ms tap response, where animate-pop at 600ms reads as a notification.Add the navigator-expanded variant, which Navigator's expanded vertical
navigation is styled with, plus @oztix/roadie-core/navigator.
@oztix/roadie-core/navigator also exports getNavigatorExpandedScript, an
optional head script that lets a static site paint a persisted expanded vertical
navigation before hydration, with the cookie name it reads and a serializer to
write it.
Add is-translucent, which lets content show through a raised or floating
surface's fill under a backdrop blur. It pairs with emphasis-raised,
emphasis-floating or bg-raised, keeps their rim light and shadow, and falls
back to the solid fill without backdrop-filter support or under
prefers-reduced-transparency: reduce. On an is-interactive-field, the
field's hover, focus and invalid fills still win.
Accordion now publishes --content-inset (16px) and both its trigger and content read it, so content dropped into Accordion.Content lines up with the trigger without extra padding.Override the variable on the root to change both at once. In Safari, an open panel whose content changes size, such as a filtered list, now resizes with it instead of clipping.
SeeAccordion
react and react-dom peer ranges move from ^19.0.0 to ^19.2.0 in both packages.Upgrade React to 19.2 before taking this release. Roadie now uses useEffectEvent, which first shipped in React 19.2. The widgets' React peer stays optional, so Vue-only installs are unaffected.
animate-* plays now, once, as a keyframe animation; motion-* is state-driven enter/exit only, a transition on Base UI's data-starting-style / data-ending-style.Renamed the keyframe mount animations to match:
motion-fade-in → animate-fade-inmotion-scale-in → animate-scale-inmotion-pop-in → animate-pop-inmotion-fade-out and motion-scale-out are deprecated with no replacement —
use motion-scale or motion-slide for the exit instead.
All five old names remain as deprecated aliases until v3.
Button and IconButton with href render a link, not a button: Enter follows it, Space scrolls the page, and download is accepted.
Tabs.List that outgrows its container now scrolls sideways, with the scrollbar hidden, instead of overflowing the layout, and keeps the active tab in view.The subtler emphasis draws its focus ring inside the tab so the scrolling list doesn't clip it.
SeeTabs
roadie.compiled.css now ships motion-scale, motion-slide, animate-shake, animate-nudge and animate-pop, which the precompiled sheet had been dropping.
duration-* utilities set --tw-duration, so a variant-scoped transition-[…] keeps their duration, and they now ship in roadie.compiled.css.cn merges emphasis-field with the other emphasis presets.