BladewindUI: Accessibility

Accessibility

BladewindUI components carry their own ARIA roles and keyboard handling. You do not switch this on and there is no accessible variant of a component to reach for. A Tab is a real tablist, a Toggle announces itself as a switch, and an Accordion header answers to Enter and Space because it is a real disclosure button rather than a div that happens to be clickable.

This page describes what you get, and the few places where only you can supply the missing piece.

Keyboard Support

Every component below is reachable with Tab and operable without a mouse.

Component Keys Behaviour
Select Home End Enter Esc Tab Arrows move the highlight, Home and End jump to the ends of the list, Enter selects, and Esc or Tab closes. Typing jumps to the first item that starts with what you typed.
Tab Home End Left and right move between tabs and wrap around at the ends. Only the selected tab sits in the page tab order, so Tab moves past the tab strip rather than through every tab in it. Disabled tabs are skipped.
Accordion Enter Space Opens and closes the section the header belongs to.
Checkcards Enter Space Selects the focused card. These were previously reachable only with a mouse.
Rating Home End Right and up step the rating up, left and down step it down, and Home and End jump to 0 and 5. Only a clickable rating is focusable. See Rating below.
Dropmenu Enter Space Opens the menu from the trigger.
Slider Handled by the browser. The slider is a native range input, so it was always operable. What it lacked was a name, which aria_label now supplies.

What Each Component Reports

Roles and states are kept in step with what is actually on screen. Opening an accordion section updates its aria-expanded, switching a tab updates aria-selected, and moving the highlight in a select updates aria-activedescendant. They cannot drift from the visible state, including when opening one accordion item closes another.

Component Reported as
Select A combobox trigger with aria-expanded, aria-required and aria-disabled, over a listbox of options. The empty-state item is marked disabled so it is not offered as a choice.
Dropmenu A button trigger with aria-haspopup="menu", over a menu of menuitems. Headers are presentational and dividers are separators.
Tab tablist, tab and tabpanel, each tab tied to its panel both ways.
Accordion A button header with aria-expanded, controlling a labelled region.
Toggle switch with aria-checked. It was always a real checkbox, so it was operable; it just announced itself as the wrong kind of control.
Checkcards A group of checkbox cards, each with aria-checked.
Rating slider when clickable, img with a text alternative when not. See below.
Alert Errors and warnings are an assertive alert. Info and success are a polite status, so a success message does not interrupt whatever is being read.
Notification A polite status region on the container, since notifications are injected after the page has settled.

Read-only And Clickable Ratings

A rating is two different controls depending on clickable, and it reports itself accordingly.

A clickable rating is a focusable slider with aria-valuemin, aria-valuemax and aria-valuenow, operable with the arrow keys listed above. A read-only rating is not focusable, because there is nothing to operate. It is exposed as an image with a text alternative, so it reads as "4 out of 5" rather than as five anonymous stars.

What You Need To Supply

Three things cannot be worked out from the markup, because only you know the answer.

Icon-only dropmenu triggers

The common dropmenu trigger is a bare icon, which reaches a screen reader as nothing at all. Give it a name with trigger_label.

        
            <x-bladewind::dropmenu trigger_label="Row actions">...</x-bladewind::dropmenu>
        
    

Icon-only buttons

A button with no visible text takes its accessible name from title, which is the attribute most people already set on these. An explicit aria-label always wins if you would rather be exact.

        
            <x-bladewind::button.circle title="Delete user" />

            <x-bladewind::button.circle aria-label="Delete user" />
        
    

Sliders

Slider takes an aria_label. It defaults to a translatable string, which is better than nothing but says nothing about what the slider adjusts. Set it where you have more than one on a page.

        
            <x-bladewind::slider aria_label="Maximum price" />
        
    

Keyboard Support Needs The JavaScript

Roles and states are rendered into the markup and are there whatever else happens. The key handling is not: it lives in helpers.js, which every component assumes, and in the per component scripts. If a component is reachable but does not answer to the keys above, check that @bladewindScripts is in your layout. See First-time setup.

Under a strict Content Security Policy this still works. No component attaches its behaviour with an inline onclick. See Content Security Policy.