Skip to content
BigBang

Popular

    ↑↓Navigate↵OpenEscClose
    TR

    Foundations

    Accessibility

    Every component and screen targets WCAG 2.2 AA. This page covers the principles, a checklist per component type, the keyboard map, focus and contrast rules, and screen reader testing.

    BigBang targets WCAG 2.2 AA on every surface (D-11). The target is the same for components, patterns, screen templates and this documentation site. The conformance report (ACR) states the measured result; it makes no legal-compliance claim.

    Accessibility is delivered in two layers:

    1. Component: Role, name, keyboard, focus, contrast and motion are solved inside the component. Each component’s Accessibility tab describes them.
    2. Screen: Heading order, page title, error summary, focus flow and content language belong to the team building the screen. A component cannot solve them on its own.
    Principle What it means Example
    Native element first When the browser has a ready element (<button>, <input>, <a>), use it. ARIA only fills in missing meaning. Button renders a native <button>; there is no <div role="button">.
    The keyboard does everything Everything done with a mouse can be done with a keyboard, in the same order as on screen. A dialog closes with Esc and focus returns to the element that opened it.
    Colour never speaks alone Status, errors and selection also show as text or shape. Badge writes the status next to its colour.
    Motion is optional With reduced motion, motion is not deleted; it turns into a calm transition. The loading indicator spins; with reduced motion it stays still.
    Equal access in both languages The Turkish and English interface carry the same roles, names and announcements. Button’s loading text comes from the ui.* catalogue in both languages.

    Before releasing a component or screen, go through the list that fits its type from top to bottom. Each row maps to a WCAG 2.2 success criterion.

    Criterion Check
    2.1.1 Keyboard Enter and Space start the action; a link opens only with Enter.
    2.4.4 Link purpose Link text read on its own says where it goes; no “click here”.
    2.4.7 Focus visible A 2 px focus ring shows when reached by keyboard.
    2.5.3 Label in name The accessible name starts with the visible label.
    2.5.8 Target size The target is at least 24 × 24 CSS px or has 24 px of space around it.
    4.1.2 Name, role, value An icon-only button has a label.
    Criterion Check
    1.3.1 Info and relationships Every field has a visible <label>; placeholder text never replaces it.
    1.3.5 Identify input purpose Personal data fields carry the right autocomplete value.
    3.3.1 Error identification The error is written as text and tied to the field with aria-describedby.
    3.3.2 Labels or instructions Required fields are marked; format rules are written under the field.
    3.3.7 Redundant entry Information entered earlier in the same process is not asked for again.
    1.4.11 Non-text contrast The field border has at least 3:1 against the surface.

    Status and feedback (Badge, notification, progress)

    Section titled “Status and feedback (Badge, notification, progress)”
    Criterion Check
    1.4.1 Use of colour Status is given as text, not by colour alone.
    4.1.3 Status messages A message that appears later is read once in a polite live region; an urgent error is read with alert.
    2.2.1 Timing adjustable A message that closes by itself can be extended, or also stays in a permanent place.
    2.2.2 Pause, stop, hide Motion lasting longer than 5 seconds can be stopped.
    Criterion Check
    2.1.2 No keyboard trap Esc closes the overlay; focus cycles inside it but there is always a way out.
    2.4.3 Focus order On open, focus moves to the first meaningful element; on close, it returns to the opener.
    2.4.11 Focus not obscured (minimum) Sticky headers and overlays do not cover the focused element.
    1.4.13 Content on hover or focus A tooltip closes with Esc, stays open while hovered and does not vanish on its own.
    4.1.2 Name, role, value A dialog takes its name from its heading (aria-labelledby).
    Criterion Check
    2.4.1 Bypass blocks A skip link to the main content sits at the top of the page.
    2.4.2 Page titled Every screen has its own <title>.
    2.4.8 Location The selected menu item carries aria-current="page".
    3.2.3 Consistent navigation The menu is in the same order on every screen.
    Criterion Check
    1.3.1 Info and relationships Tables use <th> and scope; a sorted column carries aria-sort.
    1.1.1 Non-text content Every chart has a table or text summary of the same data next to it.
    1.4.1 Use of colour Series are told apart by line pattern, marker or direct label as well as colour.
    1.4.10 Reflow A wide table scrolls horizontally inside itself at 320 CSS px; the page does not.
    Criterion Check
    1.1.1 Non-text content Decorative icons and illustrations carry aria-hidden="true" and an empty alt; a meaningful icon has a name.
    1.4.11 Non-text contrast A meaningful icon has at least 3:1 against its background.
    1.4.5 Images of text Images contain no text.

    This table is generated from the component register (apps/docs/src/data/components.ts). When a new component is registered, its rows appear here on their own.

    ComponentKeyBehaviour
    Badge-Takes no focus; has no keys of its own.
    ButtonTabMoves focus; skipped when disabled.
    EnterStarts the action or submits the form.
    SpaceStarts the action.
    TextInputTabFocuses the field; skipped when disabled.
    Shift + TabGoes back to the previous field.
    Typing keysEnter the value.
    NumberFieldUp / Down arrowChanges the value by one step.
    Page Up / Page DownChanges the value by a large step.
    Home / EndJumps to the minimum or maximum.
    PasswordInputEnter / SpaceOn the eye button, shows or hides the value.
    SearchInputEnterSubmits the search.
    EscapeClears the value.
    OtpInputLeft / Right arrowMoves between boxes.
    BackspaceDeletes a character and goes back.
    PhoneInputEnter / Space / Down arrowOpens the country list.
    EscapeCloses the list.
    CalendarArrow keysMove between days and weeks.
    Page Up / Page DownPrevious or next month; with Shift, year.
    Home / EndFirst or last day of the week.
    Enter / SpaceSelects the day.
    DatePickerDigitsFill the segment and move on.
    Up / Down arrowStep the segment up or down.
    Left / Right arrowMove between segments.
    BackspaceClears the segment.
    EscapeCloses the calendar.
    TimeFieldDigitsFill the segment and move on.
    Up / Down arrowStep the segment, wrapping at the ends.
    Left / Right arrowMove between segments.
    BackspaceClears the segment.
    DateRangePickerDigitsFill a segment; the end date follows the start.
    Up / Down arrowStep a segment; move through presets.
    Enter / SpacePick a range end in the calendar.
    EscapeCloses the calendar.
    SliderArrow keysOne step up or down.
    Page Up / Page DownA large step; Shift + arrow too.
    Home / EndLowest or highest value.
    RadioCardTabEnters the group on the selected card.
    Arrow keysSelect the previous or next card.
    SpaceSelects the focused card.
    FileDropzoneTabTo the file input, then the Remove buttons in the list.
    Enter / SpaceOpens the file chooser.
    FormEnterSubmits the form from a field.
    TabMoves between the summary links.
    StepperTabTo complete step buttons, then Back and Next.
    Enter / SpaceReturns to a step or runs the button.
    SaveBarTabTo Discard and Save; skipped while closed.
    TimelineTabOnly to links and buttons inside events.
    CopyEnter, SpaceCopies the value.
    MaskedValueEnter, SpaceOn the show toggle, reveals or hides the value.
    MoneyText-Takes no focus; has no keys of its own.
    AmountInputDigits, comma, pointType the amount; letters are dropped.
    TabLeaves the field and formats the amount (1,234.50).
    IbanInputDigitsType the IBAN; spaces are added for you and the caret stays in place.
    TabLeaves the field; an incomplete IBAN gets a message.
    DateTimeText-Takes no focus; has no keys of its own.
    CountdownTimer-Takes no focus; has no keys of its own.
    ConsentBlockTabTo the text region, the link and the checkbox.
    Up, Down, Page Up, Page DownScroll in the text region.
    SpaceChecks the box.
    NativeSelectSpace, Alt + DownOpen the browser's list.
    Up, Down, letter keysChange the option.
    CodeBlockTabTo the copy button and the scroll region.
    Left, RightScroll long lines in the scroll region.
    PreviewCardTabFocus the link; the preview opens after the delay.
    EnterFollow the link.
    EscapeClose the preview.
    MonthPickerArrow keysMove between cells.
    Page Up, Page DownPrevious or next page.
    Enter, SpaceChoose the cell.
    EscapeClose the grid.
    YearPickerArrow keysMove between cells.
    Page Up, Page DownPrevious or next page.
    Enter, SpaceChoose the cell.
    EscapeClose the grid.
    AutocompleteUp, DownHighlight suggestions.
    EnterWrite the highlighted suggestion into the field.
    EscapeClose the list.
    DateTimePickerTabTo the date segments, the calendar button and the time segments.
    Up, Down, digitsChange the segment value.
    ContextMenuUp, DownMove between items.
    Enter, SpaceRun the item.
    Right, LeftOpen or close a submenu.
    EscapeClose the menu.
    PopconfirmTabBetween the cancel and confirm buttons.
    Enter, SpacePress the focused button.
    EscapeCancel and close.
    InlineEditEnterOpen the field from the edit button; save in the field.
    EscapeDrop the change and close.
    AnchorTabMove between the links.
    EnterGo to the section.

    Keys every component follows:

    Key Behaviour
    Tab / Shift + Tab Moves to the next or previous focusable element.
    Esc Closes the open overlay and returns focus to its opener.
    Arrow keys Move inside composite widgets (tabs, menu, radio group). A composite widget is a single stop in the Tab order.
    Home / End Go to the first or last item in a composite widget.

    Do not use a positive tabindex. Focus order comes from DOM order.

    • The focus ring is drawn in color-focus-ring, 2 px thick (border-width-focus) and 2 px outside the element.
    • The ring shows only when reached by keyboard (:focus-visible). It does not show on mouse click; in fields the text caret already shows the position.
    • The ring is drawn as an outline, not a border, so it also shows in Windows high contrast mode.
    • Sticky headers, bottom bars and notifications never cover the focused element (2.4.11). Give scroll containers scroll-padding.
    • When an overlay closes, a row is deleted or a page opens, focus moves to a deliberate place: the opener, the next row or the page heading.
    Primary button
    DoThe ring is drawn outside the element with space around it; it is never clipped.
    focus:outline-none
    Don'tRemoving the focus ring makes keyboard users lose their place.

    The ratios below are computed from the selected brand’s built tokens for light and dark mode. Switch the brand and the table changes with it. The build gate is the packages/tokens/test/contrast.test.mjs test; if a pair falls below the threshold, the brand does not build (BRAND-07).

    Foreground / backgroundSampleLight modeDark mode
    text-default
    surface-default
    Aa16.73:1 Pass16.73:1 Pass16.73:1 Pass15.97:1 Pass15.97:1 Pass15.97:1 Pass
    text-subtle
    surface-default
    Aa9.67:1 Pass9.67:1 Pass9.67:1 Pass11.24:1 Pass11.24:1 Pass11.24:1 Pass
    text-subtlest
    surface-raised
    Aa7.81:1 Pass7.81:1 Pass7.81:1 Pass5.85:1 Pass5.85:1 Pass5.85:1 Pass
    text-placeholder
    surface-raised
    Aa4.74:1 Pass4.74:1 Pass4.74:1 Pass5.85:1 Pass5.85:1 Pass5.85:1 Pass
    text-link
    surface-default
    Aa7.57:1 Pass16.73:1 Pass16.73:1 Pass7.70:1 Pass15.97:1 Pass15.97:1 Pass
    action-on-primary-default
    action-primary-default
    Aa5.92:1 Pass17.17:1 Pass17.17:1 Pass9.15:1 Pass14.23:1 Pass14.23:1 Pass
    action-on-danger-default
    action-danger-default
    Aa6.45:1 Pass6.45:1 Pass6.45:1 Pass9.73:1 Pass9.73:1 Pass9.73:1 Pass
    status-success-foreground
    status-success-background
    Aa7.09:1 Pass7.09:1 Pass7.09:1 Pass10.48:1 Pass10.48:1 Pass10.48:1 Pass
    status-warning-foreground
    status-warning-background
    Aa7.41:1 Pass7.41:1 Pass7.41:1 Pass10.48:1 Pass10.48:1 Pass10.48:1 Pass
    status-danger-foreground
    status-danger-background
    Aa7.68:1 Pass7.68:1 Pass7.68:1 Pass10.54:1 Pass10.54:1 Pass10.54:1 Pass
    status-info-foreground
    status-info-background
    Aa7.28:1 Pass7.28:1 Pass7.28:1 Pass10.44:1 Pass10.44:1 Pass10.44:1 Pass
    data-positive
    surface-raised
    Aa5.68:1 Pass5.68:1 Pass5.68:1 Pass10.21:1 Pass10.21:1 Pass10.21:1 Pass
    data-negative
    surface-raised
    Aa6.45:1 Pass6.45:1 Pass6.45:1 Pass9.60:1 Pass9.60:1 Pass9.60:1 Pass

    Minimum: 4.5:1

    Foreground / backgroundSampleLight modeDark mode
    border-input
    surface-raised
    Aa3.36:1 Pass3.36:1 Pass3.36:1 Pass3.19:1 Pass3.19:1 Pass3.19:1 Pass
    focus-ring
    surface-raised
    Aa5.92:1 Pass4.74:1 Pass4.74:1 Pass6.99:1 Pass4.50:1 Pass4.50:1 Pass
    border-focus
    surface-default
    Aa5.52:1 Pass16.73:1 Pass16.73:1 Pass7.70:1 Pass13.23:1 Pass13.23:1 Pass
    icon-default
    surface-default
    Aa14.12:1 Pass14.12:1 Pass14.12:1 Pass15.29:1 Pass15.29:1 Pass15.29:1 Pass
    icon-subtle
    surface-raised
    Aa4.74:1 Pass4.74:1 Pass4.74:1 Pass5.85:1 Pass5.85:1 Pass5.85:1 Pass
    icon-danger
    surface-raised
    Aa5.04:1 Pass5.04:1 Pass5.04:1 Pass7.43:1 Pass7.43:1 Pass7.43:1 Pass
    icon-success
    surface-raised
    Aa4.39:1 Pass4.39:1 Pass4.39:1 Pass8.19:1 Pass8.19:1 Pass8.19:1 Pass
    action-primary-default
    surface-default
    Aa5.52:1 Pass16.73:1 Pass16.73:1 Pass7.70:1 Pass13.23:1 Pass13.23:1 Pass

    Minimum: 3:1

    Ratios are not rounded; 4.49:1 fails. Logos are exempt. Decorative lines (border-default, border-subtle) do not identify a control, so they do not need 3:1.

    Every pointer target is at least 24 × 24 CSS px or has 24 px of empty space around it (2.5.8). Primary controls are 40 px high on desktop and 48 px at the 390 px breakpoint. Links inside running text are exempt.

    • At 200 % zoom, the screen loses no content or function (1.4.4).
    • At 320 CSS px width (400 % at 1280 px) the page does not scroll horizontally; only two-dimensional content such as tables and charts scrolls inside itself (1.4.10).
    • Text is not cut off when line height goes to 1.5, paragraph spacing to 2, letter spacing to 0.12 and word spacing to 0.16 times the font size (1.4.12). Do not give text boxes a fixed height.
    • Amounts, IBANs, reference numbers, dates and error text are never truncated; when they do not fit, they wrap (I18N-16).

    When motion is reduced in the operating system or data-motion="reduce" is set in the product, duration tokens drop to 0-1 ms. Motion is not deleted; a short opacity transition (at most 110 ms) takes its place. Success marks appear still. Details are on the Motion page.

    • Motion longer than 5 seconds can be stopped; only the loading indicator loops without end (2.2.2).
    • Nothing flashes more than three times per second (2.3.1).
    • Parallax, moving backgrounds and autoplaying video are not used in product screens.

    Automated tests find only part of the problems. Before release, every component is tested by hand with the pairings below; the date goes into the a11yTested field in components.ts.

    Screen reader Browser Platform Required
    NVDA Firefox and Chrome Windows Yes
    VoiceOver Safari macOS Yes
    VoiceOver Safari iOS (390 px) Yes
    TalkBack Chrome Android For Android apps
    JAWS Chrome Windows When the customer asks
    1. Go through the page from start to end with the keyboard only. Note that every focus stop is visible and the order makes sense.
    2. Turn on the screen reader and reach the component with Tab. Write down the name, role and state read out (selected, expanded, disabled, invalid).
    3. Reach the same component in reading mode (browse mode in NVDA, VO + arrow keys in VoiceOver). The text read out must be the same.
    4. Trigger every state of the component: loading, error, success, open and closed. Check that each change is announced once and with the right priority.
    5. Switch the interface language to English and repeat steps 2-4. The language read out must match the page’s lang.
    6. Open each finding as an issue in the repository: date, screen reader and version, browser and version, finding.

    Write the expected output in quotes, in the order the screen reader reads it. Example: “Save, button”. Screen readers may use a different order; as long as name and role are the same, a difference in order is not a defect.

    • packages/ui tests check each component in jsdom for keyboard, focus and announcements.
    • Storybook stories are scanned with axe; the target is violations = 0. axe “incomplete” results are closed by hand.
    • On screen templates, Playwright and axe run for every route and state (A11Y-01..20).
    • If an accessibility blocker is found in sign-in, one-time password, confirmation or consent flows, the release does not ship.

    Do not replace the label with a placeholder

    Section titled “Do not replace the label with a placeholder”
    <TextInput label=“Email address” />
    DoThe visible label stays while typing; the screen reader reads the name from it.
    <input placeholder=“Email address” />
    Don'tA placeholder disappears as soon as typing starts and has low contrast.
    <IconButton icon=“x” label=“Close” />
    DoThe screen reader reads the icon's meaning from its name.
    <button><XIcon /></button>
    Don'tAn icon button without a name is read only as "button".