Back to Oh My Openagent

Interaction Mechanics — beui.dev-Anchored

packages/shared-skills/skills/frontend/references/design/interaction-skill.md

4.19.312.8 KB
Original Source

Interaction Mechanics — beui.dev-Anchored

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".

1. The reference contract — never design an interaction from memory

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:

  1. Find the nearest pattern in the catalog (section 3). The live catalog is https://beui.dev/llms.txt; refresh from it when a pattern seems missing from the tables below.
  2. Read its real source through the recipe (section 2). Never guess spring values, exit orchestration, or gesture thresholds from a preview description.
  3. Extract the mechanism, not the pixels: the spring config, the layout strategy (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.
  4. Adapt to the project. Concrete durations, easings, and spring params come from the project 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.
  5. No matching pattern? Compose from the nearest two, or state explicitly that the interaction is novel and record its mechanism in DESIGN.md before building it.

2. Consultation recipe (curl-only, verified 2026-07)

All endpoints are public, no auth, no browser:

bash
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.

3. Catalog — pattern routing map

Buttons, state feedback, and progress

Pattern (slug)MechanismReach for it when
buttonSpring press; StatefulButton idle → loading → success/error with blur-swap slots and morphing width; MagneticButton cursor pullAny submit/CTA that has async states — never leave a button state-less
action-swapText/icon swap with blur motionCopy → check, send → stop, any label that changes meaning in place
expanding-arrow-buttonExpanding, hold-to-confirm, and slide CTA interactionsExpressive marketing CTAs, destructive hold-to-confirm
animated-badgeAnimated state icons, pulse feedbackConnection/status dots, live activity indicators
loader17 variants incl. terminal-ascii; reduced motion swaps every transform for an opacity pulseAny loading state; copy its reduced-motion contract even when hand-rolling
otp-inputGliding focus ring, per-slot digit roll, error shake, success check drawCode entry, verification flows
file-uploadProgress rows, retry/remove, reduced-motion-safe state changesUpload queues, long-running item lists
feedback-widgetTrigger morphs into a popup with sending/success/retry statesCorner feedback affordances, inline report flows

Selection and form controls

Pattern (slug)MechanismReach for it when
switchSpring-driven thumb with press feedbackBoolean toggles
checkboxDraw-on checkmark, indeterminate supportMulti-select, tree selection
radioGliding layoutId indicator dotSingle-select groups
inputLabel, icons, error shake, success check drawValidated text entry
selectPanel bouncily unfolds from the trigger; Morph variant grows the trigger into the panelDropdown selection with spatial continuity
range-sliderBouncy vertical-bar thumb gliding between snapped stepsStepped value entry
wheel-pickeriOS-style 3D drum on native momentum scroll with notch snapDate/time or option drums, mobile-feel pickers
availability-schedulerPer-day spring toggles, blur-slide range add/removeSchedule/slot editors
Pattern (slug)MechanismReach for it when
tabsPill/segment/underline with a spring layoutId indicatorTab bars, view-mode selectors
expandable-tabsActive icon tab expands to a labelled pill; panel morphs height, slides direction-awareCompact tab bars with rich panels
shared-layout-bgPill glides between hovered items via shared layout, blur enter/exitSidebar/menu hover and active states
dockmacOS-style grouped actions with a gliding active pillToolbars, grouped action rails
bounce-sidebarActive dot jumps between destinations on a curved spring pathVertical navigation with a playful indicator
preview-railCompact ticks form a hover pyramid and reveal a floating destination previewDense navigation rails, session/thread switchers
expandable-action-barIcon actions expand into labelled controls on hover/focusCompact action clusters
overflow-actionsConnected pill rail springs open to reveal extra controlsPrimary-plus-overflow action groups
command-paletteFuzzy filter with a spring-animated active rowCmd-K surfaces
bloom-menuButton morphs into a menu blooming iris-out from center with radial staggerRadial/launcher menus

Overlays and surfaces

Pattern (slug)MechanismReach for it when
tooltipBlur enter/exit, spring spawnHover/focus hints
popoverGooey SVG-filter ooze from the trigger; Morph variant clip-morphs from the trigger cornerAnchored panels that should feel attached to their trigger
context-menuPointer-origin clip morph, gliding active row, keyboard nav, typeahead, long-pressRight-click and long-press menus
morphing-modalOne panel morphs height between inner views, blur cross-fade on contentMulti-step dialogs, settings panes
center-morph-modalSurface unfolds from its exact center toward every edge and folds backFocused confirm/detail modals
drawerSpring side panel, backdrop blur, body scroll lock, esc-to-closeSide panels, inspector panes
bottom-sheetDraggable sheet with snap points, inertia, glass surfaceMobile-feel sheets on any platform
dynamic-islandPill morphs between live-activity views with bouncy shell resize and blur crossfadesLive status surfaces, compact expanding widgets
notification-stackCards spring from a stacked summary into a readable list on hover/focus/tapNotification centers, grouped alerts
animated-toast-stackStatus morphs, swipe dismissal, layout-aware stackingToast systems — layout-aware stacking is the bar
theme-toggleFull-page clip-path reveal via the View Transition APITheme switching that should feel like one gesture

Content, data, and gestures

Pattern (slug)MechanismReach for it when
bouncy-accordionSingle-open accordion with weighted spring layout, reduced-motion-safe revealsDisclosure groups, expandable rows
tableVirtualized 10k+ rows, sortable, resizable, minimal reduced-motion-safe motionData grids — proof that restraint is also a motion decision
infinite-masonryVirtualized variable-height masonry with progressive loadMedia/card walls
swipeable-listRows swipe to reveal contextual actionsMobile-style lists with hidden actions
pull-to-refreshDrag resistance, threshold feedback, async refreshRefreshable feeds
marqueeInfinite horizontal/vertical scroll, pause on hoverLogo walls, tickers
text-animationSpring reveals, chromatic sweeps, shimmer loading, letter-cascade swapsHero copy, streaming/loading text
numberCount-up values, rolling digit tickersMetrics, token/cost counters
cylinder-carouselItems line a 3D cylinder with springy glide and snapShowcase carousels
knockout-bracketAnimated tournament fixtures paging through roundsBracket/progression views
prediction-market / swap / wallet-cardTrade tickets, morphing swap views, morphing account surfacesFinance-shaped composite widgets
not-foundFive animated 404 stylesError pages that keep the product's feel

Ambience and scroll

Pattern (slug)MechanismReach for it when
tilt-card3D perspective tilt with cursor-tracked glareHero/product cards that should feel physical
shader-backgroundCanvas shader variants (mesh gradient, grain, warp, waves…); reduced motion freezes themAtmospheric backgrounds with dimension
scroll-animationLenis smooth-scroll provider plus a reading-progress indicatorScroll-driven storytelling

4. Mechanics rules

These sharpen the shared axioms for interaction work; none of them replace the style skill.

  • Motion serves meaning. Every animation maps to a real interaction, state change, or affordance. A hover that changes nothing is slop — beui.dev patterns all animate state, never decoration.
  • Reduced motion is part of the component, not an afterthought. Every beui.dev component ships a reduced-motion path; match that bar. Web: 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.
  • GPU-composited properties onlytransform, opacity, filter. Never animate layout properties; morph layout through shared-layout (layoutId) or measured height primitives instead.
  • Springs move things; easings tint things. Spatial movement (position, scale, layout morphs) wants spring physics so it stays interruptible and retargetable. Color, opacity, and blur want short duration + easing. Do not put a fixed-duration tween on a gesture-driven surface.
  • Interruptibility is non-negotiable. A press, hover-out, or route change mid-animation must retarget smoothly, never queue or block input. This is the practical reason beui.dev uses springs — copy that property, not just the bounce.
  • Motion never regresses input latency or stream rendering. Measure with the perfection ruleset when in doubt; a virtualized list's measurement contract beats a pretty reveal.
  • Library choice is a project decision, not a default. beui.dev assumes Motion (motion.dev) + Tailwind. If the project already has a motion stack, adapt the mechanism to it. If it has none: CSS transitions/WAAPI cover micro-interactions; adding a library is justified by shared-layout or spring-physics needs and gets recorded (with bundle cost) in DESIGN.md. Check package.json before importing anything.

5. DESIGN.md integration

design-system-architecture.md defines a Motion & Interaction section in every DESIGN.md. This file feeds it:

  • Extracted spring configs, durations, and easings land there as named tokens before components use them.
  • Each shipped interaction traces to a catalog pattern (or a recorded novel mechanism) plus its reduced-motion behavior.
  • New reusable interaction patterns (used 2+ times) get documented back into DESIGN.md Section 5 with their states, like any other primitive.

6. Verification

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.