Composition
How primitives compose: attribute forwarding, the controlled/uncontrolled pattern, the Slot escape hatch, cancelable events, and direction.
Forwarding attributes
Every part declares [Parameter(CaptureUnmatchedValues = true)] and splats it with @attributes. Anything you pass that isn't a declared parameter (class, style, data-*, aria-*, event handlers) flows onto the underlying element.
Controlled & uncontrolled
Stateful primitives support both modes. Controlled: pass the value parameter plus its …Changed callback (use @bind-). Uncontrolled: pass the Default… parameter and let the primitive own its state. Whether a component is controlled is decided by whether the value parameter was set, not by whether a callback is attached.
<NaviusSwitch @bind-Checked="_on" />
@code { private bool _on; }<NaviusSwitch DefaultChecked="true" />Slot (asChild)
React's asChild merges a part's behaviour onto an arbitrary child. Razor render fragments are opaque, so Navius offers NaviusSlot as the closest equivalent: it forwards the part's props/attributes onto your child element rather than rendering its own. This is the one honest deviation from the original asChild model; see the Slot utility.
Cancelable events
Overlays expose cancelable lifecycle callbacks: OnEscapeKeyDown, OnPointerDownOutside, OnInteractOutside, OnOpenAutoFocus, OnCloseAutoFocus. Each event arg carries PreventDefault(); call it to keep the overlay open or to manage focus yourself.
<NaviusDialogPopup OnEscapeKeyDown="e => e.PreventDefault()">
@* Escape no longer closes the dialog *@
</NaviusDialogPopup>Direction
Wrap your app (or a subtree) in NaviusDirectionProvider to set the reading direction. It is DOM-transparent and cascades to direction-aware parts (roving focus, sliders, scroll areas) so arrow keys and layout respect RTL.
<NaviusDirectionProvider Dir="rtl">
<App />
</NaviusDirectionProvider>