packages/shared-skills/skills/frontend/references/design/interaction-skill.md
Style skills decide how a surface looks. This file decides how it moves and responds — spring physics, layout morphs, enter/exit orchestration, gesture feel, and reduced-motion discipline. It stacks on top of any Layer A style skill and any Layer B brand, exactly like layout-skill.md, and adds ZERO visual direction: color, type, and material still come from the style skill and DESIGN.md.
Load this whenever the deliverable includes interaction feel: micro-interactions, animated components, transitions, hover/press/focus/state feedback, gestures, loading/success/error morphs, animated tabs/menus/modals/drawers/toasts — or the user says "make it feel alive", "polish the interactions", "add micro-interactions".
beui.dev is the interaction benchmark: free, open-source animated React components (Motion + Tailwind CSS) where every component ships reduced-motion support and the full TypeScript source is one curl away. Improvised interaction design produces slop motion the same way freestyled styling produces generic SaaS slop, and the fix is the same: consult the reference before designing.
The contract, in order:
https://beui.dev/llms.txt; refresh from it when a pattern seems missing from the tables below.layoutId shared layout vs height morph vs clip-path), what animates in what order on enter/exit, where blur crossfades sit, and what the reduced-motion path swaps to.DESIGN.md Motion & Interaction section. Where beui.dev and DESIGN.md disagree, DESIGN.md wins. A value that is not in DESIGN.md gets added there first, then used.DESIGN.md before building it.All endpoints are public, no auth, no browser:
curl -s https://beui.dev/llms.txt # full catalog: every component + one-line feel
curl -s https://beui.dev/r # registry index (JSON): slugs, categories, endpoints
curl -s https://beui.dev/r/{slug} # component detail (JSON): files, dependencies, dates
curl -s https://beui.dev/r/{slug}/raw # component source (TypeScript) — the thing to read
curl -s https://beui.dev/components/{category}/{slug}.md # component doc page as markdown
Categories are motion (primitives) and blocks (composed patterns). When the user wants the component itself rather than the mechanism, a shadcn-style item registry exists at https://beui.dev/r/{slug}.json. Read source to learn; do not vendor beui.dev files into reference docs, and do not paste whole components into a project when only the mechanism is needed.
| Pattern (slug) | Mechanism | Reach for it when |
|---|---|---|
button | Spring press; StatefulButton idle → loading → success/error with blur-swap slots and morphing width; MagneticButton cursor pull | Any submit/CTA that has async states — never leave a button state-less |
action-swap | Text/icon swap with blur motion | Copy → check, send → stop, any label that changes meaning in place |
expanding-arrow-button | Expanding, hold-to-confirm, and slide CTA interactions | Expressive marketing CTAs, destructive hold-to-confirm |
animated-badge | Animated state icons, pulse feedback | Connection/status dots, live activity indicators |
loader | 17 variants incl. terminal-ascii; reduced motion swaps every transform for an opacity pulse | Any loading state; copy its reduced-motion contract even when hand-rolling |
otp-input | Gliding focus ring, per-slot digit roll, error shake, success check draw | Code entry, verification flows |
file-upload | Progress rows, retry/remove, reduced-motion-safe state changes | Upload queues, long-running item lists |
feedback-widget | Trigger morphs into a popup with sending/success/retry states | Corner feedback affordances, inline report flows |
| Pattern (slug) | Mechanism | Reach for it when |
|---|---|---|
switch | Spring-driven thumb with press feedback | Boolean toggles |
checkbox | Draw-on checkmark, indeterminate support | Multi-select, tree selection |
radio | Gliding layoutId indicator dot | Single-select groups |
input | Label, icons, error shake, success check draw | Validated text entry |
select | Panel bouncily unfolds from the trigger; Morph variant grows the trigger into the panel | Dropdown selection with spatial continuity |
range-slider | Bouncy vertical-bar thumb gliding between snapped steps | Stepped value entry |
wheel-picker | iOS-style 3D drum on native momentum scroll with notch snap | Date/time or option drums, mobile-feel pickers |
availability-scheduler | Per-day spring toggles, blur-slide range add/remove | Schedule/slot editors |
| Pattern (slug) | Mechanism | Reach for it when |
|---|---|---|
tabs | Pill/segment/underline with a spring layoutId indicator | Tab bars, view-mode selectors |
expandable-tabs | Active icon tab expands to a labelled pill; panel morphs height, slides direction-aware | Compact tab bars with rich panels |
shared-layout-bg | Pill glides between hovered items via shared layout, blur enter/exit | Sidebar/menu hover and active states |
dock | macOS-style grouped actions with a gliding active pill | Toolbars, grouped action rails |
bounce-sidebar | Active dot jumps between destinations on a curved spring path | Vertical navigation with a playful indicator |
preview-rail | Compact ticks form a hover pyramid and reveal a floating destination preview | Dense navigation rails, session/thread switchers |
expandable-action-bar | Icon actions expand into labelled controls on hover/focus | Compact action clusters |
overflow-actions | Connected pill rail springs open to reveal extra controls | Primary-plus-overflow action groups |
command-palette | Fuzzy filter with a spring-animated active row | Cmd-K surfaces |
bloom-menu | Button morphs into a menu blooming iris-out from center with radial stagger | Radial/launcher menus |
| Pattern (slug) | Mechanism | Reach for it when |
|---|---|---|
tooltip | Blur enter/exit, spring spawn | Hover/focus hints |
popover | Gooey SVG-filter ooze from the trigger; Morph variant clip-morphs from the trigger corner | Anchored panels that should feel attached to their trigger |
context-menu | Pointer-origin clip morph, gliding active row, keyboard nav, typeahead, long-press | Right-click and long-press menus |
morphing-modal | One panel morphs height between inner views, blur cross-fade on content | Multi-step dialogs, settings panes |
center-morph-modal | Surface unfolds from its exact center toward every edge and folds back | Focused confirm/detail modals |
drawer | Spring side panel, backdrop blur, body scroll lock, esc-to-close | Side panels, inspector panes |
bottom-sheet | Draggable sheet with snap points, inertia, glass surface | Mobile-feel sheets on any platform |
dynamic-island | Pill morphs between live-activity views with bouncy shell resize and blur crossfades | Live status surfaces, compact expanding widgets |
notification-stack | Cards spring from a stacked summary into a readable list on hover/focus/tap | Notification centers, grouped alerts |
animated-toast-stack | Status morphs, swipe dismissal, layout-aware stacking | Toast systems — layout-aware stacking is the bar |
theme-toggle | Full-page clip-path reveal via the View Transition API | Theme switching that should feel like one gesture |
| Pattern (slug) | Mechanism | Reach for it when |
|---|---|---|
bouncy-accordion | Single-open accordion with weighted spring layout, reduced-motion-safe reveals | Disclosure groups, expandable rows |
table | Virtualized 10k+ rows, sortable, resizable, minimal reduced-motion-safe motion | Data grids — proof that restraint is also a motion decision |
infinite-masonry | Virtualized variable-height masonry with progressive load | Media/card walls |
swipeable-list | Rows swipe to reveal contextual actions | Mobile-style lists with hidden actions |
pull-to-refresh | Drag resistance, threshold feedback, async refresh | Refreshable feeds |
marquee | Infinite horizontal/vertical scroll, pause on hover | Logo walls, tickers |
text-animation | Spring reveals, chromatic sweeps, shimmer loading, letter-cascade swaps | Hero copy, streaming/loading text |
number | Count-up values, rolling digit tickers | Metrics, token/cost counters |
cylinder-carousel | Items line a 3D cylinder with springy glide and snap | Showcase carousels |
knockout-bracket | Animated tournament fixtures paging through rounds | Bracket/progression views |
prediction-market / swap / wallet-card | Trade tickets, morphing swap views, morphing account surfaces | Finance-shaped composite widgets |
not-found | Five animated 404 styles | Error pages that keep the product's feel |
| Pattern (slug) | Mechanism | Reach for it when |
|---|---|---|
tilt-card | 3D perspective tilt with cursor-tracked glare | Hero/product cards that should feel physical |
shader-background | Canvas shader variants (mesh gradient, grain, warp, waves…); reduced motion freezes them | Atmospheric backgrounds with dimension |
scroll-animation | Lenis smooth-scroll provider plus a reading-progress indicator | Scroll-driven storytelling |
These sharpen the shared axioms for interaction work; none of them replace the style skill.
prefers-reduced-motion: reduce disables or replaces every transform-based animation (the loader pattern's opacity-pulse swap is the model). React Native: respect the system reduce-motion setting.transform, opacity, filter. Never animate layout properties; morph layout through shared-layout (layoutId) or measured height primitives instead.perfection ruleset when in doubt; a virtualized list's measurement contract beats a pretty reveal.DESIGN.md. Check package.json before importing anything.design-system-architecture.md defines a Motion & Interaction section in every DESIGN.md. This file feeds it:
DESIGN.md Section 5 with their states, like any other primitive.Interaction work is verified through /visual-qa with motion actually driven and inspected — hover, press, open/close, swipe, and theme transitions exercised on the rendered surface, plus a reduced-motion pass (emulate prefers-reduced-motion: reduce) proving the fallback exists. Timing-sensitive changes record a short screen capture, not just stills.