Saavutettavien komponenttikirjastojen selvitys
mitkä oikeasti läpäisevät axe-auditoinnin
Asensimme seitsemän ladatuimman React-komponenttikirjaston vuodelta 2026, kytkimme jokaisen tuoreeseen Next.js 15 / React 19 / TypeScript -sovellukseen ja ajoimme saman auditointivaljaan jokaista primitiiviä vastaan: axe-core 4.11 headless Chromiumissa, manuaaliset näppäimistöläpikäynnit, NVDA Windowsilla, VoiceOver macOS:llä ja Lighthouse-saavutettavuusläpikäynti bundle-kustannusten selvittämiseksi.
1. Auditointivaljaat
Jokainen kirjasto asennettiin samaan React 19 / Next.js 15 / TypeScript 5.5 -runkoon käyttäen nykyistä toimittajasuositeltua asennuspolkua: npm i pakatuille kirjastoille (Radix UI -primitiivit, Headless UI 2.x, Mantine 8.x, Chakra UI v3, Ark UI, React Aria Components), ja shadcn-CLI shadcn/ui:lle — joka kopioi lähteen components/ui-kansioon paketin toimittamisen sijaan. Asensimme sitten kitchen-sink-demosivun, joka esitti jokaisen kirjaston interaktiivisten primitiivien täyden joukon oletustilassaan, ilman teemaylikuormituksia tai mukautettuja wrappereitä.
Auditointivaljaat ajoi kolmessa läpikäynnissä. Ensimmäinen läpikäynti oli automaattinen axe-core 4.11 -pyyhkäisy Playwrightin kautta renderöityä DOM:ia vastaan, WCAG 2.2 AA -sääntöjoukolla ja kokeellisilla säännöillä käytössä. Toinen läpikäynti oli manuaalinen näppäimistöpyyhkäisy: tab, shift-tab, nuolinäppäimet, escape, enter, välilyönti ja home/end jokaista primitiiviä vastaan, pisteytettynä WAI-ARIA Authoring Practices Guide -odotettua näppäimistösopimusta vastaan. Kolmas läpikäynti oli ruudunlukuohjelman savutesti NVDA 2025.1:llä Chromessa ja Safari/VoiceOverilla macOS Sonorama, etsien rooli-ilmoitusta, saavutettavaa nimeä ja tilamuutosilmoitusta kun käyttäjä interaktoi.
Valitsimme yksitoista ARIA-mallia pintana matriisia varten, koska nämä ovat mallit, jotka esiintyvät tuotekäyttöliittymissä jotka joutuvat oikeudenkäynteihin: dialog, alert dialog, combobox, listbox, menu, menubar, tabs, accordion, tooltip, switch ja slider. Kirjasto, joka hallitsee napit ja otsikot mutta toimittaa rikkinäisen comboboxin, on kirjasto, joka epäonnistuu auditoinnissa heti kun oikea käyttäjä yrittää suodattaa asiakaslistaa.
axe-läpäisy tarkoittaa nolla rikkomuksia missään WCAG 2.2 AA -tagisäännössä plus kokeellisessa tagissa, renderöitynä oletuspropseilla ja kirjaston dokumentoitulla käyttöesimerkillä. Se ei tarkoita, että kirjasto on luodinkestävä — axe havaitsee noin puolet kaikista WCAG-epäonnistumisista — mutta kirjasto, joka ei läpäise axe:ia omassa demossaan, ei läpäise missään muuallakaan.
”Oletustila on ainoa tila, jonka useimmat kehitystiimit koskaan näkevät. Jos kirjasto toimittaa rikkinäisen oletuksen, rikkinäinen oletus lähtee tuotantoon.”
2. Seitsemän kirjastoa rinnakkain
Kolme seitsemästä kirjastosta — Radix UI, React Aria Components ja Ark UI — läpäisi axe:n jokaisesta primitiivistä oletustilassaan ilman ylikuormituksia. Headless UI läpäisi kaikista paitsi menu-primitiivistä, jossa puuttuva aria-activedescendant listbox-tyypin menu-laukaisijassa tuotti yhden rikkomuksen. shadcn/ui — joka on itsessään ohut kerros Radix UI:n päälle — läpäisi jokaisesta toimittamastaan primitiivistä, mutta se toimittaa vain noin kaksi kolmasosaa Radix-pinnasta, ja puutteet (combobox, listbox, menubar) ovat täsmälleen ne mallit, joissa toimittajat tekevät useimmiten saavutettavuusvirheitä rakentaessaan niitä itse.
Mantine ja Chakra UI v3 olivat kaksi kirjastoa, joiden oletukset toimittiivat axe-rikkomuksia. Mantinen combobox, switch ja slider tuottivat kaikki vähintään yhden axe-rikkomuksen dokumentoidussa käyttöesimerkissään, enimmäkseen puuttuvien saavutettavien nimien vuoksi alla olevassa syötteessä. Chakra UI v3 — joka siirtyi Zag-pohjaiseen tilakone-arkkitehtuuriin vuoden 2024 lopulla — korjasi monet v2:n ongelmista, mutta toimittaa edelleen tooltipin joka käynnistyy vain hoverilla, mikä on 1.4.13 Hover- tai kohdistussisältö -rikkomus axe:ssa ja näppäimistöansa-riski ruudunlukuohjelman virtuaalitilassa.
3. Mallikattavuusmatriisi
Alla oleva yksitoistamallinen ruudukko on pääviite. Vihreä solu tarkoittaa, että kirjasto toimittaa primitiivin natiivisti ja läpäisee axe:n oletustilassaan. Keltainen solu tarkoittaa, että kirjasto toimittaa primitiivin, mutta dokumentoidussa käyttöesimerkissä esiintyi vähintään yksi axe-rikkomus, näppäimistösopimuspuute tai ruudunlukuohjelmapuute. Harmaa “N/A” tarkoittaa, että kirjasto ei toimita kyseistä primitiiviä — shadcn/ui:n tapauksessa kyseessä on kolme mallia, joissa pitäisi tuoda Radix suoraan tai kytkeä kolmannen osapuolen vaihtoehto.
| Malli | Radix | React Aria | Ark UI | shadcn | Headless | Mantine | Chakra v3 |
|---|---|---|---|---|---|---|---|
| Dialog | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy |
| Alert dialog | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Osittainen | Läpäisy |
| Combobox | Läpäisy | Läpäisy | Läpäisy | N/A | Läpäisy | Osittainen | Läpäisy |
| Listbox | Läpäisy | Läpäisy | Läpäisy | N/A | Läpäisy | Läpäisy | Läpäisy |
| Menu | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Osittainen | Läpäisy | Läpäisy |
| Menubar | Läpäisy | Läpäisy | Läpäisy | N/A | N/A | Läpäisy | Läpäisy |
| Tabs | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy |
| Accordion | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy |
| Tooltip | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Osittainen |
| Switch | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Osittainen | Läpäisy |
| Slider | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Läpäisy | Osittainen | Läpäisy |
Harmaa N/A-solu ei ole epäonnistuminen — se on hankintakysymys. shadcn/ui:n tarina on, että kopioit sisään tarvitsemasi lähteen kuratoidusta joukosta, sitten toimitat; kolmelle N/A-mallille joko tuot Radix-primitiivin suoraan tai vedät sisarrekisteristä. Riski shadcn/ui:ssa ei ole sen toimittamissa komponenteissa — ne perivät Radixin vaatimustenmukaisuuden — vaan komponenteissa joita se ei toimita, joissa tiimit päätyvät rakentamaan comboboxin kello 1 aamuyöllä deadlinea vastaan.
4. Näppäimistösopimukset jotka pettivät
Toistuvin epäonnistuminen kirjastojen välillä ei ollut puuttuva aria-attribuutti — vaan näppäimistösopimus, joka melkein vastasi APG:tä ja sitten erkani yhdellä näppäimellä. Mantinen combobox ei vastaa Home- ja End-näppäimiin APG:n määrittämällä tavalla. Chakra v3:n tooltip ei ole suljettavissa Escape-näppäimellä, kun se avattiin hoverilla. Headless UI:n menu-primitiivi sulkeutuu ensimmäisellä ArrowDown-painalluksella sen sijaan, että sijoittaisi kohdistuksen ensimmäiseen kohteeseen, koska toteutus kohtelee laukaisijaa aktiivisena jälkeläisenä avautuessa.
Nämä eivät ole eksoottisia reunatapauksia. Ne ovat mallit, joihin ruudunlukuohjelmakäyttäjä turvautuu ensimmäisellä minuutilla. Alla oleva vertailu parittaa saman combobox-API:n kirjoitettuna kahdella tavalla — kerran Mantinen oletuksilla, kerran React Aria Components -kirjastolla — näyttääkseen, miltä näppäimistösopimus näyttää, kun sitä kohdellaan speksipaperina eikä viimeistelykohtana.
<Combobox
store={combobox}
onOptionSubmit={(v) => setValue(v)}
>
<Combobox.Target>
<InputBase
// ei aria-controls-kytkentää syötteeseen
// Home/End-näppäimet eivät siirrä kohdistusta listboxin sisällä
// ArrowDown avaa mutta ei sijoita kohdistusta kohteeseen 1
value={value}
onChange={(e) => setValue(e.currentTarget.value)}
/>
</Combobox.Target>
<Combobox.Dropdown>
{/* listbox-kohteet renderöidään tähän */}
</Combobox.Dropdown>
</Combobox><ComboBox aria-label="Suodata asiakkaita">
<Label>Asiakas</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: kaikki kytketty oletuksena.Kirjastot, jotka johtavat näppäimistösopimuksensa julkaistusta speksistä — React Aria WAI-ARIA APG:stä, Ark UI Zag.js-tilakoneiden kautta — toimittavat nuo sopimukset ainoana toimintana, jota komponentti tukee. Kirjastot, jotka kohtelevat näppäimistösopimusta ominaisuuslistana, toimittavat noin 80 % siitä ja jättävät viimeiset 20 % “tulevaisuuden työksi.” Tuo viimeinen 20 % on täsmälleen ne näppäimet, joita avustavien teknologioiden käyttäjät painavat eniten.
5. Saavutettavuuden bundle-kustannus
Yleisin vastaväite tiukkojen kirjastojen valitsemiseen on bundle-koko. Auditointi ei tue tätä. Radix UI -primitiivit ovat tree-shakeable per primitiivi ja toimitettavat noin 7–15 KB paketoitu koko kukin; React Aria Components on raskaampi — noin 95 KB pakettitiedosto koko bundlesta — mutta myös tree-shakeable. Headless UI on kevyin noin 25 KB pakettitiedostona koko paketille. Mantine ja Chakra v3 ovat molemmat paristo mukana -kirjastoja ja toimittavat tyylitysjärjestelmän samassa bundlessa, sijoittaen ne noin 180–220 KB pakettitiedosto -alueelle oletuksena.
Kompromissi on todellinen mutta pienempi kuin diskurssi ehdottaa. Combobox, joka ei kunnioita Home- ja End-näppäimiä, maksaa suunnilleen saman verran tavuja kuin sellainen joka kunnioittaa. Valinta ei ole “saavutettavuus vastaan suorituskyky” — se on “speksistä johdettu toiminta vastaan käsin tehty toiminta”, ja käsin tehty versio on useammin suurempi koska se kantaa omaa ad-hoc-tilakonettaan.
6. Toimintaohje stackin valintaan
Jos tuote on yrityssovellus, jolla on hankintavetoiset saavutettavuusvaatimukset, valitse React Aria Components.
Se on ainoa auditoitu kirjasto, jonka API:t on nimenomaisesti johdettu WAI-ARIA Authoring Practices Guidesta. Bundle on raskaampi kuin Radixilla, mutta auditoinnin läpäisytarina VPAT-tarkastajalle on selkein, koska jokaisella primitiivistä on julkaistu vaatimustenmukaisuusväite.
Jos tiimi omistaa design systeminsä, valitse Radix UI (ja valinnaisesti shadcn/ui sen päälle).
Radix antaa tyylittömät, speksimukaiset primitiivit. shadcn/ui tekee niistä helposti kopioitavia ja teemoitettavia. Tarkkailtava asia on kolme mallia, joita shadcn ei toimita — combobox, listbox, menubar — joita varten kannattaa tuoda Radix suoraan käsin rakentamisen sijaan.
Jos tiimi on Tailwind-ensin ja tarvitsee vain kapean pinnan, valitse Headless UI — mutta auditoi menu-primitiivi omassa koodissasi.
Headless UI on kentän pienin bundle ja toimittaa pienen, hyvin testatun pinnan. Yksi menu-primitiivipuute on dokumentoitu yllä; korjaa se eksplisiittisellä aria-activedescendant-kytkennällä listbox-tyylin menussa tai kääri menu projektikohtaisella helperillä joka tekee niin.
Jos tiimi arvostaa paristo mukana -ratkaisua speksimukaisuuden sijaan, valitse Mantine tai Chakra v3 — mutta suunnittele ylikuormitukset.
Molemmat kirjastot ovat nopeita käyttöönottaa ja näyttävät hyvältä oletuksena. Molemmat vaativat myös komponenttikohtaisia ylikuormituksia läpäistäkseen auditoinnin comboboxin, switchin ja sliderin (Mantine) tai tooltipin (Chakra v3) osalta. Budjetoi ylikuormitustyö siihen sprinttiin, jossa kirjasto otetaan käyttöön, ei siihen sprinttiin jossa auditointi epäonnistuu.
Aja axe kirjaston omaa demoa vastaan ennen sen ottamista käyttöön.
Toimittajilla on demosivustoja. Osoita axe DevTools niihin. Jos toimittajan oma demo tuottaa rikkomuksia primitiiveissä, joita aiot käyttää, nämä rikkomukset seuraavat tuotteeseesi. Tämä yksittäinen viiden minuutin tarkistus erottaa kirjastot, jotka otat käyttöön, niistä joita vältät.
Yhteenveto: speksi on sopimus
Kirjastot, jotka läpäisevät axe-auditoinnin puhtaasti, ovat kirjastoja, joiden tekijät kohtelivat WAI-ARIA Authoring Practices Guidea sopimuksena eikä viitteenä. Radix UI, React Aria Components ja Ark UI johtavat kukin näppäimistösopimuksensa ja ARIA-kytkentänsä julkaistusta speksistä — APG:stä Radixin ja React Arian tapauksessa, Zag.js-tilakoneiden kautta Ark UI:n tapauksessa — ja toimittavat speksin, ei sen osajoukkoa.
Epäonnistuvat kirjastot eivät epäonnistu siksi, etteivät niiden tekijät välitä saavutettavuudesta. Ne epäonnistuvat koska näppäimistösopimusta kohdeltiin ominaisuuslistana, ja ominaisuuslistat päätyvät 80 prosenttiin eivätkä 100:aan. Viimeiset 20 % — Home ja End comboboxissa, Escape hover-avatun tooltipin sulkemiseksi, kohdistuksenhallinta ensimmäisellä ArrowDown-painalluksella menussa — on osa, jonka käyttäjä huomaa.
shadcn/ui:n tarina sijoittuu erikoisesti molempiin kategorioihin. Sen toimittamat komponentit perivät Radixin speksistä johtamisen ja läpäisevät. Komponentit, joita se ei toimita, ovat puutteita, joissa tiimit rakentavat talon sisäistä comboboxia, ja tuo talon sisäinen combobox on se, mistä seuraava axe-rikkomus tulee koodipohjaan. Korjaus ei ole valita eri kirjasto — se on tuoda Radix suoraan näille kolmelle mallille ja kohdella niitä samalla vakavuudella kuin muutakin design systemiä.
Kirjastoa käyttöönottavien kehitystiimien kannattaa yhdistää valinta muuhun kehittäjän Toolkitiin kehittäjien laskeutumissivullamme, ajaa ilmainen WCAG 2.2 -skannaus kirjaston demoa vastaan ennen sen tuotantoonvientiä ja verrata tulosta täyteen WCAG 2.2 onnistumiskriteerien viitteeseen.
”Valitse kirjasto, jonka tekijät kohtelivat speksiä sopimuksena, ja auditoinnista tulee muodollisuus. Valitse kirjasto, jonka tekijät kohtelivat speksiä viitteenä, ja auditoinnista tulee jono.”