Prepared Docs

Prepared Docs

⌘K

    Loading navigation…

User

  1. Blocks
  2. Forms
  3. Accessibility

Forms

Accessibility

Overview

@prepared911/ui-forms delegates per-control semantics to @prepared911/ui-core primitives while owning the react-hook-form wiring: labels, aria-invalid, helper and error text ids, and submit/disable contracts on form shells. Your feature owns schema messages, button copy, async error text, and focus behavior after submit or dismiss.

What the component handles

  • Label association: Form* wrappers pass id, label, and htmlFor through ui-core inputs so every control has a visible or programmatic name.
  • Error display: Invalid fields set aria-invalid and link helper/error text via aria-describedby where the underlying primitive supports it.
  • Native validation off: Form defaults noValidate so browser tooltips do not compete with Zod messages.
  • Submit control: Primary actions use real <button type="submit"> inside the native <form> (or modal confirm wired to handleSubmit).
  • Disabled submit: StandardForm and DrawerForm disable Save when pristine or submitting, preventing silent no-op submits.
  • Modal/drawer focus: ModalForm and DrawerForm use ui-core modal and ui-drawer focus traps while open.

What you must provide

  • Localized validation message keys in Zod schemas; plain English-only strings fail i18n review.
  • Meaningful labels and helper text—don't rely on placeholder alone.
  • Focus management after successful submit (e.g., close drawer or move to list) or failed server validation (i.e., setError + focus first invalid field).
  • Confirm copy for destructive FormActionIntent.Destructive submits.
  • Live-region or status text for debounced autosave (SettingsRow, useDebouncedFieldSubmit) when save outcome matters mid-task.

Keyboard behavior

  • Tab / Shift+Tab: Move through fields, section accordion triggers, and footer actions in DOM order. Don't reorder fields visually without preserving tab sequence.
  • Enter: Submits the form when focus is on a text control (native form behavior). On ModalForm, Enter on the primary field should not double-fire confirm unless intentional.
  • Space: Toggles checkboxes, switches, and segmented items.
  • Escape: Does not dismiss ModalForm (noDismiss). On DrawerForm, Escape/close while dirty routes through the unsaved-change flow.

Semantics and roles

  • Use one <form> per shell—don't nest forms.
  • FormSection accordion triggers are real buttons with expanded/collapsed state. Section titles must be readable without relying on color-only status dots; pair dots with text or aria-label on the trigger when status is critical.
  • FormCombobox and FormSelect inherit listbox/combobox roles from ui-core; keep option labels concise.
  • FormFileUpload announces file count changes; provide clear empty-state copy.

Focus management

  • On failed submit: Move focus to the first field with an error. RHF does not do this automatically; call form.setFocus on the first key in form.formState.errors inside onInvalid.
  • On successful modal submit: ModalForm closes via handleClose; return focus to the element that opened the modal.
  • On drawer dismiss: When DrawerForm shows UnsavedChangesModal, focus stays trapped until the operator confirms discard or returns to edit.
  • After autosave error: Keep focus on the control that failed; surface error in FormHelperText or row-level helper.

Screen reader announcements

  • Validation errors: Error text is rendered in the document; on submit failure, focusing the first invalid field is usually sufficient. For long sectioned forms, consider a polite role="status" summary ("3 fields need attention") when SectionedForm panels are collapsed.
  • Section status: FormSection error dots reflect field errors; ensure that the accordion header text names the section so the dot is not the only cue.
  • Saving: SettingsRow debounced save should expose saving/error state in visible helper text; optional polite live region for "Saved" when the row is easy to miss visually.
  • Unsaved changes: UnsavedChangesModal exposes a heading and Keep editing / Discard actions (no body copy). Ensure button names stay clear.

Reduced motion

Form shells use minimal motion (e.g., accordion expand or drawer slide). Respect prefers-reduced-motion: reduce in any custom field animations; ui-core primitives gate transitions where applicable.

Touch targets

Footer Save/Cancel buttons use default ui-core button sizes (44×44 minimum on touch layouts). Checkbox and switch rows should not shrink hit targets below threshold when labels wrap—preserve vertical padding on SettingsRow.

Known caveats

  • useZodForm validates on blur by default—screen reader users may not hear errors until leaving a field; critical fields can use mode: "onChange" selectively.
  • FormSecret does not wire error UI—add explicit helper text if used for required secrets.
  • ModalForm confirm is a button calling handleSubmit, not a native submit inside the modal footer—test keyboard activation explicitly.
  • Mixing legacy register fields with Form* fields in one form breaks typing and error paths—migrate atomically per field group.

Previous

Forms / API and Development

Next

Crud Page / Usage

On this page

Overview
What the component handles
What you must provide
Keyboard behavior
Semantics and roles
Focus management
Screen reader announcements
Reduced motion
Touch targets
Known caveats