Motion & View Transitions
kinu keeps motion in the platform: CSS transitions and animations for component state, and the native View Transitions API for larger changes like route swaps and list reorders. There is no animation runtime to ship.
Motion tokens
Easing lives in CSS custom properties so you can retune motion globally or per
component. The defaults are defined in kinu/style.css:
| Token | Use |
|---|---|
--k-ease |
the default easing (--k-ease-out) |
--k-ease-out |
enter/exit and most UI motion |
--k-ease-spring |
playful, slightly overshooting motion |
--k-ease-elastic |
pronounced overshoot for emphasis |
:root {
--k-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}
[k="accordion"][open] {
transition-duration: 200ms;
transition-timing-function: var(--k-ease-spring);
}
Always respect reduced-motion. The base stylesheet already neutralizes
animations under @media (prefers-reduced-motion: reduce); honor it in your own
overrides too.
The transition() helper
For DOM updates that should animate as a View Transition, wrap the update in
transition(). It calls document.startViewTransition where available and
falls back to a synchronous update otherwise — so it is always safe to use,
including during SSR.
import {transition} from 'kinu';
function navigate(next: string) {
transition(() => {
// mutate the DOM / set state synchronously here
setRoute(next);
});
}
Naming transitioned elements
Give elements a stable view-transition-name so the browser can morph them
between states (a thumbnail expanding into a hero image, a row moving in a
reordered list):
.card-hero {
view-transition-name: hero;
}
Only one element may carry a given view-transition-name at a time. For list
reorders, derive the name from the item's id.
Cross-document transitions (MPA)
For multi-page apps, opt into cross-document view transitions with a single at-rule — no JavaScript at all:
@view-transition {
navigation: auto;
}
The browser then animates same-origin navigations using any matching
view-transition-names on both pages.