Motion

Timing, easing, and animation tokens for consistent micro-interactions.

Overview

Byteion defines motion tokens for transition durations, easing curves, and 16 named keyframe animations. Every interactive component uses these tokens for hover, focus, open, close, loading, validation, selection, and feedback interactions.

Motion is used across SaaS dashboards, admin panels, ERP and POS tools, ecommerce back offices, internal tools, forms, modals, dropdowns, toasts, tabs, skeleton loaders, and command palettes. Transitions are intentionally subtle — Byteion is designed for data-heavy product interfaces where clarity matters more than flourish.

When to use motion

  • Use fast transitions for hover, focus, toggles, and small state changes.
  • Use default transitions for buttons, inputs, tabs, dropdowns, and tooltips.
  • Use slow transitions for overlays, modals, drawers, and large panels.
  • Use animate-shimmer for loading placeholders and skeleton screens.
  • Use animate-shake only for validation errors or failed actions.
  • Use animate-check-pop or animate-scale-spring for confirmation or selection feedback.

When not to use motion

  • Do not animate every card, row, or table cell in dense dashboards — it creates visual noise.
  • Do not delay critical data visibility with slow entrance animations.
  • Do not use spring or bouncy animations for serious admin workflows — they feel playful, not trustworthy.
  • Do not use motion as the only feedback for errors or success — always pair with text and colour.
  • Do not repeatedly shake inputs after every keystroke — one shake on submission is enough.
  • Do not use decorative motion that competes with task completion — motion should serve the interaction.

Duration

Duration tokens control transition speed. The default transition applies when no explicit duration-* class is used:

TokenTailwind classValueUse case
instantduration-instant0msImmediate state changes, no visible transition
fastduration-fast120msMicro-interactions, toggles
normal (default)duration-normal200msDefault transitions — buttons, inputs, tabs
slowduration-slow320msOverlay open/close, slide, drawer
slowerduration-slower500msLarge panel transitions, page-level entrances

Easing

Easing tokens control the acceleration curve of transitions and animations. The default easing applies when no explicit ease-* class is used:

TokenTailwind classCurveBest forAvoid for
defaultease-defaultcubic-bezier(0.4, 0, 0.2, 1)General UI transitionsExpressive animations
out-softease-out-softcubic-bezier(0.22, 1, 0.36, 1)Entrances, overlays, smooth decelerationError feedback, alerts
springease-springcubic-bezier(0.34, 1.56, 0.64, 1)Celebratory or selection feedbackDense enterprise tables, admin workflows
in-softease-in-softcubic-bezier(0.55, 0, 0.68, 0.06)Exit transitions, dismissalsEntrance or reveal animations
outease-outcubic-bezier(0, 0, 0.2, 1)Clean exits, quick dismissalsEmphasis or spring-like reveals
inease-incubic-bezier(0.4, 0, 1, 1)Fast entrances that finish at full speedOverlay reveals, soft transitions
in-outease-in-outcubic-bezier(0.4, 0, 0.2, 1)Symmetrical state changes (same as default)Cases where asymmetric timing is preferred

Keyframe animations

Byteion includes 16 named keyframe animations available via Tailwind animate-* classes. Each is tuned for a specific interaction pattern:

ClassPurposeBest component usage
animate-fade-inSubtle content revealTabs, panels, command palettes
animate-fade-outSubtle content hideTooltips, dismissible alerts
animate-slide-upContent slides up and fades inToast, bottom sheet, popover
animate-slide-downContent slides down and fades inDropdown menu, select options
animate-slide-in-rightContent slides in from rightDrawer (right), sidebar panel
animate-slide-in-leftContent slides in from leftDrawer (left), nav sidebar
animate-slide-in-bottomContent slides up from belowMobile bottom sheet, notification panel
animate-slide-in-topContent slides down from aboveAlert bar, top notification
animate-scale-inGrows in from slightly smallerModal, dialog, popover opening
animate-scale-springGrows in with a bounceCheckmarks, selection confirmations
animate-shakeHorizontal shake for errorsValidation error on inputs, failed actions
animate-shimmerSweeping gradient for loading stateSkeleton loader, placeholder blocks
animate-pulse-softGentle opacity pulseAttention state, recording indicator
animate-check-popIcon pops in with springCheckbox, radio, success confirmation
animate-progress-stripesAnimated stripe movementProgress bar, upload indicator
animate-progress-indeterminateSliding bar for unknown durationIndeterminate progress, loading bar

Practical examples

HTML — Button hover transition:

<button class="rounded-button bg-primary px-inset-md py-inset-sm text-sm font-medium text-primary-foreground shadow-button transition-shadow duration-fast hover:shadow-button-hover">
  Save
</button>

HTML — Modal with scale-in animation:

<div class="fixed inset-0 z-50 flex items-center justify-center animate-fade-in">
  <div class="w-full max-w-lg rounded-overlay border border-border bg-card p-surface-panel shadow-modal animate-scale-in">
    <h3 class="text-lg font-semibold text-foreground">Confirm</h3>
    <p class="text-sm text-muted-foreground">Are you sure?</p>
  </div>
</div>

HTML — Skeleton loading with shimmer:

<div class="space-y-stack-md">
  <div class="h-4 w-3/4 rounded-button bg-muted animate-shimmer"></div>
  <div class="h-4 w-1/2 rounded-button bg-muted animate-shimmer"></div>
  <div class="h-10 w-full rounded-input bg-muted animate-shimmer"></div>
</div>

HTML — Error input with shake:

<div class="space-y-stack-xs">
  <label class="text-sm font-medium text-danger">Email</label>
  <input class="w-full rounded-input border border-danger bg-background px-inset-md py-inset-sm text-foreground shadow-field-error animate-shake" aria-invalid="true" />
  <p class="text-xs text-danger">Please enter a valid email address.</p>
</div>

React:

import { Button, Card, Input } from '@byteion/react';

export default function Form() {
  return (
    <Card>
      <Input label="Name" />
      <Button>Submit</Button>
    </Card>
  );
}

Vue:

<script setup>
import { Button, Card, Input } from '@byteion/vue';
</script>

<template>
  <Card>
    <Input label="Name" />
    <Button>Submit</Button>
  </Card>
</template>

Reduced motion

Byteion UI respects the user's operating-system prefers-reduced-motion setting. When enabled, the --motion-* duration variables are set to 0ms, removing almost all transition animation:

@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast: 0ms;
    --motion-normal: 0ms;
    --motion-slow: 0ms;
  }
}

Keyframe animations (such as animate-shimmer and animate-pulse-soft) are not automatically disabled by this rule. If your component uses keyframe animations, consider removing or minimising them when reduced motion is active:

<div class="animate-shimmer motion-reduce:animate-none">...</div>

Components must remain fully functional and visually understandable without motion. Do not rely on animation as the only indicator of state — always pair it with colour, text, or icon changes.

Customization

Motion tokens are defined in packages/tokens/motion.js and consumed through the shared Tailwind preset. The CSS variables in packages/core/theme/variables.css can be overridden at runtime:

:root {
  --motion-fast: 80ms;
  --motion-normal: 150ms;
  --motion-slow: 250ms;
}
  • Keep dashboard and admin transitions short. Users in data-heavy interfaces notice delay more than polish.
  • Test on slow devices. A 320ms transition on a flagship phone feels like 600ms on a mid-range device — reduce durations if needed.
  • Test reduced motion. Verify that every interaction works without animation.
  • Avoid changing motion per component unless absolutely necessary — inconsistent timing feels disjointed.

Do and Don't

Do

  • Use tokenized durations and easing curves
  • Keep motion subtle in dense product screens
  • Use motion to clarify state changes, not decorate them
  • Test reduced-motion mode before shipping
  • Pair motion with visible state, text, colour, or icons

Don't

  • Use decorative animation everywhere — every transition should serve a purpose
  • Use slow transitions for frequent interactions like toggles or tooltips
  • Use spring motion in tables, admin lists, or serious workflows
  • Shake inputs repeatedly after every keystroke
  • Use motion as the only success or error feedback

Common mistakes

  • Over-animating dashboards. Animating every card, row, or stat change creates visual noise in data-heavy screens.
  • Using modal-scale-in for small tooltips. A tooltip or badge does not need a full scale-in animation — a quick fade-in is sufficient.
  • Making loading shimmer too aggressive. High-contrast shimmer with fast speed distracts users. The default 1.8s cycle is intentionally gentle.
  • Forgetting reduced motion. A component that relies on animate-shake without an accessible text alternative fails when motion is reduced.
  • Mixing random custom cubic-bezier values with Byteion motion tokens. One-off curves bypass the design system and create inconsistent feel.
  • Creating one-off animations instead of using existing tokens. Before writing a new keyframe, check whether animate-fade-in, animate-slide-up, or animate-scale-in can be composed to achieve the same effect.

Developer tips

• Use ease-out-soft for most transitions. It feels natural and polished — smooth deceleration without overshoot. • Use ease-spring sparingly. It is designed for celebratory moments (checkmarks, confirmations), not routine interactions. • Keep animations under 300ms for UI elements. Longer animations feel sluggish in data-heavy enterprise interfaces. • Pair duration-fast with small state changes. Hover states, focus rings, and toggles should resolve quickly — 120ms is fast enough to feel responsive without being instant. • Use transition-shadow for hover card elevations. It is cheaper than animating transform or all and avoids layout side effects. • Always test with reduced motion. Your interface should be fully functional without any animation enabled.

Unlock Premium Patterns

Get access to copy-paste ready Pro blocks, SaaS templates, and advanced component patterns.

Explore Pro Components