Components/MotionToggle

MotionToggle

Twelve controlled switch/action styles with real models, icon feedback and caller-owned counters.

Since 0.6.3BETA

This component doc is in progress

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

Usage

Controlled actions

Every directory variant has a real controlled model. Like and repost actions also emit reversible counter changes. The demo shows all twelve directory IDs plus the registry's classic-toggle, external model reset, sizes, disabled behavior, caller-owned tab panels and optional haptic results.

Loading demo...

Named variants

IDIndependent feedback
t-bounceA moving thumb with two overshoot rebounds after the first actual change.
t-solidContrasting solid track and a crisp 150ms thumb translation.
t-rectSquarish track/thumb with a 500 stiffness / 30 damping spring.
t-circleLarger circular pill with 450 stiffness / 25 damping momentum.
t-bookmarkFilled bookmark, spring pop and caller-provided off/on labels.
t-likeFilled heart, spring burst, radial particles and reversible count update.
t-dislikeHighlighted thumb-down state with a brief −15° shake.
t-repostA 180° icon rotation and reversible count update.
t-pillCaller-provided options with a measured sliding spring indicator and keyboard selection.
t-morphLock/unlock icon swap and 180° rotating thumb.
t-checkSVG checkmark path draw after moving the thumb.
t-themeSun/moon swap with a 360° thumb turn and state-driven background change. It does not mutate the document theme.
classic-toggleRegistry-only 64×36px pill at md, 28px travel and 500 stiffness / 30 damping spring.

Best Practices

  • Use boolean v-model for switches and actions; use a string/number model with matching options for t-pill.
  • Supply label. Icon-only switches have a native button root with switch semantics; action buttons use aria-pressed. Enter and Space activate the same native click path.
  • Use v-model:count for like/repost when displaying counts. Activating adds one; undoing subtracts one. The caller owns the starting value and persistence. No timer pretends the action was saved remotely.
  • t-pill uses a tablist, roving focus, Arrow keys and Home/End. Disabled options are skipped. If the caller renders tab panels, give options their matching panelId; keep panel content and data fetching outside this primitive.
  • enabled=false disables only motion. It does not disable model operations. Use disabled to block activation.
  • Reduced motion preserves the final thumb/icon/checkmark and model changes, with no decorative burst. All motion resources are cancelled when inactive.
  • Haptics are opt-in. An accepted browser request is not proof of physical vibration; unsupported desktop browsers report their actual capability.

API Reference

Props

PropTypeDefaultDescription
modelValueboolean | string | numberfalseControlled state. t-pill selects matching string/number option values.
variantMotionToggleVariant't-bounce'All IDs above; exported as MOTION_TOGGLE_VARIANTS.
size'xs' | 'sm' | 'md' | 'lg''md'Component size. Native source geometry is retained at md.
disabledbooleanfalseBlocks pointer and keyboard activation.
labelstringRequiredAccessible name. Also the action-label fallback when off/on labels are omitted.
onLabelstringlabelActive action text.
offLabelstringlabelInactive action text.
countnumber—Caller-owned displayed count for like/repost; enables update:count.
optionsMotionToggleOption[][]{ value: string | number, label: string, disabled?: boolean, panelId?: string }. No business labels are hard-coded.
enabledbooleantrueEnables animations, independently of model operation.
hapticfalse | MotionHapticTypefalseOptional light/medium/heavy/success/warning/error request.
transitionTransitionSource-specific shared springOverrides thumb and tab-indicator transition through the existing Liquid spring compiler.

Events

EventPayloadDescription
update:modelValueMotionToggleValueNext boolean or selected option value.
update:countnumberLike/repost count after +1 on activation or −1 on undo. Only emitted when a count is supplied.
changeMotionToggleValueSame new model after an actual activation. Unchanged option selection emits nothing.
activateMotionToggleActivation{ value, previous, variant, count? }; no implied remote success.
hapticMotionHapticResult{ supported, accepted } after an opt-in request. accepted reflects the browser return value only.

Slots

NameScopeDescription
default{ active: boolean, count?: number }Action content; replaces the default text/count, not the model operation.
icon{ active: boolean }Replaces bookmark/heart/dislike/repost or lock/theme icons.
thumb{ active: boolean }Content inside switches without lock/theme/checkmark icons.
option{ option, index, active }Caller-rendered tab label. Keep it non-interactive inside the native tab button.

Overview

All operations are controlled. External changes update thumb, icon and tab state; the component never stores a second business model. Switches use role="switch" and aria-checked; actions use native pressed-button semantics; tabs expose aria-selected and their caller-supplied panel relationship. Like/repost counts are derived only from an actual state toggle.

The internal IconSwap is shared with TxMotion, preserving keyed scale/blur/opacity transitions. All spring configuration is resolved by the existing Liquid engine. WAAPI feedback and particle work are cancelled on suspension; tab measurement observers and resize listeners follow lifecycle. Haptic requests reuse the existing vibration utility and do not promise macOS desktop vibration.

Technologies

Adapted from Amicro's MIT AnimatedToggle, the twelve toggle catalog entries, IconSwap and the registry's classic-toggle source. Copyright (c) 2026 SYED SUBHAN UDDIN. Native Vue/browser controls replace React/Motion. The upstream double-bounce CSS class has no supplied stylesheet; this port supplies explicit two-rebound keyframes instead of preserving an inert class. Final integration checks and real-browser acceptance are owned by the build coordinator, not claimed by this page.