Components/MotionForm

MotionForm

Fifteen animated form interactions built on TuffEx form controls.

Since 0.6.3BETA

This component doc is in progress

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

Usage

All Variants

validate only requests work: the caller writes back status and error, and changing validationKey replays the shake.

Loading demo...

Best Practices

  • Keep values, validation messages, and business status in the caller; the component never decides success or clears an error on a timer.
  • Treat filesSelected as a selection only: upload each File through your own service and drive status from the result.
  • Always pass a label and localized labels; OTP digit names are built from label too.
  • Use readonly only for text fields and OTP; use disabled for choices, files, the slider, and actions.
  • Set nativeType="submit" only when an enclosing native form owns submission, and don't run the same work from both the click and the form's submit.

API Reference

Props

NameTypeDefaultDescription
variantMotionFormVariant'floating-label-input'One of the fifteen effects in the variant table.
modelValueMotionFormValueunsetControlled value; its shape depends on the variant.
labelstring''Visible label and accessible name; falls back to labels.field.
placeholderstring''Text and select placeholder; a resting floating label covers it.
descriptionstring''Helper text in the message region; error and status take precedence.
size'xs' | 'sm' | 'md' | 'lg''md'Height, choice mark, and radius; action xs maps to Button sm.
disabledbooleanfalseBlocks edits, selection, removal, password reveal, and action requests.
readonlybooleanfalseMakes text, textarea, and OTP read-only; password reveal still works.
requiredbooleanfalseRequired marker and accessible state; native text fields also get required.
status'default' | 'loading' | 'success' | 'error''default'Caller-driven status; loading blocks action requests.
errorstring''When non-empty, sets the error state and shows this message.
validationKeystring | numberunsetReplays the current error when it changes.
labelsPartial<MotionFormLabels>unsetLocalizes static text, digit names, and removal labels.
optionsMotionFormOption[][]Choices for radio, dropdown, and chips.
inputType'text' | 'email' | 'number' | 'date''text'Text control type; the password variant switches text/password itself.
autocompletestringunsetNative autocomplete; the first OTP box always uses one-time-code.
passwordVisiblebooleanunsetControlled reveal state, paired with update:passwordVisible.
rowsnumber2Minimum textarea rows.
maxRowsnumber8Maximum auto-grow rows before scrolling; never below rows.
maxLengthnumberunsetLength limit for text and textarea; OTP is fixed at 4 digits.
acceptstring'*/*'File type filter for picking and dropping.
multiplebooleantrueMultiple files; when false, a new file replaces the old one.
maxFilesnumber10Maximum number of files.
minnumber0Slider minimum.
maxnumber100Slider maximum.
stepnumber1Slider step.
formatValue(value: number) => stringunsetFormats the slider value and tooltip.
nativeType'button' | 'submit''button'Native type of the submit button.
motionbooleantrueEnables motion, still gated by visibility, KeepAlive, and reduced motion.

Events

EventPayloadMeaning
update:modelValueMotionFormValueFires on a user edit or selection.
changeMotionFormValueFires together with update:modelValue.
update:passwordVisiblebooleanFires when password reveal toggles.
focus, blurFocusEventFire when focus enters or leaves the component, not on internal moves.
searchstringFires when the search-expand text changes; sends no request.
validateMotionFormValueAsks the caller to validate the current value.
submit[value: MotionFormValue | undefined, event: MouseEvent]Asks the caller to do the work; doesn't change status.
otpCompletestringFires when all four boxes hold digits; can fire again after an edit.
filesSelectedFileUploaderFile[]Newly accepted files only; neither the full list nor an upload completion.
fileRemove{ id: string, value: FileUploaderFile[] }Fires on removal with the file ID and the new list.

Slots

SlotScopeUse
labelnoneVisible label, linked to the control through a stable ID.
prefix, suffixnoneInput affixes; suffix replaces the password reveal button.
option{ option, selected }Radio and dropdown option content.
chip{ option }Chip label; the remove button stays.
file{ file, remove: () => void }File row content; the remove button stays.
submit{ status: MotionFormStatus, label: string }Submit button content, beside the state glyph.
status{ status, error, value }Content of the live message region.

Exposed Methods

MethodBehavior
focus()Focuses the first available input, textarea, or action button.
blur()Blurs the focused descendant.

Types

import type { FileUploaderFile } from '@talex-touch/tuffex/file-uploader'
import type { MotionFormProps, MotionFormVariant } from '@talex-touch/tuffex/motion-form'

type MotionFormValue = string | number | boolean | (string | number)[] | FileUploaderFile[]
type MotionFormOption = TxSelectOption // { value, label, disabled?, icon?, description? }
// FileUploaderFile: { id, name, size, type, file: File }
// MOTION_FORM_VARIANTS exports the full readonly variant tuple.

MotionFormVariant

Original IDvariantModelEffect
frm1floating-label-inputstring or numberThe label floats up and shrinks on focus or with a value.
frm2input-focus-glowstring or numberA halo spreads on focus and retracts on blur.
frm3password-togglestringThe reveal button toggles plain text and spins the eye; the value is untouched.
frm4search-expandstringWidens within the available space on focus; the icon shifts.
frm5checkbox-drawbooleanChecking draws the tick and pops the box.
frm6radio-scalestring or numberSingle choice; the inner dot springs in.
frm7error-shakestring or numberShakes when error, the error status, or validationKey changes.
frm8success-checkstring or numberRequests validation; success springs in a drawn check.
frm9select-dropdownstring or numberSelect opens with origin-aware scale, offset, and fade.
frm10multi-select-chips(string | number)[]Chips spring in and out; remove buttons update the array.
frm11textarea-auto-growstringGrows with its scroll height, springy and capped.
frm12otp-inputstringFour digit boxes auto-advance and distribute pasted text.
frm13file-upload-dropzoneFileUploaderFile[]Pick or drop files; dragging pulses the ring and lifts the arrow.
frm14range-slidernumberSlider handles pointer and keyboard, with a springy thumb and value tooltip.
frm15form-submit-buttonoptional MotionFormValueMorphs text, spinner, and check from the caller's status.

MotionFormLabels

Defaults are exported as MOTION_FORM_DEFAULT_LABELS; labels overrides any subset.

KeyDefault/type
field'Field'
showPassword, hidePassword, capsLock'Show password', 'Hide password', 'CapsLock is on'
validate, validating, verified, validationError'Validate', 'Validating…', 'Verified', 'Validation failed'
submit, submitting, submitted, submitError'Submit', 'Submitting…', 'Submitted', 'Submission failed'
chooseFiles, dropFiles, fileHint'Choose files', 'Drop files here', 'or click to browse'
searchOptions, noOptions'Search options', 'No options'
otpDigit(index: number) => string; one-based default Digit N of 4
removeOption(label: string) => string; default Remove <label>
removeFile(name: string) => string; default Remove <name>

CSS Variables

Variablemd defaultRole
--tx-mf-height36pxInput and action height; sizes set 26/30/36/42px.
--tx-mf-choice22pxCheckbox and radio mark size; sizes set 16/18/22/24px.
--tx-mf-radius12pxField radius; sizes set 8/10/12/12px.

Colors come from --tx-color-*, --tx-text-color-*, --tx-bg-color, and --tx-border-color-*; motion variables are generated internally and aren't public API.

Overview

  • Input, Select, Checkbox, Radio, Textarea, FileUploader, and Slider own editing, options, drag and drop, and keyboard semantics; this component adds motion and controlled events.
  • Labels sit beside their controls, and useId links labels, helper text, and OTP boxes. The password button is a native button with aria-pressed.
  • Status and errors live in a role="status" aria-live="polite" region; replaying motion never resets focus.
  • OTP accepts paste, autofill, Left/Right, Home/End, Backspace, and Delete; a new external value replaces all four boxes.
  • The chips variant adds one option at a time and never adds a selected option twice.
  • Motion and listeners pause when hidden or KeepAlive-inactive; reduced motion turns off decorative motion only, never input handling or measurement.

Technologies

  • Text transitions use TxTextMorph and curves come from the shared liquid spring resolver; upstream's timed error clearing and fake submit success became caller-owned error and status.
  • Upstream: src/components/forms/AnimatedFormElement.tsx at Amicro commit 43c29ce, MIT, Copyright (c) 2026 SYED SUBHAN UDDIN.
  • Source: packages/tuffex/packages/components/src/motion-form/.
查看源码
packages/tuffex/packages/components/src/motion-form/index.ts