Skip to content

Editorial Ink barely moves. Motion confirms that something responded (a hover, a toggle, a new toast) and shows that something is still working (a spinner, a skeleton). It never decorates. All motion lives inside components; app code adds none of its own.

Layer
Foundation
Rules
4 numbered
Examples
4 do and don’t
Updated
Source
motion.md

The four steps, live

Feedback

0.12s ease · colour, border, shadow

Movement

0.16s ease · something changes place

Progress

0.3s ease · a determinate bar filling

Loading

Loop

0.6s to 1.6s, infinite · work in progress

Live tenet-ui components. With reduced motion turned on, the spinner and skeleton pulse instead of moving.

tenet-ui has no motion tokens yet. The durations below are written in each component’s CSS, and this page records them so that new components match.

StepDuration and easingUsed forComponents
Feedback0.12s easeColour, border and shadow changes on hover, focus and selectionButton, IconButton, TextInput, Textarea, NumberInput, Select, DatePicker, Tabs, SegmentedControl, Pagination, Calendar, Table (row hover), Accordion (header background), Tooltip (fade)
Movement0.16s easeSomething changes place or appearsSwitch (track colour and thumb slide), Accordion (chevron turn), Toast (enter)
Progress0.3s easeA determinate bar fillingProgressBar
Loop0.6s linear to 1.6s ease-in-out, infiniteWork in progressSpinner (spin), Skeleton (shimmer), ProgressBar (indeterminate sweep)

Under prefers-reduced-motion: reduce, the components that move or loop change what they do:

ComponentNormalReduced
SpinnerSpinning ringSlow opacity pulse (1.2s)
SkeletonMoving shimmerSlow opacity pulse (1.6s)
ProgressBar (indeterminate)Sweeping barFull-width bar with an opacity pulse (1.6s)
ToastFades and slides upAppears with no animation
TooltipFadesAppears with no transition
AccordionChevron turnsChevron jumps

The colour, border and shadow transitions in the Feedback row do not move anything, so they are not reduced (the Tooltip fade is). Switch is the one gap: its thumb still slides (0.16s) under reduced motion.

  1. Motion comes from components. App code writes no animation or transition of its own. When it must, the rule sits inside @media (prefers-reduced-motion: no-preference) and uses a duration from the table above.
  2. Nothing moves to draw attention. Status changes are announced with words (Toast, Banner, FormControl.Validation), not with shaking, bouncing or flashing.
  3. Loops are for work in progress only, and stop when the work stops. A Spinner or Skeleton is removed as soon as the content arrives.
  4. Durations stay short. Nothing in tenet-ui takes longer than 0.3s to finish, except the progress loops.

Do

<Skeleton />

While a list loads (the component reduces its own motion)

@media (prefers-reduced-motion: no-preference) { .chart-bar { transition: height 0.16s ease; } }

App motion behind the media query, on the Movement step

Don’t

.card:hover { transform: scale(1.03); transition: transform 0.4s; }

Decorative, too slow, and ignores reduced motion

@keyframes shake { ... }

On an invalid field (use FormControl.Validation text instead)