Motion
@simurgh-ui/motion adds purposeful animation without changing the default behavior of Simurgh
components. Durations and delays use seconds. The engine uses the Web Animations API and imports
safely during server rendering.
pnpm add @simurgh-ui/motionLive examples
Section titled “Live examples”These examples use the React adapter, but the motion definitions are shared by every adapter. They
cover transform keyframes, spring gestures, enter and exit presence, staggered children, viewport
intersection, and an explicit reduced-motion setting. The default reducedMotion: "user" setting
automatically removes duration when the operating system requests reduced motion.
Keyframes
Combine transform and opacity arrays in one timeline.
Spring gestures
Hover, focus, or press the button.
Presence
Staggered children
- Plan
- Build
- Verify
In-view motion
Elements animate when they intersect the viewport.
Reduced motion
Product settings can override the operating-system preference.
Use gesture states for immediate feedback, Presence when removed content needs an exit animation,
and stagger on a parent definition to sequence bound children. Motion should reinforce a state
change; it should not delay focus, validation, or access to content.
Transform keyframes
Section titled “Transform keyframes”Transform shorthands accept a single value or an array. Arrays with different lengths are sampled
across the same timeline, and numeric x, y, and rotate values receive pixel and degree units.
const celebration = { opacity: [0, 1, 1, 1], scale: [0.8, 1.08, 0.96, 1], rotate: [0, 8, -5, 0],};
animate(element, celebration, { duration: 0.65, easing: 'ease-in-out',});Interface patterns
Section titled “Interface patterns”The same primitives can produce application-level effects without a special component for every pattern. These examples adapt common animation ideas—typewriter text, staggered character reveal, accordion reveal, loading shimmer, a timeline sequence, and SVG path drawing—to Simurgh’s smaller API.
Typewriter
Character reveal
Accordion reveal
Skeleton shimmer
Timeline sequence
SVG path drawing
The accordion preserves aria-expanded and its controlled-region relationship. The loading bars
are hidden from assistive technology, while the SVG retains an accessible name. Treat those
semantics as part of the example rather than decoration to remove when copying it.
Choreographed keyframes
Section titled “Choreographed keyframes”These GSAP-inspired examples synchronize several property tracks to create an orbital path, a repeating marquee, and a shape-and-color transformation. They use ordinary keyframe arrays, so no plugin or browser-global setup is required.
An x array and a y array with matching lengths approximate a path through a series of points.
This is useful for small decorative routes; use a dedicated path engine when an object must follow
an arbitrary SVG curve precisely. Repeated motion still follows the configured reduced-motion mode.
Core API
Section titled “Core API”import { animate, sequence } from '@simurgh-ui/motion';
const controls = animate( card, { opacity: [0, 1], y: [8, 0] }, { type: 'spring', stiffness: 180, damping: 24, },);
await sequence([ [heading, { opacity: [0, 1] }], [actions, { opacity: [0, 1], y: [4, 0] }, { delay: 0.04 }],]).finished;
controls.pause();controls.play();controls.cancel();import { animated, Presence } from '@simurgh-ui/motion/react';import { Button } from '@simurgh-ui/react/button';
const itemMotion = { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, whileHover: { scale: 1.02 }, whilePress: { scale: 0.98 }, exit: { opacity: 0, y: -4 },};
<Presence exit={itemMotion}> {open && ( <animated.div key="panel" motion={itemMotion}> <Button>Save</Button> </animated.div> )}</Presence>;useMotion(definition) returns an element ref and controls for cases where a wrapper is not useful.
<script setup lang="ts">import { Motion, Presence } from '@simurgh-ui/motion/vue';const panel = { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 },};</script>
<Presence :exit="panel"><Motion v-if="open" :motion="panel"><button>Save</button></Motion></Presence>Use v-motion="definition" or useMotion(definition) when an extra component is undesirable.
Angular
Section titled “Angular”import { SimurghMotionDirective, SimurghPresence,} from '@simurgh-ui/motion/angular';
@Component({ imports: [SimurghMotionDirective, SimurghPresence], template: `<simurgh-presence [present]="open" [motion]="panel"> <section [simurghMotion]="panel">Content</section> </simurgh-presence>`,})export class Example { open = true; panel = { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, };}Variants, gestures, and in-view motion
Section titled “Variants, gestures, and in-view motion”Definitions accept named variants and the states whileHover, whilePress, whileFocus, and
whileInView. A state may contain keyframes directly or name a variant. Delays and stagger are
expressed in seconds.
Stagger a group
Section titled “Stagger a group”Bind a motion definition to both the parent and its children. The parent adds its stagger delay to
each child in document order.
const list = { animate: { opacity: 1 }, stagger: 0.3 };const item = { initial: { opacity: 0, x: -12 }, animate: { opacity: [0, 1], x: [-18, 0] }, transition: { duration: 0.45 },};
<animated.ul motion={list}> {items.map((label) => ( <animated.li key={label} motion={item}>{label}</animated.li> ))}</animated.ul>Animate an existing element
Section titled “Animate an existing element”Use useMotion when adding an animated.* wrapper would change markup or component semantics.
import { useMotion } from '@simurgh-ui/motion/react';
function StatusMessage() { const { ref, controls } = useMotion<HTMLParagraphElement>({ initial: { opacity: 0 }, animate: { opacity: 1 }, });
return ( <p ref={ref}> Saved <button type="button" onClick={() => controls.current?.play()}> Replay </button> </p> );}Reduced motion and accessibility
Section titled “Reduced motion and accessibility”The default reducedMotion: "user" follows prefers-reduced-motion. Use "always" for a product
setting that disables motion and "never" only for a necessary, non-spatial state transition.
Reduced motion removes delays and repeats. Never delay focus, dismissal, or validation feedback
until decorative animation finishes.
The CSS package exposes --simurgh-duration-fast, --simurgh-duration,
--simurgh-duration-slow, --simurgh-ease-standard, and --simurgh-ease-emphasized.
Last verified on 2026-08-13 against Simurgh registry 0.1.1.