# Accessibility Guide

**Status of this document**: new as of v0.38.0, written directly against
the current codebase (roadmap: Fluent Forms competitive comparison,
"Accessibility" — Fluent Forms publishes a guide like this; ChargeForms had
shipped comparable or better concrete fixes but never written one down).
Every claim below is checked against real code (`grep`, the builder's own
accessibility-focused commits, and the shared conditional-logic test
suite) — not memory, and not what "should" be true. Where something is
genuinely unverified (real screen readers, real keyboard-only end-to-end
sessions), that's stated plainly in [§6](#6-known-limitations), not
implied to be fine.

**What this document is not**: a WCAG conformance claim, a VPAT, or the
output of a third-party audit. It's the same kind of thing Fluent Forms'
own accessibility guide is — practical guidance on what's already handled
for you, and what your own form design still needs to get right.

---

## Table of contents

1. [Keyboard support in the Builder](#1-keyboard-support-in-the-builder)
2. [Screen reader labeling](#2-screen-reader-labeling)
3. [The rendered front-end form](#3-the-rendered-front-end-form)
4. [Choosing accessible layout settings](#4-choosing-accessible-layout-settings)
5. [Targeting WCAG 2.1 AA](#5-targeting-wcag-21-aa)
6. [Known limitations](#6-known-limitations)

---

## 1. Keyboard support in the Builder

Building a form should not require a mouse. Concretely, today:

- **Reordering a field on the canvas**: select a field, then
  `Alt+ArrowUp` / `Alt+ArrowDown` moves it up or down within its current
  container — no drag required.
- **Reordering conditional-logic conditions and groups**: the Rule
  Builder has explicit Move Up / Move Down buttons on every condition and
  group, not drag-only reordering.
- **The Tabs field**, both in the Builder and on a real submitted form,
  follows the WAI-ARIA APG tabs pattern in full: `Arrow Left`/`Arrow
  Right` move between tabs, `Home`/`End` jump to the first/last tab, and
  only the active tab sits in the regular tab order (roving `tabindex`).
- **Finding a field type** in the palette: type to filter, no pointer
  needed.
- **Finding anything else** in the admin: `Ctrl+K` (or `Cmd+K` on macOS)
  opens a global command palette — jump to any screen, form, or action
  without navigating menus.
- **Closing a dialog** (e.g. Rename Form): `Escape` closes it, matching
  the WAI-ARIA dialog pattern, not just a click-outside/close-button-only
  interaction.

What is **not yet keyboard-operable** — named honestly rather than
glossed over — is in [§6](#6-known-limitations).

---

## 2. Screen reader labeling

Icon-only controls are the most common screen-reader dead end in form
builders generally: a trash-can glyph with no accessible name announces
as "button" and nothing else. ChargeForms's icon-only controls carry real
`aria-label`s, covering:

- The Field Palette's search and filter controls.
- The Settings Panel's repeatable option editors (Custom Attributes rows,
  Image Choice options, Shipping methods) — each Add/Remove control
  identifies what it adds or removes.
- Section expand/collapse state, via `aria-expanded`.
- The canvas's Floating Toolbar (Edit/Duplicate/Delete/drag) on every
  field.
- Column/pane split-delete controls in multi-column layouts.
- The Rename Form dialog.
- The Vue-rebuilt Forms List's filter/sort/search controls and per-row
  actions (Edit/Duplicate/Delete/status toggle each identify *which* form
  they act on, not just "Edit"/"Delete").
- The Rule Builder's Live Preview result region uses `aria-live`, so
  screen reader users hear evaluation results update as sample values
  change, without needing to re-focus anything.

---

## 3. The rendered front-end form

This is what a real visitor's screen reader or keyboard actually
encounters:

- **Labels are real `<label for="...">` elements**, pointing at the
  input's id — including when that id has been overridden via a field's
  HTML ID Override setting, so `for`/`id` never silently fall out of
  sync.
- **A field-level Tooltip**, when set, is exposed via `aria-label` on a
  small focusable glyph next to the label — not only via the `title`
  attribute. This matters because a `title`-only tooltip is invisible to
  many screen readers unless the exact right combination of hover/focus
  events fires; `aria-label` is announced unconditionally. (Fluent Forms'
  own accessibility guide flags hover-only, "beside label" help text as
  the least accessible placement option for exactly this reason — the
  fix here is to not depend on hover at all for the accessible name.)
- **Required fields** get a visual `*` and the `required` HTML attribute,
  which most screen readers announce on their own.
- **Multi-step forms** announce Next/Previous/Submit with real accessible
  names, not just visual button text relying on surrounding context.

---

## 4. Choosing accessible layout settings

ChargeForms's Global Settings and per-field Advanced settings include a few
choices that affect accessibility more than they might look like they do:

- **Label Placement — prefer Top.** Screen readers process markup in
  source order; a label physically after its input (as some "Right"
  layouts render) can announce in a confusing sequence. Top placement
  avoids this entirely.
- **Help Message Position — prefer "Below Input".** A help message
  placed only as a hover tooltip has the same discoverability problem as
  the field-level Tooltip described in §3 — below-input placement stays
  visible and in-flow for both sighted and screen-reader users.
- **Custom Attributes** (Developer settings) can set `autocomplete` on
  any field — useful for the fields WCAG 1.3.5 ("Identify Input Purpose")
  cares about (email, name, phone, address fields), and unlike some
  competitors this is a real UI field, not something that requires a PHP
  filter to reach.

---

## 5. Targeting WCAG 2.1 AA

The same target Fluent Forms' own guide names is a reasonable one to
point at here too — not because of that guide, but because WCAG 2.1 AA
is the standard most site owners are actually asked to meet. The parts of
it most relevant to a form specifically:

- **1.3.1 Info and Relationships** — real `<label>`/`<fieldset>`
  structure rather than visual-only grouping. ChargeForms's field wrapper
  markup and the Tabs/Accordion fields' semantic containers are built
  with this in mind.
- **1.3.5 Identify Input Purpose** — see the Custom Attributes /
  `autocomplete` note above.
- **3.3.1 Error Identification** and **3.3.2 Labels or Instructions** —
  every field's required/validation state is both visually indicated and
  programmatically exposed (`required`, `aria-*` where applicable).
- **4.1.2 Name, Role, Value** — the icon-labeling sweep in §2 and the
  Tabs field's full ARIA pattern are both direct work toward this
  criterion.
- **Contrast** — this depends on your site's own color/theme choices for
  the form; ChargeForms doesn't hardcode low-contrast text, but the
  4.5:1 (normal text) / 3:1 (large text, input borders) targets are worth
  checking with your actual branding applied.

---

## 6. Known limitations

Stated plainly, matching this project's standing practice of not hiding
open gaps behind confident-sounding prose elsewhere in the docs:

- **Canvas drag-and-drop still has no keyboard alternative for the
  initial placement** of a field from the palette onto the canvas (field
  *reordering*, once placed, is keyboard-operable — see §1).
- **The Rule Builder's and Repeater's drag-and-drop reordering are
  mouse/touch-only** in the sense of *drag* itself — the Rule Builder's
  Move Up/Down buttons (§1) are the keyboard path there, but Repeater row
  reordering has no button equivalent yet.
- **No real screen-reader-plus-browser verification has been performed
  on any of this.** Every check so far is code-level (markup structure,
  ARIA attribute presence, keyboard event handler wiring) in an
  environment without WordPress Playground or Playwright access — not
  an actual session with VoiceOver, NVDA, or JAWS. This is the single
  most important thing to verify before treating any claim in this
  document as fully proven, and matches the same caveat already recorded
  for the conditional logic engine in `FEATURE_STATUS.md`.
- **No VPAT, Accessibility Conformance Report, or third-party audit
  exists** for ChargeForms. This document is internal engineering honesty,
  not a certification.
