All articles & videos

Enterprise frontend accessibility: put it in the design system

Accessibility in enterprise frontends: , the for banking, keyboard and focus, form errors, and testing in CI.

Adil Ben Moussa
08 November 2026· 5 min
Enterprise frontend accessibility: put it in the design system

Fifty teams build fifty screens, and each one gets its own dialog, its own dropdown and its own way to show an error. Then an audit arrives, and the same keyboard bug has to be fixed fifty times. Accessibility in an enterprise app is won or lost in the shared components, long before the audit.

It is also no longer optional in Europe. The European Accessibility Act (with an exception for microenterprises) applies to consumer banking services and e-commerce services provided to consumers after 28 June 2025. For consumer banking, Annex I asks for identification methods, electronic signatures, security and payment services that are "perceivable, operable, understandable and robust".

The few concepts that matter

WCAG 2.2 AA as the target. MDN calls WCAG 2.2 "the most recent version of the guidelines". Level AA is a good team target because it is concrete enough to test. For banking forms, one criterion matters more than most: 3.3.4 (AA) asks that submissions of financial data "can be reversed, verified, or confirmed", for example with a step where the user reviews and corrects before the submission is final. A transfer confirmation step is accessibility, not only good UX.

Native HTML first, second. 's guide says native elements "capture several standard interaction patterns" and you "should re-use these native elements directly when possible". When you need a widget HTML does not have, MDN puts it plainly: with ARIA "you are responsible for mimicking the equivalent browser behavior in script". A role is a promise you have to keep in code.

Keyboard and focus. For a : focus moves inside on open, Tab stays inside, Escape closes, and on close focus "should be moved back to where it was before it moved into the dialog". In a the route change is the one people forget: Angular's guide suggests updating focus on NavigationEnd and avoiding focus falling back to body.

Forms and errors. Long regulated forms are where users give up. WebAIM's WCAG checklist puts it simply: an input error "is clearly identified", and an important status message "must be announced to screen reader users" even when focus is not on it. In practice: a real <label> per field, errors with role="alert", and on long forms a summary that links to each field.

The carries it. One accessible date picker beats fifty fixes. The shared library is where , contrast and keyboard behaviour are decided once. Angular's gives the building blocks (cdkTrapFocus, LiveAnnouncer), and the guide now points to for such as , menu and tabs. In React, the same job falls to your component library; choose it for its keyboard support.

Fix it in the component once, or fix it in every screen forever.

Testing: tools and people. Automated checks in CI catch the cheap mistakes on every pull request. MDN is clear about their limit: "You can't rely on automated tools alone for determining accessibility problems on your site." A keyboard and pass on the main flows finds the rest.

When to choose what

  • Build or buy the hard widgets: buy or adopt (CDK, Angular Aria, a mature React library) for combobox, date picker and data grid; build only what is specific to your domain.
  • role="alert" or a service: role="alert" for an error next to a field; LiveAnnouncer for something that happened elsewhere ("Transfer sent").
  • Automated or manual: both, always. Automated in every pull request, manual on the flows the law cares about: login, payment, signature.

On Atlas Bank

Atlas Bank's rules file has the line: "A restyle never changes the flow. Labels, button names and role=alert messages are what the URL tests read; keep them, and the tests pass unchanged." Accessibility and tests share the same contract.

The in apps/atlas/src/styles/tokens include a --color-focus role, with a light and a dark value, and apps/atlas/src/styles/base/_document.scss puts a default focus ring on every :focus-visible. npm run check:tokens fails when a component outside the legacy corner uses a raw colour instead of a token.

Atlas also shows the gap. On main, the frozen screen in libs/legacy/transfers/src/lib/transfer.component.html shows its error in a plain <div class="alert alert-danger">, with no role. The beneficiaries form and the new transfer screen of module 5 both use role="alert". Old corners hide old debt.

Atlas already lints its templates for accessibility in CI ('s accessibility rules; the legacy corner switches label-has-associated-control off). What it does not have yet: a check on the rendered page, such as in the end-to-end tests, and a contrast check on the tokens. Both would be small additions; check:tokens today checks where colours live, not whether they contrast.

What I left out, and why

  • , , colour contrast as separate items: they live inside "native HTML first" and "the design system carries it".
  • . One line: an overlay script does not fix the components underneath, so it is not a shortcut.

On Monday

  • Open your design system's dialog and do the four keyboard steps above. Then do the same with your oldest screen.
  • Search for error messages in forms without role="alert" or a live region.
  • If you build for an EU bank or shop, ask who owns the accessibility information the service has to provide. If nobody does, that is the first decision.

For your coding agent

The rules of this article, written for an agent. Paste them into your AGENTS.md, save them as a skill, or point your agent at the file.

For your coding agent Download .md
# Accessibility rules for enterprise apps

Source: https://tt-tech.io/blog/enterprise-frontend-accessibility-design-system
For Angular and React frontends. Add to AGENTS.md or save as a skill. Your project's own rules win where they differ.

## Rules

1. Target WCAG 2.2 level AA.
2. Use native HTML elements first (`<label>`, `<dialog>`, native form controls). Use ARIA only for a widget HTML does not have.
3. When you add an ARIA role, implement in script the keyboard and behaviour the browser would give the native element. A role is a promise you keep in code.
4. Every modal dialog: focus moves inside on open, Tab stays inside (`cdkTrapFocus` in Angular), Escape closes, and on close focus returns to where it was before.
5. On a route change in a single-page app, move focus (in Angular, on `NavigationEnd`). Never let focus fall back to `body`.
6. In forms, give every field a real `<label>`, show field errors with `role="alert"`, and on long forms add an error summary that links to each field.
7. Announce something that happened elsewhere on the page ("Transfer sent") through a live region, `LiveAnnouncer` in Angular.
8. Submissions of financial data need a step where the user reviews and corrects before the submission is final (WCAG 3.3.4).
9. Fix accessibility in the shared design-system component, not in each screen. Focus rings, contrast and keyboard behaviour are decided there once.
10. For combobox, date picker and data grid, adopt a tested building block (Angular CDK, Angular Aria, or a mature React library chosen for its keyboard support). Build only what is specific to the domain.
11. Never add an accessibility overlay script as a fix. It does not fix the components underneath.
12. Run automated accessibility checks in CI, and never report a flow as accessible from automated checks alone. Login, payment and signature also need a manual keyboard and screen reader pass.

## Before you say done

- Run the project's accessibility lint (for example angular-eslint's template accessibility rules) and fix every new error.
- Search the diff for form error messages without `role="alert"` or a live region, and for `role=` attributes. For each role, name the code that implements its keyboard behaviour.
- For every new or changed dialog, list in the pull request where the code handles focus in, Tab, Escape and focus return.
- List the manual keyboard and screen reader checks still needed.

Sources

  1. EUR-Lex, Directive (EU) 2019/882 on the accessibility requirements for products and services, 2019
  2. MDN, Understanding the Web Content Accessibility Guidelines (WCAG)
  3. WebAIM, WebAIM's WCAG 2 Checklist
  4. Angular, Accessibility in Angular
  5. MDN, ARIA
  6. MDN, ARIA: dialog role
  7. MDN, <dialog> HTML dialog element
  8. MDN, Accessibility tooling and assistive technology
Share this article