Components/Motion

Motion

Caller-driven entrance, pointer, hover, scroll and visibility interactions.

Since 0.6.3BETA

This component doc is in progress

This page is still being migrated. Demos and API details may change.

Usage

Registry interactions

TxMotion preserves seven entrances, four hover interactions, three cursor effects and three scroll interactions. The demo renders every named variant, actual pointer coordinates, scroll progress, sticky content and the keyed icon and visibility helpers.

Loading demo...

Named variants

GroupIDs and behavior
Entrancefade-in (opacity); fade-up / fade-down (vertical offset); slide-left / slide-right (horizontal offset); scale-in (0.92 scale with overshoot); zoom-in (0.85 scale plus 12px blur).
Hovercard-hover shares a moving background between caller-supplied items; tilt-card maps normalized pointer coordinates to 3D rotation; magnetic-button pulls inside a distance threshold; glow-button moves a 120px radial glow under the pointer.
Cursorcursor-trail has shrinking dots with distinct springs; spotlight moves a 250px radial highlight over content; mouse-follow spring-follows the pointer and accepts a cursor slot.
Scrollscroll-reveal reveals content when intersecting the configured viewport; progress-indicator spring-follows actual scroll progress; sticky-reveal maps target-relative progress to the current item and sticky visual.
Supporting componentsicon-swap implements IconSwap / IconSwapItem with keyed scale, blur and opacity transitions; in-view implements InViewRender by mounting the slot near the viewport.

Best Practices

  • Supply content, items and action handlers. The component does not navigate, copy, publish or fabricate business success.
  • Use label for native magnetic/glow buttons and progress indicators. Card items are native links when href is present; otherwise they are native buttons with select events.
  • Keep cursor effects local by default. global teleports cursor layers and a global progress bar to body, so transformed ancestors cannot trap fixed positioning. Decorative cursor content is hidden from assistive technology.
  • Pass the actual element to scrollContainer for nested scrolling. Without it, progress reads the document. Sticky visuals and steps use that viewport's measured height and resize updates rather than document vh; the caller still supplies a meaningful scroll range.
  • Change stateKey or call the exposed replay() to replay entrances. For icon-swap, change the key with the actual state and provide the corresponding icon.
  • enabled=false suspends animation and its input resources while leaving content readable. Reduced motion keeps semantic scroll progress and immediately displays the final content/icon state.
  • For in-view, keep a stable wrapper size to avoid layout shifts. once=true retains mounted content after the first intersection; once=false unmounts it when it leaves.

API Reference

Props

PropTypeDefaultDescription
variantMotionVariant'fade-in'Any named variant listed above; exported as MOTION_VARIANTS.
asstringNative button for magnetic/glow, otherwise divRoot element. Native-button attributes and events fall through.
enabledbooleantrueEnables motion and input tracking.
disabledbooleanfalseDisables native buttons and input-driven effects.
labelstring—Accessible name; supply it for icon-only controls and progress.
durationnumber500 / 600 / 700ms by entrance; 300ms for icon swapDuration in milliseconds.
delaynumber0Entrance delay in milliseconds.
xOffsetnumber40 for left, -40 for right, otherwise 0Entrance starting x coordinate.
yOffsetnumber20 up, -20 down, 30 scroll reveal, otherwise 0Entrance starting y coordinate.
initialScalenumber0.92 scale, 0.85 zoom, 0.95 scroll reveal, otherwise 1Starting scale.
initialBlurnumber12Zoom blur radius in pixels.
maxTiltnumber15Maximum rotation at the pointer edges, in degrees.
rangenumber45Magnetic pull radius from the center, in pixels.
strengthnumber0.35Magnetic coordinate multiplier.
springSpringConfigSource-specificOverrides pointer/trail/progress stiffness, damping and mass; uses the shared spring integrator.
glowColorstring'var(--tx-color-primary)'Accent for glows, cursors and progress. Prefer theme tokens.
glowSizenumber120 glow button; 250 spotlightRadial effect radius in pixels.
cursorSizenumber8Trail head diameter; the follower has a minimum 24px outline.
cursorCountnumber6Trail dot count, clamped to 1–64. Each dot shrinks and has its own spring.
globalbooleanfalseGlobal cursor coordinates/teleport; fixed top progress bar.
scrollContainerHTMLElement | nullDocumentViewport and progress scroller.
progressHeightnumber4Progress bar height in pixels.
stickyTopnumber20Sticky visual top inset in pixels.
itemsMotionItem[][]Card/sticky content: { id, title, description?, href?, disabled? }.
oncebooleantrueRetains first entrance / visibility mount.
rootMarginstring'-15%' reveal; '200px' in-viewIntersectionObserver margin.
stateKeystring | number | boolean0Entrance replay / icon identity.
transitionTransitionSource entrance easing / shared 'smooth'Shared transition override for entrances and card-background motion.

Events

EventPayloadDescription
complete—An entrance animation finished normally. Suspension cancels it without claiming completion.
progressnumberActual progress from 0 to 1.
active-changenumberCurrent sticky-item index.
select(item: MotionItem, index: number)Enabled card action activated with pointer or keyboard.
visible-changebooleanReveal/in-view intersection changed.

Slots and exposed state

NameScope / TypeDescription
default{ pointer, progress, active } for generic effectsCaller content. For icon-swap, supply the icon associated with stateKey.
item{ item, index, active }Card item / sticky text.
visual{ item, index, active }Sticky visuals. Inactive layers are inert and hidden from assistive technology.
cursor—Follower decoration.
replay()() => voidReplays an entrance when motion is active.
progressnumberExposed actual scroll progress; Vue unwraps the internal readonly ref.
activeIndexnumberExposed sticky selection; Vue unwraps the internal computed ref.

Vue supporting APIs

Import these from @talex-touch/tuffex/motion, not the utils barrel. All browser resources follow mount, KeepAlive and document visibility; browser APIs are not accessed during SSR.

ExportInputsActual output
useMousePositionOptional target ref, enabled getter, global getterReadonly ref { x, y, elementX, elementY, width, height, inside }; native pointer coordinates. Touch does not create hover decorations.
useScrollProgressContainer getter, enabled getter, optional target getterReadonly 0–1 ref. Without target: scrollTop / scroll range. With target: start-start to end-end target progress.
useStaggerCount getter, { baseDelay?, staggerDelay?, from? } getterComputed delay array in milliseconds. Defaults: 0ms base, 50ms step, first; supports last, center and numeric origin.
useReducedMotion—Existing shared reactive preference, not a second media-query implementation.
useScreenSizeOptional enabled getterReadonly viewport width/height; SSR starts at 0/0.
useIsMobileBreakpoint getter, default 768Readonly media-query result. Width is not treated as a user's reduced-motion preference.
useLoopFlagTarget ref, enabled getter, interval getter (2000ms)Readonly incrementing flag. Pauses offscreen, hidden, disabled, reduced and deactivated.
useWebHapticsOptional enabled getter{ supported, trigger(type) }, where trigger returns { supported, accepted }. Types: light, medium, heavy, success, warning, error. Uses the existing vibration utility.
useCanvasSetupCanvas ref, enabled getterCached logical { width, height, dpr }, actual pixel-size updates, active, visible, reduced; DPR is capped at 2. The caller owns drawing.

accepted=true means the browser accepted a Vibration API request. It does not prove physical vibration. Unsupported macOS desktop browsers return supported=false; no device-feedback claim is made.

Overview

Shared spring physics drives tilt, magnetism, independent trail dots, mouse following and scroll progress. Frame work stops at rest and is cancelled on suspension. WAAPI entrances and icon transitions are cancelled on hidden/offscreen/deactivated/unmounted scopes. Observers, resize/pointer/scroll listeners, loop timers and vibration ownership are released by their Vue lifecycle owners. Without IntersectionObserver, meaningful content remains available.

Technologies

The source is adapted from Amicro's MIT-licensed entrance/hover/cursor/scroll registry, IconSwap, InViewRender and support hooks. Copyright (c) 2026 SYED SUBHAN UDDIN. The port uses Vue, the existing motion-activity helper, shared Liquid spring and vibration utilities; it adds no React, Motion or Tailwind runtime. Validation of this integration is performed by the owning build; this page does not claim a completed browser acceptance run.