Animation
A collection of pure CSS entrance animations with WCAG 2.2 accessibility support.
Installation
npx vayu-ui init #one time onlynpx vayu-ui add animationnpx vayu-ui add -t animation #with test case needsUsage
<Animation.Fade>
<div className="bg-indigo-500 rounded-md p-4 text-white">Fading in</div>
</Animation.Fade>
<Animation.Slide direction="left">
<div className="bg-blue-500 rounded-md p-4 text-white">Sliding from left</div>
</Animation.Slide>
<Animation.Bounce scale="large">
<div className="bg-yellow-500 rounded-md p-4 text-black">Bouncing in</div>
</Animation.Bounce>
<Animation.Flip direction="up">
<div className="bg-purple-500 rounded-md p-4 text-white">Flipping on X-axis</div>
</Animation.Flip>
<Animation.Rotate degrees={180}>
<div className="bg-red-500 rounded-md p-4 text-white">Rotating 180 degrees</div>
</Animation.Rotate>
<Animation.Zoom scale="medium">
<div className="bg-green-500 rounded-full p-4 text-white">Zooming in</div>
</Animation.Zoom>
<Animation.Roll direction="right">
<div className="bg-pink-500 rounded-md p-4 text-white">Rolling in</div>
</Animation.Roll>
<Animation.JackInTheBox>
<div className="bg-teal-500 rounded-md p-4 text-white">Jack in the box</div>
</Animation.JackInTheBox>
<Animation.Hinge duration="slower">
<div className="bg-orange-500 rounded-md p-4 text-white">Hinge effect</div>
</Animation.Hinge>
<Animation.Bounce iteration="infinite">
<div className="bg-cyan-500 rounded-full p-4 text-white">Infinite loop</div>
</Animation.Bounce>Anatomy
import { Animation } from 'vayu-ui';
// Fade — simple opacity transition
<Animation.Fade duration="normal" delay="none">
{children}
</Animation.Fade>
// Slide — directional entrance
<Animation.Slide direction="left" duration="fast">
{children}
</Animation.Slide>
// Bounce — scale-based entrance
<Animation.Bounce scale="medium" iteration={2}>
{children}
</Animation.Bounce>
// Flip — axis-based rotation entrance
<Animation.Flip direction="up">
{children}
</Animation.Flip>
// Rotate — custom degree rotation
<Animation.Rotate degrees={-200}>
{children}
</Animation.Rotate>
// Zoom — scale-based entrance
<Animation.Zoom scale="large">
{children}
</Animation.Zoom>
// Roll — rolling entrance with direction
<Animation.Roll direction="left">
{children}
</Animation.Roll>
// JackInTheBox — playful spring entrance
<Animation.JackInTheBox>
{children}
</Animation.JackInTheBox>
// Hinge — element swings and falls
<Animation.Hinge duration="slower">
{children}
</Animation.Hinge>- Animation.Fade — Smooth opacity transition from invisible to visible.
- Animation.Slide — Translates the element in from a specified direction.
- Animation.Bounce — Scales in with an elastic bounce effect.
- Animation.Flip — Rotates the element on the X or Y axis.
- Animation.Rotate — Rotates the element by a custom number of degrees.
- Animation.Zoom — Scales the element from a smaller or larger size.
- Animation.Roll — Rolls the element in from a specified direction.
- Animation.JackInTheBox — Playful spring-loaded entrance animation.
- Animation.Hinge — Element swings and falls off the page.
Accessibility
- Reduced Motion Support:
- Respects the OS-level
prefers-reduced-motion: reducesetting via Tailwind'smotion-reduce:CSS variant. - When enabled, animations are suppressed and content is rendered with
opacity: 1viamotion-reduce:opacity-100to ensure visibility. - A global CSS rule (
@media (prefers-reduced-motion: reduce) { * { animation: none !important } }) provides an additional safety net. - Fully compliant with WCAG 2.2 Success Criterion 2.3.3 (Animation from Interactions).
- Respects the OS-level
- CSS-Only Approach:
- Animations are purely visual decorations applied via CSS classes. No ARIA roles or live regions are needed.
- Content inside animation wrappers remains fully accessible to assistive technologies regardless of animation state.
- Server Components:
- All animation components are React Server Components — no client-side JavaScript is required for rendering or accessibility support.
- No Focus Impact:
- Animations do not trap or steal focus. Interactive elements inside animation wrappers maintain normal tab order and focus behavior.
Screen reader behavior
Animation components are decorative CSS wrappers. Screen readers announce the content inside the animation as-is, without referencing the animation effect. When prefers-reduced-motion is enabled, animations are silently disabled via CSS and content renders immediately. Since animations do not convey meaning or state, no additional ARIA attributes are applied. Users who rely on assistive technology receive the same content without any loss of information.
Component Folder Structure
Animation/
├── Animation.tsx # Root component with compound composition
├── FadeAnimation.tsx # Fade variant
├── SlideAnimation.tsx # Slide variant (directional)
├── BounceAnimation.tsx # Bounce variant (scale-based)
├── FlipAnimation.tsx # Flip variant (axis-based)
├── RotateAnimation.tsx # Rotate variant (degree-based)
├── ZoomAnimation.tsx # Zoom variant (scale-based)
├── RollAnimation.tsx # Roll variant (directional)
├── JackInTheBoxAnimation.tsx # JackInTheBox variant
├── HingeAnimation.tsx # Hinge variant
├── types.ts # TypeScript type definitions and mappings
├── utils.ts # buildAnimationClasses utility
├── index.ts # Re-exports all components and types
└── README.md # Component usage referenceProps
Common Props (All Variants)
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Content to animate. |
duration | 'slower' | 'slow' | 'normal' | 'fast' | 'faster' | 'normal' | Animation duration. |
delay | 'none' | 'short' | 'medium' | 'long' | 'none' | Delay before animation starts. |
iteration | 1 | 2 | 3 | 'infinite' | 1 | Number of times the animation repeats. |
fillMode | 'none' | 'forwards' | 'backwards' | 'both' | 'none' | How styles are applied before and after animation. |
className | string | — | Additional CSS classes. |
Animation.Fade
Uses common props only. No additional props.
Animation.Slide
| Prop | Type | Default | Description |
|---|---|---|---|
direction | 'up' | 'down' | 'left' | 'right' | 'left' | Direction the element slides in from. |
Plus all Common Props.
Animation.Bounce
| Prop | Type | Default | Description |
|---|---|---|---|
scale | 'small' | 'medium' | 'large' | 'medium' | Intensity of the bounce effect. |
Plus all Common Props.
Animation.Flip
| Prop | Type | Default | Description |
|---|---|---|---|
direction | 'up' | 'down' | 'left' | 'right' | 'up' | Flip direction. up/down flip on X-axis, left/right flip on Y-axis. |
Plus all Common Props.
Animation.Rotate
| Prop | Type | Default | Description |
|---|---|---|---|
degrees | number | -200 | Starting rotation angle in degrees. |
Plus all Common Props.
Animation.Zoom
| Prop | Type | Default | Description |
|---|---|---|---|
scale | 'small' | 'medium' | 'large' | 'medium' | Starting scale intensity. |
Plus all Common Props.
Animation.Roll
| Prop | Type | Default | Description |
|---|---|---|---|
direction | 'up' | 'down' | 'left' | 'right' | 'left' | Direction the element rolls in from. |
Plus all Common Props.
Animation.JackInTheBox
Uses common props only. No additional props.
Animation.Hinge
Uses common props only, but defaults fillMode to 'forwards' instead of 'none' so the element remains visible after the animation completes.