Theming / Motion
Motion
Six touch points in zits/ui forward plain class strings from Navius.Motion: a shake on ZitsFieldError, a shimmer on ZitsSkeleton, a pulse on ZitsBadge, and a presence class on the three overlay contents (ZitsDialogContent, ZitsAlertDialogContent, ZitsPopoverContent). None of it depends on the Navius.Motion assembly: every opt-in is a raw class name, inert until the app links the stylesheet below. This preview is the real components running in WebAssembly.
Setup
The six opt-ins below already ship with every navius add copy: the params exist whether or not the stylesheet is linked, they just render byte-identical output when it is not. Two steps light them up.
1. Reference the Navius.Motion preview package from your app:
dotnet add package Navius.Motion --prerelease2. Link the generated stylesheet in your app shell, the same way app.css is linked:
<link href="_content/Navius.Motion/navius-motion.css" rel="stylesheet" />That is the whole install. No component code changes: the params are already there, waiting.
Micro pack opt-ins
Bool params, default off. Each forwards one motion-* class through the component's existing Cn.Class merge. Click "Trigger error" to feel the shake fire on mount. ZitsSkeleton.Shimmer is a separate mechanism from the Shimmer text component: this one swaps the skeleton's animation, that one paints a text-clip sweep.
<ZitsField data-invalid="true">
<ZitsFieldLabel For="pw">Password</ZitsFieldLabel>
<ZitsInput id="pw" type="password" aria-invalid="true" />
<ZitsFieldError Shake="true">Password must be at least 8 characters.</ZitsFieldError>
</ZitsField>
<ZitsBadge Pulse="true">Live</ZitsBadge>
<ZitsSkeleton Shimmer="true" class="h-4 w-[200px]" />| Prop | Type | Default |
|---|---|---|
| ZitsFieldError.Shake | bool | false |
| ZitsSkeleton.Shimmer | bool | false (swaps the default animate-pulse, not additive) |
| ZitsBadge.Pulse | bool | false |
Presence hooks
A single string? Motion param, default null, on the three overlay contents. It lands on the underlying Base UI popup, the part that carries the data-open, data-closed, data-starting-style, and data-ending-style attributes the presence classes key off. Raw class string, not a mirrored enum: it forwards without helm encoding any Navius class-name knowledge.
<ZitsDialog>
<ZitsDialogTrigger>Open dialog</ZitsDialogTrigger>
<ZitsDialogContent Motion="motion-pop">
<ZitsDialogHeader>
<ZitsDialogTitle>Edit profile</ZitsDialogTitle>
</ZitsDialogHeader>
</ZitsDialogContent>
</ZitsDialog>| Prop | Type | Default |
|---|---|---|
| ZitsDialogContent.Motion | string? | null |
| ZitsAlertDialogContent.Motion | string? | null |
| ZitsPopoverContent.Motion | string? | null |
Preset classes
Every class the stylesheet generates, usable directly (splat one onto any markup, wired opt-in or not). Durations and easings are baked spring linear() curves, so they run on the compositor with zero JavaScript.
Presence (pair with an element carrying the Navius state attributes; this is what the Motion param above accepts):
| Prop | Type | Default |
|---|---|---|
| motion-fade | class | opacity only |
| motion-fade-up | class | fade, enters from 8px below |
| motion-fade-down | class | fade, enters from 8px above |
| motion-zoom | class | fade plus a 0.95 to 1 scale |
| motion-pop | class | bouncy spring, fade plus a 0.9 to 1 scale |
| motion-slide-up | class | enters from 24px below |
| motion-slide-down | class | enters from 24px above |
| motion-slide-left | class | enters from 24px right |
| motion-slide-right | class | enters from 24px left |
Enter-once (animates on insertion via @starting-style, no state attributes needed, delay with --navius-motion-delay):
| Prop | Type | Default |
|---|---|---|
| motion-enter-fade | class | opacity only |
| motion-enter-fade-up | class | fade, enters from 8px below |
| motion-enter-fade-down | class | fade, enters from 8px above |
| motion-enter-zoom | class | fade plus a 0.95 to 1 scale |
| motion-enter-pop | class | bouncy spring, fade plus a 0.9 to 1 scale |
| motion-enter-slide-up | class | enters from 24px below |
| motion-enter-slide-down | class | enters from 24px above |
| motion-enter-slide-left | class | enters from 24px right |
| motion-enter-slide-right | class | enters from 24px left |
Scroll-reveal (starts hidden, transitions to visible once [data-in-view] is set on the element; pair with Motion.InView to splat the class and CreateInViewAsync to attach the observer that sets the attribute, stagger a group with --navius-motion-delay per child):
| Prop | Type | Default |
|---|---|---|
| motion-in-view-fade | class | opacity only |
| motion-in-view-fade-up | class | fade, enters from 8px below |
| motion-in-view-fade-down | class | fade, enters from 8px above |
| motion-in-view-zoom | class | fade plus a 0.95 to 1 scale |
| motion-in-view-pop | class | bouncy spring, fade plus a 0.9 to 1 scale |
| motion-in-view-slide-up | class | enters from 24px below |
| motion-in-view-slide-down | class | enters from 24px above |
| motion-in-view-slide-left | class | enters from 24px right |
| motion-in-view-slide-right | class | enters from 24px left |
Gesture and micro pack (the micro classes back the bool opt-ins above; motion-focus-glow has no wired param yet, add it directly):
| Prop | Type | Default |
|---|---|---|
| motion-press | class | scale down on :active, keyboard activation included |
| motion-hover | class | lift on hover, hover-capable pointers only |
| motion-shake | class | one-shot decaying nudge, backs ZitsFieldError.Shake |
| motion-pulse | class | looped opacity/scale breathing, backs ZitsBadge.Pulse |
| motion-shimmer | class | looped sweep, backs ZitsSkeleton.Shimmer |
| motion-focus-glow | class | looped hairline ring pulse, no wired param |
New in the motion package
Beyond the class strings above, Navius.Motion ships four package-level components: an auto-animate container (NaviusAutoAnimate, FLIP on child add, remove, or reorder), a fluent multi-element timeline builder (MotionSequence), a spring-driven selection indicator (NaviusSelectionIndicator), and an experimental same-document page transition wrapper (NaviusPageTransition). None of them are wired into a helm component yet, so this site does not carry API tables for them. They are documented on navius-docs, the primitives docs site.
Reduced motion
Handled once, in the stylesheet, under a single @media (prefers-reduced-motion: reduce) block. No per-component code needed on the zits/ui side.
- Every presence and enter-once preset collapses to an opacity-only transition; the transform is dropped.
motion-pressandmotion-hoverdrop their transform on interaction, so pressing or hovering no longer moves anything.motion-shake,motion-shimmer, andmotion-focus-glowstop outright (all transform, background-position, or box-shadow driven, nothing left to show under reduce).motion-pulsekeeps a plain opacity beat: it still reads as "live" without the scale, so it stays non-vestibular rather than vanishing.