Skip to main content
Skip to main content

Accessibility

Forge components are built and tested against WCAG 2.2 levels A and AA, but a conformant component can still be assembled into an inconformant page.

Web accessibility means building products usable by everyone, including people with visual, auditory, motor, or cognitive disabilities—many of whom rely on assistive technologies like screen readers, magnifiers, and keyboard-only navigation.

Several laws apply directly to the products our customers ship, and all of them reference the Web Content Accessibility Guidelines (WCAG):

  • Americans with Disabilities Act (ADA): A broad civil rights law applying to public and business websites.
  • Section 508 of the Rehabilitation Act: Mandates accessible digital technology for federal agencies and contractors.
  • European Accessibility Act (EAA): Effective June 28, 2025, covering e-commerce, banking, and smartphones across the EU with clear, uniform requirements rather than the ADA’s broader interpretation. It applies to U.S. companies operating in Europe.

Shared responsibility

Every accessibility requirement falls into one of three categories.

  • Forge provides: Handled inside the component. Use it as documented and this criterion is met.
  • Shared: Forge handles part of it. The rest depends on what you slot into the component.
  • Your responsibility: Depends on your content, page structure, or application logic. Forge can’t satisfy it for you.

Forge owns the component, you own the composition. A button that meets contrast requirements can still fail on a background Forge never tested. A select with a correct listbox still fails if you leave off the label.

Designing accessibly

Forge’s token system encodes contrast requirements, font sizing, and spacing across both themes. Using alias tokens rather than raw values is the easiest way to stay conformant.

Color tokens are designed in tested pairs—the on- tokens name which surface they belong on. --jh-color-content-on-primary-enabled is meant for --jh-color-content-primary-enabled and nothing else. Overriding one half of a pair moves you outside the tested combination, so recheck contrast if you do, in both themes.

Three things tokens can’t decide for you:

  • Never rely on color alone. If color carries meaning—a negative notification, an error state—that meaning has to appear in text or an icon too.
  • Focus order follows visual order. Reordering with CSS without reordering the DOM breaks it. Focus must also stay visible when scrolled, so watch sticky headers and footers.
  • Localized strings run up to 40% longer. Layouts that fit in English may not fit translated.

Building accessibly

Native HTML elements come with built-in assistive technology support—roles, keyboard interaction, focus behavior. Web components don’t, and the Shadow DOM can hide a component’s structure from assistive technology. Forge closes that gap two ways.

ElementInternals lets custom elements participate in the browser’s Accessibility Object Model, giving Forge components default accessibility properties that can be overridden per component.

The accessible-* namespace solves ARIA attributes being blocked at the Shadow DOM boundary. Set accessible-label on a Forge component and it’s mapped to the correct aria-* attribute inside.

<jh-button accessible-label="Print"><jh-icon-printer></jh-icon-printer></jh-button>

Reach for this whenever a control needs a name it doesn’t get from its content. Several components accept an accessible label and default to nothing—icon-only controls and dismiss buttons ship unnamed unless you set one.

Status messages and live regions

Forge does not provide live regions. Components that display new or changing information—notifications, badges with counts, toasts, validation messages—render the content, but announcing it is the application’s job.

When content appears without focus moving to it, it needs a live region:

  • role="status": For a successful action or state change.
  • role="alert": For an error or something needing immediate attention.

The region must exist in the DOM before the content is inserted. Creating both at once usually announces nothing. This is the most common accessibility gap across Forge consumers—if you’re showing a result the user didn’t navigate to, assume you need one.

Forms and errors

  • Every field needs a visible, associated label. A placeholder is not a label.
  • Error messages should say what’s wrong and how to fix it. Forge renders your error text; the wording is yours.
  • Announce validation results—that’s a live region.
  • Prefer keeping a control enabled and explaining the failure over disabling it. Disabled controls leave the tab order and are invisible to most screen reader users.

Beyond the design system

Accessible components don’t make an accessible page. Page-level structure is always yours.

  • Semantic HTML: Use <header>, <nav>, <main>, and <article> to structure content meaningfully.
  • Heading levels: Nest without skipping. Components don’t know their surroundings.
  • Keyboard: Everything reachable, focus visible, no traps. Focus returns to the opener when an overlay closes.
  • Alt text: Convey content or purpose for every image.
  • Descriptive links: Link text should describe its destination. Never “click here.”

Don’t wrap interactive components in another interactive element, and don’t override component roles unless you know exactly why.

Testing

Every Forge component is tested against WCAG 2.2 levels A and AA using Axe-core for automated checks, manual testing with screen readers and magnifiers across supported browsers, and manual keyboard testing.

Run Axe-core or equivalent in CI on your own work. It reliably catches missing alt text, contrast failures, missing form labels, invalid ARIA, and duplicate IDs. But automated tools only catch around 57% of accessibility issues. Passing a scan is a floor, not a result. The rest needs a person.

  • Keyboard pass: Tab the whole flow. Can you reach, activate, and escape everything? Is focus visible at every step?
  • Screen reader pass: Does each control announce a meaningful name and role? Do status changes get announced?
  • Zoom pass: 200% zoom, and 320px width without horizontal scrolling.
  • Content pass: Do labels and errors make sense read aloud, without the visual context?