Accessibility, keyboard support and axe auditing
QForm Builder Community 0.1.16 adds a consistent accessibility contract across the catalog, canvas, tree, dialogs and viewing modes.
Keyboard navigation
In the left catalog:
Tabfocuses an item;EnterorSpaceadds it to the form;- the newly added field then receives focus in the canvas.
In the editing canvas:
Tabtraverses field overlays;EnterorSpaceselects the field;Alt+ArrowUpmoves the field upward;Alt+ArrowDownmoves the field downward.
In the tree:
- every business node is focusable;
Alt+ArrowUp/ArrowDowninvokes the same move action as the contextual menu;- focus returns to the moved node.
Copy and delete actions are real QBtn controls with accessible names and direct-child QTooltip components.
Click, selection and drag consistency
The canvas uses one interaction session. A simple click selects the field, while a native drag preserves that selection until drop. Post-drag click suppression is tied to the exact source: it neutralizes the browser-generated synthetic click without blocking selection of another field.
Field overlays, contextual actions and step headers are delegated to their dedicated handlers during capture. They never fall through to generic outside-click cleanup, so consuming the dragged source's synthetic click cannot clear another valid selection first.
Keyboard reordering remains independent from pointer drag and keeps its live announcements, focus restoration and Alt + ArrowUp/ArrowDown alternative.
Announcements and focus restoration
The builder contains two visually hidden live regions:
- a
politeregion for additions, selections and moves; - an
assertiveregion for destructive or high-priority operations.
After closing the Theme Builder, history panel, or import/export dialogs, focus returns to the button that opened the panel.
Custom components nested inside the builder can use the auto-imported composable:
The same composable is available through the public explicit-import subpath:
import { useFormBuilderAccessibility } from '@vevedh/qform-builder-layer/accessibility'const accessibility = useFormBuilderAccessibility()
accessibility.announce('Configuration applied')
await accessibility.focusField('email')The composable is safe outside a FormBuilder: its fallback implementation is a no-op.
Readonly and disabled modes
readonly switches the builder to preview and prevents mutations. disabled disables the relevant actions and controls. Both states are covered by the browser accessibility fixture.
Automated audit
The project uses @axe-core/playwright with WCAG A/AA tags through WCAG 2.2 AA.
bun run accessibility:check
bun run e2e:accessibility
bun run release:browser:checkThe scenario covers:
- the editing builder;
- preview mode;
- the Theme Builder;
- import/export dialogs;
- readonly and disabled modes;
- keyboard addition and reordering;
- focus restoration.
An axe violation fails the test and prints the rule identifier, help text, DOM target and failure summary.
Automation limits
An axe audit does not replace human review. Before a release candidate, also verify:
- reading flow with NVDA or another screen reader;
- relevance of business labels;
- tab-order consistency;
- mouse-free use of complex forms;
- contrast of host-provided custom themes;
- 200% zoom and reflow.
Extension contract
A custom element or panel must:
- use an appropriate native or Quasar control;
- provide an accessible name when visible content is insufficient;
- preserve a visible focus indicator;
- support
EnterandSpacewhen a non-native element behaves as a button; - avoid clickable
divelements without role and keyboard support; - restore focus after closing a modal panel;
- honor
readonly,disabledandprefers-reduced-motion; - add a Playwright scenario whenever a new keyboard workflow is introduced.