Accessibility
What the components guarantee for WCAG 2.2 and what remains the project's responsibility.
On this page
Systhema holds the markup of its components and templates to WCAG 2.2: semantics, ARIA, keyboard use, forms, media and motion. Some criteria depend on decisions only your project makes, such as color contrast, target sizes and the words you write. This page lists what the components handle and what stays with you.
What Systhema handles and what you ownLink to this section
| Area | Systhema | Your project |
|---|---|---|
| Page structure | Skip link, <main>, <html lang> in the templates; real heading elements | A logical heading outline; landmarks in layouts you write yourself |
| Names and labels | One accessible name on every icon-only control; decorative icons hidden | Meaningful link text, alt text, labels you pass as props |
| Keyboard and focus | Menus, accordions and dialogs manage focus, inert and Escape | Custom widgets you build |
| Forms | Descriptions, errors and groups wired with ARIA | Clear labels and error messages |
| Motion | Reveals and parallax respect prefers-reduced-motion | Your own animations |
| Color and size | Token-driven, so one change fixes every component | Contrast ratios and target sizes in your tokens |
| Media | Titles on embeds, play buttons only where something plays | Captions and transcripts for video and audio |
Landmarks and the skip linkLink to this section
The Payload page templates render <main id="main-content">, and RootLayout renders a skip link to it as the first element in <body> and sets <html lang> to the active locale. In your own layouts, add the skip-link class to a link to #main-content and give the page's main content that id; the class ships in the base layer, so it works whatever Tailwind scans. See Accessibility utilities.
HeadingsLink to this section
Hero titles and the rich-text headings the editor produces are real <h1>–<h6> elements (Heading), not styled divs, so the outline depends only on the levels you and your editors pick. Post cards use <h3> and the highlight card <h2> by default.
Icons and icon-only controlsLink to this section
- Decorative icons (
ButtonIcon,ChipIcon, the accordion icon, the share glyphs) render witharia-hidden="true", and inline SVGs also getfocusable="false". Passaria-hidden={false}and a label for an icon that carries meaning. - Icon-only controls (carousel and gallery navigation, menu toggles, social and share links) have exactly one accessible name: visually hidden text (
sr-only!) or anaria-label, never both, because anaria-labelreplaces the inner text. - The Payload Button and Chip blocks can hide their title visually and keep it for screen readers, and a linked Icon block always has a name (its label, or one derived from the link's domain).
What you pass in is yours to get right: alt text, link text that names the destination, and translated labels (labels props, the frontend message catalogs).
Links that open a new tabLink to this section
Links with target="_blank" get rel="noopener noreferrer" and an "(opens in new tab)" cue: visually hidden text on a text link, or part of the aria-label on an icon-only link. See Link.
Keyboard and menusLink to this section
- The header's mobile menu keeps
aria-expandedin sync, makes the closed menu and, while it is open, the rest of the pageinert, moves focus into the menu and back, and closes onEscape. The current page's link hasaria-current="page". See Header. - Collapsed accordion content is
inert. See Accordion. MediaWrapperis a focusable button only when it wraps something playable, so a still image is never announced as "Play video".
FormsLink to this section
The form fields connect each control to its description and error with aria-describedby, set aria-invalid on a failed field, give radio and checkbox groups a role and a label (aria-labelledby), and announce errors with role="alert". Email and phone fields set autoComplete to email and tel. The archive filter is a role="search" form with labelled dropdowns and named remove buttons.
Lists and countersLink to this section
Footer link collections are real lists (<ul>), with display: contents so the layout is unchanged. The gallery's slide counter announces "current / total" images in a status region; see Gallery.
Content that changes without a page load announces itself: PostsList sets aria-busy while loading and reports loading and the running count in a status region, and its empty state is a live region.
Reduced motionLink to this section
For visitors who prefer reduced motion, every reveal shows its end state at once (never opacity: 0, with or without JavaScript), and the parallax engine writes no transform. Both follow a change of the preference without a reload. Animations you write yourself need their own prefers-reduced-motion rule. See Motion.
Color, contrast and target sizeLink to this section
Every color and size comes from your tokens, so contrast and target size are decided in Figma and in customTokens, not in the components. Check text and interactive colors in every theme against WCAG's contrast ratios (4.5:1 for body text, 3:1 for large text and UI boundaries), including muted text such as foundations.text-muted, and keep touch targets at least 24 by 24 CSS pixels. Fixing a token fixes every component that uses it. See Themes and backgrounds.
Embeds and viewportLink to this section
Google Maps embeds render with a title. The scaffolded root layouts never set maximumScale or userScalable in the viewport, so visitors can pinch-zoom; keep it that way in layouts you write. Video blocks have no caption track or caption upload yet, so provide captions or a transcript another way when a video has speech.