---
id: accessibility
title: Accessibility
summary: The landmark, the live region, describedBy pointing at your own page, reduced motion.
faces: ["public", "agent"]
section: front-end
group: Customise
order: 70
---
# Accessibility

The checkout is a `region` landmark named "ripper checkout — secure payment" with two live
regions, and only one of them holds text at a time: a visually hidden, polite status region
announces progress, steps and the outcome, and a visible, assertive alert region carries validation
messages and failures. Every field is labelled; Tab order follows the visual order; Enter on the pay
button pays; Escape cancels with `user_cancelled`.

`accessibility.ariaLabel` renames the landmark. `announceErrors: false` keeps the inline errors
and stops announcing errors; progress, steps and the outcome are still announced (`true`, the
default, announces validation once per pass, never per keystroke). `reducedMotion: true` switches the one animation off (so does `prefers-reduced-motion`).

```js run id=a11y-options
const result = await ripper.collect({ amount: 4200, currency: 'GBP', accessibility: { ariaLabel: 'Pay Acme Coffee', announceErrors: true, reducedMotion: false } });
```

`describedBy` names ids on YOUR page. The checkout renders inside its own isolated root, and an id
reference cannot reach out of it, so the runtime does the work for you: the named elements' text is
copied into the checkout and kept in sync as it changes.
`aria-labelledby` is not accepted — the label is `ariaLabel` only. Precedence, stated once: the
React prop wins over the `collect()` option, which wins over the integration's default.

```js run id=a11y-describedby
const result = await ripper.collect({ amount: 4200, currency: 'GBP', accessibility: { describedBy: 'order-summary' } });
```
