Accessibility

Native elements provide the baseline. Custom widgets follow WAI-ARIA Authoring Practices for semantics, names, keyboard behavior, and focus.

// Controls without visible text take a name
<Switch aria-label="Notifications" />
<Slider aria-label="Volume" />
<Progress label="Uploading" value={40} />
<Spinner label="Loading" />
<LineChart aria-label="Sheets per day" … />

// Field wires label, hint, and error to the control
<Field>
  <FieldLabel htmlFor="email">E-mail</FieldLabel>
  <Input plain id="email" type="email" />
  <FieldHint>We reply within a day.</FieldHint>
  <FieldError>Enter a valid address.</FieldError>
</Field>

// Dialog titles are h2 and name the dialog; the close button gets a label
<Dialog open={open} onClose={close} closeLabel="Close">
  <DialogTitle>Remove this item?</DialogTitle>
  <DialogBody>This can't be undone.</DialogBody>
</Dialog>

Components with visible text name themselves. Components without it (Switch, Slider, icon buttons, charts) accept aria-label or aria-labelledby and pass it to the element that carries the role. Field binds hint and error to its control with aria-describedby and sets aria-invalid while an error is mounted. Dialog, Sheet, and Drawer title themselves from their Title part and describe themselves from Body. Alert is a note by default; pass live only when it appears in response to something.

// vitest, jsdom
import { render } from "@testing-library/react";
import { axe } from "vitest-axe";
import { Select } from "@noorddev/vlak-react";

it("has no axe violations", async () => {
  const { container } = render(<Select options={cities} aria-label="City" />);
  expect(await axe(container)).toHaveNoViolations();
});

The package suite runs axe on every interactive component and walks the keyboard path for each pattern: open, move, select, dismiss, focus back on the trigger. The same setup works in your project. Test your composition, not the component: the name you passed, the order of fields, the focus target after a dialog closes.

ComponentPatternKeys
ButtonButton, native <button>Tab, Enter, Space
Button groupGroup of native buttonsTab, Enter, Space
Text linkLink, native <a>Tab, Enter
InputNative inputTab, Enter
FieldNative label, hint, and error wired through aria-describedby
Input groupNative input with a labelled addon
Native selectNative <select>Space, Alt + Arrow down, Arrow up, Arrow down, Type a letter
Inline formNative form with one fieldEnter, Tab
RadioRadio group, native inputsTab, Arrow up, Arrow down, Arrow left, Arrow right, Space
CheckboxCheckbox, native inputTab, Space
SwitchSwitch, role switch on a buttonTab, Space, Enter
SliderSlider, native range inputTab, Arrow right, Arrow up, Arrow left, Arrow down, Home, End
ProgressProgressbar
TabsTabs, horizontal or verticalTab, Arrow left, Arrow right, Arrow up, Arrow down, Home, End
BreadcrumbsBreadcrumb, nav > ol with aria-currentTab, Enter
PaginationNavigation landmark with aria-currentTab, Enter, Space
SelectSelect-only comboboxArrow down, Arrow up, Enter, Space, Home, End, Type letters, Arrow down, Arrow up, Page up, Page down, Enter, Space, Escape, Tab
DialogDialog, native <dialog>Escape, Tab, Shift + Tab, Enter, Space
StepperList with aria-current step
AccordionDisclosure, native <details>Tab, Enter, Space
AlertNote; status or alert when live
Alert dialogAlert dialog, native <dialog> with role alertdialogTab, Shift + Tab, Enter, Space, Escape
TextareaNative textareaTab
SpinnerStatus
TooltipTooltipTab, Escape
ToastStatus region, aria-live politeTab, Enter, Space
Dropdown menuMenu button and menuArrow down, Enter, Space, Arrow up, Arrow down, Arrow up, Home, End, Type letters, Enter, Space, Escape, Tab
ToggleToggle button, aria-pressedTab, Enter, Space
Toggle groupGroup of toggle buttonsTab, Enter, Space
PopoverPopover APIEnter, Space, Escape, Tab
SheetDialog, native <dialog>Escape, Tab, Shift + Tab
DrawerDialog, native <dialog>Escape, Tab, Shift + Tab
Scroll areaRegionTab, Arrow up, Arrow down, Page up, Page down
ChartsFigure with a keyboard cursor and a screen-reader tableTab, Arrow right, Arrow left, Home, End, Escape
Bar chartFigure with a keyboard cursor and a screen-reader tableTab, Arrow right, Arrow left, Home, End, Escape
Area chartFigure with a keyboard cursor and a screen-reader tableTab, Arrow right, Arrow left, Home, End, Escape
Scatter chartFigure with a keyboard cursor and a screen-reader tableTab, Arrow right, Arrow left, Home, End, Escape
Donut or shareFigure with a screen-reader table
HistogramFigure with a keyboard cursor and a screen-reader tableTab, Arrow right, Arrow left, Home, End, Escape
Small multiplesFigures with screen-reader tablesTab, Arrow right, Arrow left, Home, End, Escape
CollapsibleDisclosure, native <details>Tab, Enter, Space
Hover cardTooltipTab, Escape
One-time codeGroup of native inputsType a digit, Backspace, Arrow left, Arrow right, Paste
Context menuMenu, opened by pointer or Shift+F10Shift + F10, Context menu key, Arrow down, Arrow up, Home, End, Type letters, Enter, Space, Escape
MenubarMenubarTab, Arrow left, Arrow right, Home, End, Arrow down, Enter, Space, Arrow up, Escape
Navigation menuNavigation landmarkTab, Enter
SidebarNavigation landmarkTab, Enter
CarouselCarousel, scroll snap with named groupsTab, Arrow left, Arrow right, Enter, Space
ResizableWindow splitter, role separatorTab, Arrow left, Arrow up, Arrow right, Arrow down, Shift + Arrow keys, Home, End
ComboboxCombobox with list autocompleteType, Arrow down, Arrow up, Home, End, Page up, Page down, Enter, Escape, Tab
CommandDialog plus combobox and listboxType, Arrow down, Arrow up, Home, End, Page up, Page down, Enter, Escape
CalendarGrid with a roving cellTab, Arrow left, Arrow right, Arrow up, Arrow down, Home, End, Page up, Page down, Shift + Page up, Shift + Page down, Enter, Space
Date pickerDialog holding a gridEnter, Space, Arrow down, Arrow keys, Home, End, Page up, Page down, Enter, Space, Escape, Tab
Data tableTable with sortable column headers (aria-sort)Tab, Enter, Space
FormNative formEnter
Theme toggleButton with a state-dependent nameTab, Enter, Space

Each component page carries the full keyboard table and the accessibility notes for that component.