Foundation

Motion

Motion is a tokenized interaction contract for hover, press, focus, overlays, disclosure, tabs, toasts, loading, feedback, and reduced-motion behavior.

Duration tokens

NameTokenValueUse
Instant--n-duration-instant80msReduced-motion and technical synchronization.
Fast--n-duration-fast140msPress, focus, and compact acknowledgement.
Normal--n-duration-normal220msHover, reveals, overlays, and feedback.
Slow--n-duration-slow360msPage-level reveals used sparingly.

Easing tokens

NameTokenValueUse
Standard--n-easing-standardcubic-bezier(0.2, 0, 0, 1)Default state changes.
Enter--n-easing-entercubic-bezier(0, 0, 0.2, 1)Content appearing.
Exit--n-easing-exitcubic-bezier(0.4, 0, 1, 1)Content leaving.
Expressive--n-easing-expressivecubic-bezier(0.16, 1, 0.3, 1)Success feedback and larger reveals.

Semantic motion

Semantic motion variables describe intent and point to duration and easing tokens. Component source should use these aliases instead of repeating raw timing values. Hover feedback always transitions with the semantic hover pair; instant timing is not used for ordinary pointer interaction.

Token
--n-motion-hover-duration
--n-motion-press-duration
--n-motion-focus-duration
--n-motion-reveal-duration
--n-motion-collapse-duration
--n-motion-overlay-enter-duration
--n-motion-overlay-exit-duration
--n-motion-page-enter-duration
--n-motion-data-refresh-duration
--n-motion-success-feedback-duration
--n-motion-error-feedback-duration

Tailwind motion recipes

motionClasses exposes complete, statically detectable Tailwind class strings. The former n-motion-* visual utility classes are not part of the post-migration contract.

NameTokenAuthoringUse
Interactive controlmotionClasses.interactiveStatic Tailwind recipeComposable hover, press, and focus transitions for actions.
Form controlmotionClasses.controlStatic Tailwind recipeComposable hover and focus transitions without press scaling.
HovermotionClasses.hoverStatic Tailwind recipeBackground, border, color, and opacity transitions.
PressmotionClasses.pressStatic Tailwind recipeSubtle press scale with reduced-motion fallback.
FocusmotionClasses.focusStatic Tailwind recipeFocus ring and border transitions.
Overlay entermotionClasses.overlayEnterStatic Tailwind recipeOpacity plus small translate/scale.
DisclosuremotionClasses.disclosureStatic Tailwind recipeHeight and opacity for open/close content.
Tab indicatormotionClasses.tabIndicatorStatic Tailwind recipeActive indicator movement.
SkeletonmotionClasses.skeletonStatic Tailwind recipeCalm loading pulse with reduced-motion fallback.

Optional Motion adapter

Install motion only when a composition needs presence, interruption, coordinated sequencing, gestures, or layout continuity that would make CSS state orchestration fragile. Nerio Core never imports Motion, and unrelated adapter subpaths do not resolve the optional peer.

pnpm add motion @nerio-ui/adapters
"use client";import {  NerioMotionConfig,  motionTransitions,  motionVariants,  useNerioReducedMotion,} from "@nerio-ui/adapters/motion";import { AnimatePresence, LazyMotion, domAnimation } from "motion/react";import * as m from "motion/react-m";export function Presence({ visible }: { visible: boolean }) {  return (    <NerioMotionConfig>      <LazyMotion features={domAnimation} strict>        <AnimatePresence initial={false}>          {visible ? (            <m.div              key="panel"              initial="hidden"              animate="visible"              exit="exit"              variants={motionVariants.fadeScale}              transition={motionTransitions.normal}            />          ) : null}        </AnimatePresence>      </LazyMotion>    </NerioMotionConfig>  );}

The adapter entrypoint is client-only. Keep the use client boundary at the smallest interactive composition. NerioMotionConfig always sets reducedMotion="user". Use initial={false} when server-rendered state is already visible so hydration does not replay an entrance. useNerioReducedMotion provides a server-stable snapshot and updates mounted compositions when the operating-system preference changes.

domAnimation covers variants, presence, and tap, hover, and focus gestures. Load domMax only for layout, pan, or drag capabilities. Strict mode catches an accidental full motion component inside a LazyMotion boundary; use m from motion/react-m there.

Focused examples

These examples keep animation restrained and expose stable end states for browser verification. They do not replace existing Core component motion.

Presence

A coordinated enter and exit that preserves a deterministic end state.

Release notes ready

Interruption

Rapid reversals continue from the current value instead of restarting.

Layout

The larger feature bundle is loaded only for layout continuity.

PlanBuildReview

Reduced motion

User preference removes transform travel while preserving opacity and state.

System motion active

Choose the smallest motion layer

LayerUse forAvoid when
CSS and TailwindHover, press, focus, color, opacity, small transforms, and reliable Base UI states.The change requires coordinated presence, interruption, or shared layout.
Optional Motion adapterPresence, interruption, layout continuity, gestures, and product-level sequences.A shared CSS recipe already expresses the complete interaction.
View Transitions APIBrowser-owned page or route transitions with stable old and new document states.The interaction is gesture-driven or needs element-level interruption.

Reduced motion

PreferenceBehaviorExamples
DefaultCore components use short durations and avoid layout-heavy motion.Hover, focus, overlays, and skeleton loading resolve through CSS variables.
Reduced motionLarge movement collapses to opacity or immediate state changes.Press scale, overlay translation, and repeated skeleton movement are removed or minimized.

Usage

import { cn, motionClasses } from "@nerio-ui/ui";<button  type="button"  className={cn(    "rounded-n-control border border-n-border bg-n-surface px-n-4 py-n-2 text-n-text focus-visible:outline-0 focus-visible:shadow-(--n-focus-ring)",    motionClasses.interactive,  )}>  Save changes</button>
  • Use shared motion recipes before adding component-specific Tailwind transitions.
  • Keep Core motion subtle; expressive motion belongs in product compositions and Pro examples.
  • Do not add animation libraries for basic hover, focus, overlay, or loading behavior.

Source installation and removal

pnpm add motionpnpm nerio add motion-adapterimport {  NerioMotionConfig,  motionTransitions,  motionVariants,  useNerioReducedMotion,} from "@/components/nerio/lib/motion-adapter";

Removing the adapter does not change Core components: replace Motion compositions with CSS recipes or static end states, remove the copied adapter file, then uninstall motion. No hidden provider or Core migration is required.