Integration demo

Conditional Fields Integration

Connect conditional form sections with A11y Form Validator so hidden fields do not block submission, while visible follow-up fields still get accessible errors and summary links.

Back to demo gallery

Scenario

A workspace operations team collects access requests. The base form stays short, but enterprise billing, security review, and external collaborator details become required only when the requester chooses those paths.

User goal: submit a request without hidden fields causing validation errors, and still get clear guidance when visible conditional fields are incomplete.

Try it

  • Submit the untouched form and follow the summary links to visible required fields.
  • Choose Enterprise and submit without billing details to see visible-only required errors.
  • Turn on Security review, type a short reason, and leave the field to trigger the minlength message.
  • Hide a section that has errors and confirm it no longer blocks validation after the refresh.
  • Use the server-response button to preview external field and form errors.

Example

The page-level conditional adapter follows the a11y-conditional-fields integration pattern: toggle hidden sections, disable hidden controls, refresh the validator, and revalidate after a user has already attempted validation.

Workspace access request

Hidden sections are marked hidden and their fields are disabled, so the validator skips them until they become visible again.

Use the email that should receive access updates.

Example: customer-success-team.

No optional sections are visible.

Visible sections: none | Field errors: 0 | Form errors: 0

Accessibility notes

  • The form uses native labels, a real select, checkboxes, labelled sections, and submit/reset buttons.
  • Hidden conditional sections use hidden, disabled controls, and visible-only required attributes so they are ignored by validation and submission.
  • Conditional changes dispatch an a11y-conditional-fields:change event; the validator calls refresh() so field state matches the visible DOM.
  • After validation has run, showing or hiding a section revalidates the visible fields and updates the summary.
  • The status and output elements report conditional changes, validation results, reset state, and simulated server errors.
  • Keyboard behavior remains native: Tab reaches visible controls and summary links, Space toggles checkboxes, and Escape collapses a conditional section when focus is inside it.
  • The demo avoids motion-dependent behavior and uses the shared reduced-motion and forced-colors CSS rules.
  • Limitation: final product forms should still be tested with target browsers and assistive technologies.

Developer notes

This repository stays dependency-free, so the live page includes a small demo-only adapter with the same selectors and event shape. In an application, install a11y-conditional-fields and import its runtime directly.

Conditional markup

<form data-a11y-conditional-fields data-a11y-form-validator>
  <select data-condition-select required>
    <option value="">Choose a plan</option>
    <option value="enterprise" data-condition-show="enterprise-billing">
      Enterprise
    </option>
  </select>

  <section id="enterprise-billing" data-condition-target hidden>
    <input name="billingContact" type="email" data-required-when-visible>
  </section>
</form>

Integration script

import { createConditionalFields } from "a11y-conditional-fields";
import {
  createDefaultPreset,
  createFormValidator
} from "a11y-form-validator";

const conditionalFields = createConditionalFields(form, {
  collapseOnEscape: true,
  disableWhenHidden: true
});

const validator = createFormValidator(form, {
  ...createDefaultPreset(),
  validateOn: ["submit", "blur", "input", "change"]
});

let validationHasRun = false;

form.addEventListener("a11y-form-validator:after-validate", () => {
  validationHasRun = true;
});

form.addEventListener("a11y-conditional-fields:change", async () => {
  validator.refresh();

  if (validationHasRun) {
    await validator.validate({ reason: "conditional-change" });
  }
});