Motion
Define the animation principles, easing curves, and transition tokens that enhance user experience through thoughtful motion.
Motion
Motion helps bring the Tendoo interface to life. It guides users, enhances feedback, and adds delight — all without getting in the way. Our motion system uses consistent tokens and principles to ensure motion is meaningful, accessible, and performant.
Why motion matters
- Provides visual feedback and spatial awareness.
- Guides attention and supports interaction.
- Reinforces brand personality through consistent expression.
Motion tokens
Our motion tokens define a shared language for timing and easing across all components. Use these to ensure smooth and consistent interactions.
Durations
Token | Value | Use cases |
---|---|---|
motion.duration.xs | 75ms | Instant feedback (e.g., toggle, switch, button group) |
motion.duration.sm | 150ms | Hover, press, small UI transitions (e.g., chip, badge) |
motion.duration.md | 250ms | Modals, drawers, dropdowns, tooltips |
motion.duration.lg | 400ms | Page transitions, image viewers, masonry layout |
motion.duration.xl | 600ms | Carousel slides, timeline scrolls, skeleton loaders |
Easings
Token | Curve | Use cases |
---|---|---|
motion.easing.linear | cubic-bezier(0, 0, 1, 1) | Progress bars, sliders |
motion.easing.standard | cubic-bezier(0.4, 0, 0.2, 1) | Default easing for UI transitions |
motion.easing.in | cubic-bezier(0.4, 0, 1, 1) | Entering elements (e.g., dialogs, dropdowns) |
motion.easing.out | cubic-bezier(0, 0, 0.2, 1) | Exiting elements (e.g., tooltips, toasts) |
motion.easing.elastic | cubic-bezier(0.34, 1.56, 0.64, 1) | Playful or attention-grabbing elements (e.g., rating, snackbar) |
// motion.tokens.ts
export const motion = {
duration: {
xs: "75ms",
sm: "150ms",
md: "250ms",
lg: "400ms",
xl: "600ms",
},
easing: {
linear: "cubic-bezier(0, 0, 1, 1)",
standard: "cubic-bezier(0.4, 0, 0.2, 1)",
in: "cubic-bezier(0.4, 0, 1, 1)",
out: "cubic-bezier(0, 0, 0.2, 1)",
elastic: "cubic-bezier(0.34, 1.56, 0.64, 1)",
},
};
Component examples
Here’s how these tokens are typically applied across your components:
Component | Duration token | Easing token |
---|---|---|
accordion | duration.md | easing.standard |
alert-dialog | duration.md | easing.in / out |
aspect-ratio | — | — |
audio-player | duration.sm | easing.out |
avatar | duration.sm | easing.standard |
badge | duration.xs | easing.standard |
breadcrumb | duration.xs | easing.standard |
button | duration.sm | easing.out |
button-group | duration.sm | easing.out |
calendar | duration.md | easing.standard |
card | duration.sm | easing.standard |
carousel | duration.xl | easing.standard |
chart | duration.lg | easing.linear |
checkbox | duration.sm | easing.out |
chip | duration.sm | easing.out |
code-block | duration.xs | easing.standard |
collapsible | duration.md | easing.standard |
color-picker | duration.sm | easing.out |
combobox | duration.md | easing.in / out |
command | duration.sm | easing.out |
context-menu | duration.md | easing.out |
data-table | duration.md | easing.standard |
date-picker | duration.md | easing.standard |
dialog | duration.md | easing.in / out |
drawer | duration.lg | easing.in / out |
dropdown-menu | duration.md | easing.in / out |
empty-state | duration.lg | easing.out |
error-boundary | duration.md | easing.out |
file-upload | duration.md | easing.standard |
image-gallery | duration.lg | easing.out |
image-viewer | duration.lg | easing.out |
input | duration.sm | easing.standard |
input-otp | duration.sm | easing.out |
json-viewer | duration.sm | easing.standard |
kbd | duration.xs | easing.out |
label | duration.xs | easing.standard |
link | duration.xs | easing.out |
list-group | duration.sm | easing.standard |
loader | duration.lg | easing.linear |
map | duration.lg | easing.out |
masonry-grid | duration.lg | easing.out |
menubar | duration.md | easing.standard |
metric | duration.sm | easing.linear |
navigation-menu | duration.md | easing.in / out |
notification | duration.sm | easing.elastic |
pagination | duration.sm | easing.standard |
popover | duration.md | easing.in / out |
progress | duration.md | easing.linear |
radio-group | duration.sm | easing.out |
range-slider | duration.sm | easing.standard |
rating | duration.sm | easing.elastic |
resizable | duration.md | easing.standard |
scroll-area | duration.lg | easing.standard |
select | duration.md | easing.in / out |
separator | — | — |
sheet | duration.lg | easing.in / out |
skeleton | duration.lg | easing.linear |
snackbar | duration.sm | easing.elastic |
spinner | duration.lg | easing.linear |
stepper | duration.md | easing.standard |
switch | duration.sm | easing.out |
tab | duration.md | easing.standard |
table | duration.md | easing.standard |
tag | duration.sm | easing.out |
text-editor | duration.md | easing.standard |
textarea | duration.sm | easing.standard |
time-picker | duration.md | easing.in / out |
timeline | duration.xl | easing.standard |
toast | duration.sm | easing.elastic |
toggle | duration.sm | easing.out |
toggle-group | duration.sm | easing.out |
tooltip | duration.sm | easing.out |
tree-view | duration.md | easing.standard |
video-player | duration.md | easing.standard |
Usage guidelines
- Use motion sparingly to support usability, not distract from it.
- Apply consistent duration and easing based on context.
- Avoid overly fast or slow transitions — use tokens to maintain rhythm.
- Always respect user preferences via
prefers-reduced-motion
.
Accessibility best practices
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
Examples
Button hover
<button className="transition-transform duration-fast ease-in-out hover:scale-105">
Hover Me
</button>
Modal transition
.modal-enter {
opacity: 0;
transform: translateY(16px);
}
.modal-enter-active {
opacity: 1;
transform: translateY(0);
transition: opacity 200ms var(--motion-easing-ease-out), transform 200ms var(--motion-easing-ease-out);
}
Related
Motion enhances experience when done with purpose. Use tokens, stay subtle, and let transitions support — not steal — the user's attention.