← All Foundations

Canon

Motion

Motion should be purposeful, not decorative. Animation reveals state changes and guides attention. When in doubt, don't animate.

Published January 8, 2026

Motion Philosophy

Every animation must answer: what does this communicate that stillness cannot? Motion exists to reduce cognitive load, not increase visual complexity.

Purposeful

Motion communicates state change. No decorative animation.

Subtle

Users should feel the effect, not notice the animation.

Consistent

One easing curve for coherent motion language.

Reducible

Always respect prefers-reduced-motion.

Clear Communication Motion

Ona-derived clear surfaces use motion only when it clarifies operational state. The acceptable uses are narrow:

  • state changed: allow, review, block, waiting, complete
  • selection changed: the active proof object, decision tab, or receipt changed
  • progression happened: a step moved from mapped to validated to handed off
  • attention is needed: an operator must review or stop before execution

Do not animate decorative backgrounds, idle proof panels, or generic AI atmosphere. If the motion does not clarify state, selection, progression, or handoff, remove it.

Duration Tokens

Five duration levels from instant feedback to deliberate reveals.

TokenValueUse Case
--duration-instant0msImmediate state changes
--duration-micro100msHover states, button feedback
--duration-fast200msTooltips, dropdowns
--duration-normal300msModal transitions, page elements
--duration-slow500msComplex reveals, hero animations

Easing

Canon uses a single easing curve for consistency:

--ease-standard: cubic-bezier(0.4, 0.0, 0.2, 1);

This is Material Design’s standard easing—quick acceleration, gradual deceleration. It feels natural because it mimics physical motion.

Accessibility

Always respect user preferences:

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Usage Examples

Button Hover

.button {
  transition: all var(--duration-micro) var(--ease-standard);
}

.button:hover {
  transform: translateY(-1px);
}

Modal Entrance

.modal {
  animation: fadeIn var(--duration-normal) var(--ease-standard);
}

@keyframes fadeIn {
  from { opacity: 0; transform: scale(0.95); }
  to { opacity: 1; transform: scale(1); }
}

Dropdown

.dropdown {
  transition: opacity var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}

.dropdown[data-state="closed"] {
  opacity: 0;
  transform: translateY(-4px);
}