Изглед отгоре на физически дървени карти с UI компоненти върху скандинавско бюро от дъб, като централната карта с изрязан бутон е оцветена в алено червено — визуалният знак за одита на библиотеките от компоненти.
Image description: Изглед отгоре на физически дървени карти с UI компоненти върху скандинавско бюро от дъб, като централната карта с изрязан бутон е оцветена в алено червено — визуалният знак за одита на библиотеките от компоненти.

Инженерно ръководство · Одит на библиотеки от компоненти

Преглед на достъпни библиотеки от компоненти: кои всъщност минават одит с axe

Извършихме одит на седем библиотеки от React компоненти, предлагани през 2026 г. — Radix UI, Headless UI, shadcn/ui, Mantine, Chakra UI v3, Ark UI и React Aria Components — като оценихме всяка по дял на преминаване през axe, покритие на ARIA шаблоните, клавиатурен договор и цена в размер на пакета.

Преглед на достъпни библиотеки от компоненти
кои всъщност минават одит с axe

Инсталирахме седем от най-изтегляните библиотеки от React компоненти, предлагани през 2026 г., свързахме всяка от тях с ново приложение на Next.js 15 / React 19 / TypeScript и пуснахме една и съща одитна среда срещу всеки примитив: axe-core 4.11 в headless Chromium, ръчни прегледи с клавиатура, NVDA на Windows, VoiceOver на macOS и преминаване с Lighthouse за достъпност, за да отчетем цената в размер на пакета.

7
библиотеки, преминали одит
3
с чисто преминаване през axe на всеки примитив
11
оценени ARIA шаблона на библиотека
11 мин. четене
Обновено май 2026 г.

1. Одитната среда

Всяка библиотека беше инсталирана в един и същ скелет на React 19 / Next.js 15 / TypeScript 5.5 по текущия препоръчван от доставчика път на инсталиране: npm i за пакетираните библиотеки (примитивите на Radix UI, Headless UI 2.x, Mantine 8.x, Chakra UI v3, Ark UI, React Aria Components) и CLI на shadcn за shadcn/ui — която копира изходния код в components/ui, вместо да добавя пакет. След това монтирахме демонстрационна страница от типа „всичко наведнъж“, която показва пълния набор от интерактивни примитиви на всяка библиотека в тяхно стандартно, недокоснато състояние, без презаписи на темата и без персонализирани обвивки.

Одитната среда работеше на три преминавания. Първото преминаване беше автоматизирано сканиране с axe-core 4.11 чрез Playwright срещу изобразения DOM, с пълния набор от правила за WCAG 2.2 AA и активирани експериментални правила. Второто преминаване беше ръчен преглед с клавиатура: tab, shift-tab, клавишите със стрелки, escape, enter, space и home/end срещу всеки примитив, оценени спрямо очаквания клавиатурен договор от WAI-ARIA Authoring Practices Guide. Третото преминаване беше бърз тест с екранен четец с NVDA 2025.1 на Chrome и Safari/VoiceOver на macOS Sonoma, в който търсихме обявяването на ролята, достъпното име и обявяването на състоянието при взаимодействие на потребителя.

Избрахме единайсет ARIA шаблона като обхват за матрицата, защото това са шаблоните, които се появяват в продуктовите интерфейси, срещу които се водят съдебни производства: dialog, alert dialog, combobox, listbox, menu, menubar, tabs, accordion, tooltip, switch и slider. Библиотека, която се справя отлично с бутоните и заглавията, но предлага счупен combobox, е библиотека, която ще се провали на одит първия път, когато реален потребител се опита да филтрира списък с клиенти.

11
ARIA шаблона, преминали одит на библиотека (от dialog до slider)
77
клетки „библиотека по шаблон“ в матрицата на покритие
3
одитни преминавания — axe-core, ръчно с клавиатура, бърз тест с екранен четец
май 2026 г.
снимка с фиксирана версия на всяка тествана библиотека
Какво означава тук „преминаване през axe“

Преминаване през axe означава нула нарушения на което и да е правило в тага WCAG 2.2 AA плюс експерименталния таг, изобразено със стандартните свойства и документирания пример за употреба на библиотеката. То не означава, че библиотеката е неуязвима — axe улавя приблизително половината от всички пропуски по WCAG — но библиотека, която не може да премине през axe в собствената си демонстрация, не може да премине никъде другаде.

„Стандартното състояние е единственото състояние, което повечето инженерни екипи изобщо виждат. Ако дадена библиотека предлага счупено стандартно поведение, счупеното стандартно поведение стига до продукцията.“

— инженерен отдел на disabilityworld.org, бележки от одита

2. Седем библиотеки една до друга

Три от седемте библиотеки — Radix UI, React Aria Components и Ark UI — преминаха през axe на всеки примитив в стандартното си състояние без необходими презаписи. Headless UI премина на всички с изключение на примитива menu, където липсващ aria-activedescendant на тригера на меню от тип listbox генерира едно-единствено нарушение. shadcn/ui — която сама по себе си е тънък слой върху Radix UI — премина на всеки примитив, който предлага, но уловката е, че предлага само около две трети от повърхността на Radix, а пропуските (combobox, listbox, menubar) са точно шаблоните, при които доставчиците най-често допускат грешки в достъпността, когато ги пресъздават ръчно.

Mantine и Chakra UI v3 бяха двете библиотеки, чието стандартно поведение предлагаше нарушения по axe. Combobox, switch и slider на Mantine генерираха поне по едно нарушение по axe в документирания си пример за употреба, най-вече около липсващи достъпни имена на подлежащия input. Chakra UI v3 — която премина към архитектура със състоятелна машина, базирана на Zag, в края на 2024 г. — поправи много от проблемите на v2, но все още предлага tooltip, който се задейства само при посочване с мишката, което е нарушение на 1.4.13 Content on Hover or Focus в axe и риск от клавиатурен капан във виртуалния режим на екранния четец.

Radix UI
WorkOS · нестилизирани примитиви
приблизително 4,2 млн. изтегляния седмично (radix-ui/themes + primitives, npm, май 2026 г.)
Дял на преминаване през axe11 / 11
Покритие на ARIA шаблоните
Естествено спрямо презаписЕстествено — без нужда от презаписи
React Aria Components
Adobe · съобразено с WAI-ARIA APG
приблизително 980 хил. изтегляния седмично (react-aria-components, npm, май 2026 г.)
Дял на преминаване през axe11 / 11
Покритие на ARIA шаблоните
Естествено спрямо презаписЕстествено — най-строгото съответствие с APG от всички тествани библиотеки
Ark UI
Chakra Systems · състоятелни машини с Zag.js
приблизително 210 хил. изтегляния седмично (@ark-ui/react, npm, май 2026 г.)
Дял на преминаване през axe11 / 11
Покритие на ARIA шаблоните
Естествено спрямо презаписЕстествено — клавиатурният договор е изведен от спецификациите на състоятелните машини
shadcn/ui
Shadcn · Radix върху Tailwind, копиран изходен код
приблизително 92 хил. звезди в GitHub · инсталира се чрез CLI, не е пакетирана (май 2026 г.)
Дял на преминаване през axe8 / 8 предлагани (combobox, listbox, menubar липсват)
Покритие на ARIA шаблоните
Естествено спрямо презаписЕстествено за това, което предлага — но след копирането изходният код е ваша отговорност
Headless UI
Tailwind Labs · нестилизирана, ориентирана към Tailwind
приблизително 1,1 млн. изтегляния седмично (@headlessui/react, npm, май 2026 г.)
Дял на преминаване през axe10 / 11 (примитивът menu се проваля)
Покритие на ARIA шаблоните
Естествено спрямо презаписПредимно естествено — по-тясна повърхност от Radix
Mantine
екипът на Mantine · стилизирана, „всичко включено“
приблизително 540 хил. изтегляния седмично (@mantine/core, npm, май 2026 г.)
Дял на преминаване през axe8 / 11
Покритие на ARIA шаблоните
Естествено спрямо презаписИзисква презапис — подайте свойства, за да поправите combobox, switch, slider
Chakra UI v3
Chakra Systems · базирана на Zag, стилизирана
приблизително 480 хил. изтегляния седмично (@chakra-ui/react, npm, май 2026 г.)
Дял на преминаване през axe9 / 11
Покритие на ARIA шаблоните
Естествено спрямо презаписПредимно естествено — tooltip само при посочване е известен пропуск на v3

3. Матрица на покритие на шаблоните

Решетката с единайсетте шаблона по-долу е основният справочник. Зелена клетка означава, че библиотеката предлага примитива естествено и преминава през axe в стандартното си състояние. Жълта клетка означава, че библиотеката предлага примитива, но в документирания пример за употреба се появи поне едно нарушение по axe, пропуск в клавиатурния договор или пропуск с екранния четец. Сив надпис „N/A“ означава, че библиотеката не предлага този примитив — за shadcn/ui това са три шаблона, за които би се наложило да импортирате Radix директно или да свържете решение от трета страна.

ШаблонRadixReact AriaArk UIshadcnHeadlessMantineChakra v3
DialogПреминаваПреминаваПреминаваПреминаваПреминаваПреминаваПреминава
Alert dialogПреминаваПреминаваПреминаваПреминаваПреминаваЧастичноПреминава
ComboboxПреминаваПреминаваПреминаваN/AПреминаваЧастичноПреминава
ListboxПреминаваПреминаваПреминаваN/AПреминаваПреминаваПреминава
MenuПреминаваПреминаваПреминаваПреминаваЧастичноПреминаваПреминава
MenubarПреминаваПреминаваПреминаваN/AN/AПреминаваПреминава
TabsПреминаваПреминаваПреминаваПреминаваПреминаваПреминаваПреминава
AccordionПреминаваПреминаваПреминаваПреминаваПреминаваПреминаваПреминава
TooltipПреминаваПреминаваПреминаваПреминаваПреминаваПреминаваЧастично
SwitchПреминаваПреминаваПреминаваПреминаваПреминаваЧастичноПреминава
SliderПреминаваПреминаваПреминаваПреминаваПреминаваЧастичноПреминава
Четете матрицата внимателно

Сива клетка N/A не е провал — тя е въпрос за източника. Историята на shadcn/ui е, че копирате нужния ви изходен код от подбран набор и след това го пускате; за трите шаблона N/A или импортирате примитив на Radix директно, или го взимате от сродна директория. Рискът в shadcn/ui не са компонентите, които предлага — те наследяват съответствието на Radix — а компонентите, които не предлага, при които екипите в крайна сметка пишат combobox на ръка в 1 часа през нощта, за да спазят срока.


4. Клавиатурни договори, които се счупиха

Най-повтарящият се провал в различните библиотеки не беше липсващ ARIA атрибут — а клавиатурен договор, който почти съответстваше на APG и след това се разминаваше с един клавиш. Combobox на Mantine не реагира на Home и End така, както указва APG. Tooltip на Chakra v3 не може да бъде затворен с Escape, когато е отворен чрез посочване с мишката. Примитивът menu на Headless UI се свива при първото натискане на ArrowDown, вместо да постави фокуса върху първия елемент, защото реализацията третира тригера като активен потомък при отваряне.

Това не са екзотични гранични случаи. Това са шаблоните, които потребителят на екранен четец използва от първата минута. Сравнението по-долу съпоставя един и същ API на combobox, написан по два начина — веднъж със стандартните настройки на Mantine, веднъж с React Aria Components — за да покаже как изглежда клавиатурният договор, когато се третира като спецификация, а не като елемент за лустро.

Изисква презапис: combobox на Mantine в стандартно състояние
<Combobox
store={combobox}
onOptionSubmit={(v) => setValue(v)}
>
<Combobox.Target>
  <InputBase
    // no aria-controls wiring on the input
    // Home/End keys do not move focus inside the listbox
    // ArrowDown opens but does not place focus on item 1
    value={value}
    onChange={(e) => setValue(e.currentTarget.value)}
  />
</Combobox.Target>
<Combobox.Dropdown>
  {/* listbox items render here */}
</Combobox.Dropdown>
</Combobox>
Естествено: combobox на React Aria Components в стандартно състояние
<ComboBox aria-label="Filter customers">
<Label>Customer</Label>
<Input />
<Popover>
  <ListBox>
    <ListBoxItem>Alpha</ListBoxItem>
    <ListBoxItem>Bravo</ListBoxItem>
    <ListBoxItem>Charlie</ListBoxItem>
  </ListBox>
</Popover>
</ComboBox>
// aria-controls, aria-activedescendant,
// aria-expanded, role=combobox, Home/End,
// PageUp/PageDown, Escape: all wired by default.
Защо този пропуск е структурен, а не редакционен

Библиотеките, които извеждат клавиатурните си договори от публикувана спецификация — React Aria от WAI-ARIA APG, Ark UI от състоятелните машини на Zag.js — предлагат тези договори като единственото поведение, което компонентът поддържа. Библиотеките, които третират клавиатурния договор като списък с функции, предлагат приблизително 80% от него и оставят последните 20% като „бъдеща работа“. Тези последни 20% са точно клавишите, които потребителите на помощни технологии натискат най-често.


5. Цената на достъпността в размер на пакета

Най-честото възражение срещу избора на строгите библиотеки е размерът на пакета. Одитът не го потвърди. Примитивите на Radix UI се поддават на tree-shaking поотделно и са в диапазона приблизително 7–15 KB gzipped всеки; React Aria Components е по-тежка — приблизително 95 KB gzipped за пълния пакет — но също се поддава на tree-shaking. Headless UI е най-леката с приблизително 25 KB gzipped за целия пакет. Mantine и Chakra v3 са „всичко включено“ и предлагат системата за стилизиране в същия пакет, което ги поставя в диапазона приблизително 180–220 KB gzipped по подразбиране.

Компромисът е реален, но по-малък, отколкото подсказва дискусията. Combobox, който не зачита Home и End, струва приблизително същия брой байтове като онзи, който ги зачита. Изборът не е „достъпност срещу производителност“ — а „поведение, изведено от спецификация, срещу поведение, написано на ръка“, като ръчно написаната версия по-често е по-голямата, защото носи собствена импровизирана състоятелна машина.

7–15 KB
Radix UI на примитив (gzipped)
25 KB
пълен пакет на Headless UI (gzipped)
95 KB
пълен пакет на React Aria Components (gzipped, с tree-shaking)
прибл. 200 KB
стандартно „всичко включено“ за Mantine + Chakra v3

6. Наръчник за избор на технологичен стек

1

Ако продуктът е корпоративно приложение с изискване за достъпност, водено от обществените поръчки, изберете React Aria Components.

Това е единствената библиотека, преминала одит, чиито API са изрично изведени от WAI-ARIA Authoring Practices Guide. Пакетът е по-тежък от Radix, но историята с преминаването на одит пред рецензент на VPAT е най-чиста, защото всеки примитив има публикувана декларация за съответствие.

2

Ако екипът притежава собствена дизайн система, изберете Radix UI (и по избор shadcn/ui отгоре).

Radix предоставя нестилизирани, съответстващи на спецификацията примитиви. shadcn/ui ги прави лесни за копиране и стилизиране. Внимавайте за трите шаблона, които shadcn не предлага — combobox, listbox, menubar — за които трябва да импортирате Radix директно, вместо да пишете на ръка.

3

Ако екипът е ориентиран към Tailwind и се нуждае само от тясна повърхност, изберете Headless UI — но извършете одит на примитива menu в собствения си код.

Headless UI е най-малкият пакет в групата и предлага малка, добре тествана повърхност. Единственият пропуск с примитива menu е документиран по-горе; поправете го с изрично свързване на aria-activedescendant на менюто от тип listbox или обвийте менюто с локален за проекта помощник, който прави това.

4

Ако екипът цени „всичко включено“ повече от съответствието със спецификацията, изберете Mantine или Chakra v3 — но планирайте презаписи.

И двете библиотеки позволяват бързо разработване и изглеждат добре по подразбиране. И двете обаче изискват презаписи на отделните компоненти, за да преминат одита за combobox, switch, slider (Mantine) или tooltip (Chakra v3). Заложете работата по презаписите в спринта, в който се приема библиотеката, а не в спринта, в който се проваля одитът.

5

Пуснете axe срещу собствената демонстрация на библиотеката, преди да я приемете.

Доставчиците поддържат демонстрационни сайтове. Насочете axe DevTools към тях. Ако собствената демонстрация на доставчика генерира нарушения на примитивите, които планирате да използвате, тези нарушения ще последват в продукта ви. Тази единствена петминутна проверка отделя библиотеките, които приемате, от онези, които избягвате.


Заключение: спецификацията е договорът

Библиотеките, които преминават чисто одит с axe, са библиотеките, чиито автори са третирали WAI-ARIA Authoring Practices Guide като договор, а не като справочник. Radix UI, React Aria Components и Ark UI извеждат своите клавиатурни договори и ARIA свързвания от публикувана спецификация — APG в случая на Radix и React Aria, състоятелните машини на Zag.js в случая на Ark UI — и предлагат спецификацията, а не подмножество от нея.

Библиотеките, които се провалят, не се провалят, защото авторите им не държат на достъпността. Те се провалят, защото клавиатурният договор е третиран като списък с функции, а списъците с функции стигат до 80%, а не до 100%. Последните 20% — Home и End в combobox, Escape за затваряне на tooltip, отворен при посочване, управление на фокуса при първото натискане на ArrowDown в меню — са частта, която потребителят забелязва.

Историята на shadcn/ui стои неловко между двете категории. Компонентите, които предлага, наследяват извеждането от спецификацията на Radix и преминават. Компонентите, които не предлага, са пропуските, при които екипите пишат собствен combobox на ръка, и този собствен combobox е мястото, където следващото нарушение по axe влиза в кодовата база. Поправката не е да се избере друга библиотека — а да се импортира Radix директно за тези три шаблона и те да се третират със същата сериозност като останалата част от дизайн системата.

Инженерните екипи, които приемат библиотека, трябва да съчетаят избора с останалата част от инструментариума за разработчици на нашата страница за разработчици, да пуснат безплатно сканиране по WCAG 2.2 на демонстрацията на библиотеката, преди да я пуснат в продукция, и да сравнят резултата с пълния справочник на критериите за успех по WCAG 2.2.

„Изберете библиотеката, чиито автори са третирали спецификацията като договор, и одитът се превръща във формалност. Изберете библиотеката, чиито автори са третирали спецификацията като справочник, и одитът се превръща в списък със задачи.“

— инженерен отдел на disabilityworld.org, заключителна бележка