Tabs
Faner lar brukeren veksle mellom likeverdige innholdsseksjoner på samme side — uten å navigere til en ny side. Bare én seksjon vises om gangen, og en horisontal fane-liste styrer hvilken. Fanene supplerer SegmentedControl, som brukes til gjensidig utelukkende tilstander og filtre.
Egnet til
- Å dele opp relatert innhold i seksjoner der brukeren ser én om gangen
- Detaljvisninger med flere fasetter (oversikt, transaksjoner, innstillinger)
- Å redusere skrolling ved å samle innhold bak likeverdige valg
Uegnet til
- Sekvensielle steg brukeren skal gjennom i rekkefølge — bruk en stegindikator
- Navigasjon mellom sider — bruk lenker eller meny
- Gjensidig utelukkende filtre eller på/av-tilstander — bruk SegmentedControl
- Innhold brukeren må se samtidig — vis det åpent ved siden av hverandre
Bruk
Marker start-fanen med defaultValue (i HTML: aria-selected="true" på fanen og hidden på de skjulte panelene). Hver fane kobles til sitt panel via samme value — i HTML med et delt data-value på fanen og panelet. Koblingen følger data-value, ikke rekkefølgen, så fanene og panelene kan stå i vilkårlig orden.
Eksempler
Med ikon
En fane kan ha et ikon foran teksten. Ikonet følger samme tilstandsfarge som teksten (aktiv/passiv) og er kun støtte — teksten er hovedbæreren.
Kun ikon
Faner uten synlig tekst må ha et tilgjengelig navn (på brukerens språk) — ellers får skjermlesere ingen fane-etikett. I HTML settes det med aria-label på fanen; i React med ariaLabel.
Retningslinjer
Navngi fanene med ett eller to ord
Fanenavnet leses på tvers av en rad, ikke nedover, så det viktigste ordet må komme først. Hold navnene på samme form gjennom hele settet: enten alle substantiv («Oversikt», «Transaksjoner») eller alle verb, aldri en blanding.
La brukeren aktivere fanen selv
Piltast flytter fokus mellom fanene uten å bytte panel. Panelet skifter først når brukeren trykker Enter, Mellomrom eller klikker. Da kan en skjermleserbruker gå gjennom hele raden og høre hvilke faner som finnes, uten å laste og få opplest fire paneler på veien.
Del innholdet når fanene blir mange
Er det ikke plass til hele raden, scroller den horisontalt i én linje. Rekkefølgen holder seg, og siden får ingen horisontal scroll. Men en rad du må dra i for å se, skjuler valg: har du mange seksjoner, hører de på egne sider.
Velg kontrollert modus når fanen styres utenfra
Ukontrollert (defaultValue) lar web componenten eie tilstanden, og er nok i de fleste
tilfeller. Kontrollert (value + onChange) gir React eierskapet, og er det du trenger når
valgt fane skal henge sammen med noe annet, som URL-en.
function Konto() {
const [fane, setFane] = useState('oversikt');
return (
<Tabs value={fane} onChange={setFane}>
<Tabs.List ariaLabel="Kontoinformasjon">
<Tabs.Tab value="oversikt">Oversikt</Tabs.Tab>
<Tabs.Tab value="transaksjoner">Transaksjoner</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="oversikt">…</Tabs.Panel>
<Tabs.Panel value="transaksjoner">…</Tabs.Panel>
</Tabs>
);
}
Universell utforming
Hva du selv må sørge for
- Gi kun-ikon-faner et
ariaLabel. En fane uten synlig tekst trenger et tilgjengelig navn på brukerens språk. Komponenten har ingen hardkodet fallback. - Merk fane-settet med
ariaLabelpåTabs.Listnår flere uavhengige fane-sett finnes på samme side, så skjermleserbrukere kan skille dem. - Skriv korte, beskrivende etiketter som beskriver innholdet i tilhørende panel og gir mening lest alene.
- Bruk faner til likeverdig innhold. Ikke til sekvensielle steg (bruk stegindikator) eller navigasjon mellom sider (bruk lenker).
Hva komponenten gjør automatisk
- Roller og relasjoner: web componenten setter
role="tablist"/"tab"/"tabpanel",aria-selected,aria-controls(fane → panel) ogaria-labelledby(panel → fane) ved mount. Ingen ekstra ARIA er nødvendig. - Tastaturnavigasjon (manuell aktivering): roving
tabindexgir én tab-stopp; pil venstre/høyre flytter fokus, Home/End går til første/siste, og Enter/Mellomrom aktiverer. - Tilstand annonseres: aktiv fane formidles av
aria-selected, ikke av farge alene. - Fokusindikator: tydelig fokusring rundt hele fanen (
:focus-visible); tablisten reserverer vertikal plass så ringen ikke klippes av scroll-containeren. - Reflow og touch-mål: fane-lista scroller horisontalt ved plassmangel (siden får ingen horisontal scroll ned til 320 px), og hver fane har min. 44×44 px touch-mål.
- Redusert bevegelse: indikator-overgangen respekterer
prefers-reduced-motion: reduce.
Tastaturnavigasjon
| Tast | Handling |
|---|---|
| Tab | Flytter fokus inn i tablisten (til aktiv fane) og videre ut til første fokuserbare element etter tablisten — kun én tab-stopp i tablisten. Panelet er ikke en egen tab-stopp. |
| Shift+Tab | Flytter fokus til forrige fokuserbare element |
| Pil venstre / Pil høyre | Flytter fokus til forrige/neste fane, looper rundt endene (aktiverer ikke) |
| Home | Flytter fokus til første fane |
| End | Flytter fokus til siste fane |
| Enter | Aktiverer den fokuserte fanen og viser tilhørende panel |
| Space | Aktiverer den fokuserte fanen og viser tilhørende panel |
Skjermleser
- Ved fokus på en fane: «[etikett], fane, valgt/ikke valgt, [posisjon] av [antall]»
- Å aktivere en fane bytter det synlige panelet uten å flytte fokus bort fra fanen; panelet er programmessig knyttet til fanen via aria-controls/aria-labelledby
WCAG-kriterier
Sist gjennomgått: 2026-07-23 — alle 56 WCAG 2.2-kriterier vurdert
WCAG-kriterier5 ditt ansvar · 16 håndtert · 36 ikke relevant · 0 ikke på plass
Ditt ansvar (5)
| Kriterium | Nivå | Hva du må gjøre |
|---|---|---|
| 4.1.2 Navn, rolle, verdi | A | Gi kun-ikon-faner et tilgjengelig navn med ariaLabel. En fane som bare inneholder et ikon har ingen synlig tekst skjermlesere kan lese. Sett `ariaLabel` på `Tabs.Tab` (i HTML: `aria-label` på `<ix-tab>`) med en kort, beskrivende etikett på brukerens språk (bokmål, nynorsk eller engelsk). Komponenten har ingen hardkodet fallback. |
| 2.4.4 Formål med lenke (i kontekst) | A | Gi kun-ikon-faner et tilgjengelig navn med ariaLabel. En fane som bare inneholder et ikon har ingen synlig tekst skjermlesere kan lese. Sett `ariaLabel` på `Tabs.Tab` (i HTML: `aria-label` på `<ix-tab>`) med en kort, beskrivende etikett på brukerens språk (bokmål, nynorsk eller engelsk). Komponenten har ingen hardkodet fallback. |
| 1.3.1 Informasjon og relasjoner | A | Merk fane-settet med ariaLabel når flere finnes på samme side. Har siden flere uavhengige fane-sett, gi hver `Tabs.List` et eget `ariaLabel` (i HTML: `aria-label` på `<ix-tab-list>`) slik at skjermleserbrukere kan skille dem fra hverandre. Teksten er i18n-ansvaret til konsumenten. |
| 2.4.6 Overskrifter og ledetekster | AA | Skriv korte, beskrivende fane-etiketter. Fane-etiketten skal gi mening lest alene og beskrive innholdet i tilhørende panel. Hold den kort så lista kan skannes raskt. Et valgfritt prefiks-ikon støtter forståelsen, men teksten er hovedbæreren. |
| 1.3.1 Informasjon og relasjoner | A | Bruk faner til likeverdig innhold — ikke steg eller navigasjon. Faner er for å veksle mellom likeverdige innholdsseksjoner på samme side. Bruk dem ikke for sekvensielle steg (bruk en stegindikator) eller for navigasjon mellom sider (bruk lenker). Feil bruk gir skjermleserbrukere misvisende semantikk. |
Håndtert av komponenten (16)
| Kriterium | Nivå | Hva komponenten gjør |
|---|---|---|
| 1.3.1 Informasjon og relasjoner | A | Web componenten kobler `role="tablist"`/`"tab"`/`"tabpanel"`, `aria-selected`, `aria-controls` (tab → panel) og `aria-labelledby` (panel → tab) ved mount. Relasjonene er dermed programmessig eksponert, ikke bare visuelle. |
| 1.3.2 Meningsfull rekkefølge | A | Innhold følger naturlig leserekkefølge i DOM: tablist først, deretter det synlige panelet. Skjulte paneler har native `hidden` og er tatt ut av leserekkefølgen. |
| 1.4.1 Bruk av farge | A | Aktiv fane formidles av `aria-selected` (annonseres av skjermleser) i tillegg til understrek-indikatoren — ikke av farge alene. |
| 1.4.3 Kontrast (minimum) | AA | Fane-tekst bruker `--ix-color-foreground-main-default` (aktiv) og `--ix-color-foreground-main-subtle` (passiv) mot `--ix-color-surface-main`, som oppfyller kontrastkravet i både lys og mørk modus. |
| 1.4.4 Endre tekststørrelse | AA | Relative enheter (font-size-tokens) — tekst skalerer korrekt ved 200 % zoom uten at innhold brytes. |
| 1.4.10 Omflyt | AA | Ved plassmangel scroller kun tablisten horisontalt (én rad, bevart rekkefølge); siden får ingen horisontal scroll. Reflower korrekt ned til 320 px viewport. |
| 1.4.11 Kontrast for ikke-tekstlig innhold | AA | Fokusindikatoren på fanene oppfyller 3:1 kontrastkrav via `--ix-outline-default`. Aktiv-indikatoren (understreken) bruker brand-fargen `--ix-color-fill-main-default`; passiv/hover-understrek bruker `--ix-color-border-main-default`/`--ix-color-border-main-hover`. |
| 2.1.1 Tastatur | A | Full tastaturstøtte: Tab inn/ut av tablisten (roving tabindex — kun én tab-stopp), pil venstre/høyre flytter fokus mellom faner, Home/End til første/siste, Enter/Mellomrom aktiverer fokusert fane. |
| 2.1.2 Ingen tastaturfelle | A | Ingen tastaturfeller — fokus navigeres fritt ut av tablisten med Tab/Shift+Tab. |
| 2.4.3 Fokusrekkefølge | A | Roving tabindex gir én tab-stopp for hele tablisten; fokusrekkefølgen følger DOM: tablist før panel. |
| 2.4.7 Synlig fokus | AA | Tydelig fokusindikator rundt hele fanen (`:focus-visible`); tablisten reserverer vertikal plass (`padding-block`) så ringen ikke klippes av scroll-containeren. |
| 2.3.3 2.3.3 | ? | Overgangen på aktiv-indikatoren respekterer `prefers-reduced-motion: reduce` — transition settes til `none`. |
| 2.5.8 Målstørrelse (minimum) | AA | Hver fane har min. 44×44 px klikk-/touch-mål via `min-height`/`min-width` + padding. |
| 3.2.1 Ved fokus | A | Ingen kontekstendring ved fokus. Manuell aktivering: å flytte fokus mellom faner med piltast bytter ikke panel før brukeren trykker Enter/Mellomrom. |
| 3.2.2 Ved inndata | A | Å aktivere en fane gjør kun det forventede (viser tilhørende panel) — ingen automatisk kontekstendring eller navigasjon. |
| 4.1.2 Navn, rolle, verdi | A | Roller, navn og tilstand (`aria-selected`) eksponeres korrekt via ARIA satt av web componenten. Aktiv/valgt fane annonseres til skjermlesere. |
Ikke relevant (36)
| Kriterium | Nivå | Hvorfor ikke relevant |
|---|---|---|
| 1.1.1 Ikke-tekstlig innhold | A | Komponenten har ikke eget bildeinnhold. Et valgfritt prefiks-ikon i en fane er konsumentens ansvar (Icon-komponenten håndterer alt-tekst/aria-hidden), og kun-ikon-faner krever `ariaLabel` (se konsumentansvar). |
| 1.2.1 Bare lyd og bare video (forhåndsinnspilt) | A | Ingen medieelementer. |
| 1.2.2 Teksting (forhåndsinnspilt) | A | Ingen medieelementer. |
| 1.2.3 Synstolking eller mediealternativ (forhåndsinnspilt) | A | Ingen medieelementer. |
| 1.2.4 Teksting (direkte) | AA | Ingen medieelementer. |
| 1.2.5 Synstolking (forhåndsinnspilt) | AA | Ingen medieelementer. |
| 1.3.3 Sensoriske egenskaper | A | Formidler ikke instruksjoner basert på sensoriske egenskaper. |
| 1.3.4 Visningsretning | AA | Ingen fast orientering — tilpasser seg visningsretning. |
| 1.3.5 Identifiser formål med inndata | AA | Ikke et skjemafelt som ber om personlig informasjon. |
| 1.4.2 Styring av lyd | A | Ingen lydelementer. |
| 1.4.5 Bilder av tekst | AA | Ingen bilder av tekst. |
| 1.4.12 Tekstavstand | AA | |
| 1.4.13 Innhold ved hover eller fokus | AA | |
| 2.1.4 Tastatursnarveier | A | Ingen egendefinerte tastatursnarveier. |
| 2.2.1 Justerbar hastighet | A | Ingen tidsbegrensede funksjoner. |
| 2.2.2 Pause, stopp, skjul | A | Ingen animasjon eller automatisk oppdatering. |
| 2.3.1 Terskelverdi på tre glimt | A | Indikator-overgangen er kort, respekterer prefers-reduced-motion og blinker ikke. |
| 2.4.1 Hoppe over blokker | A | Sidekrav — gjelder ikke enkeltkomponenter. |
| 2.4.2 Sidetitler | A | Sidekrav — gjelder ikke enkeltkomponenter. |
| 2.4.5 Flere måter | AA | Sidekrav — gjelder ikke enkeltkomponenter. |
| 2.5.1 Pekerbevegelser | A | Ingen gestbaserte interaksjoner — enkelt klikk/tap eller tastatur. |
| 2.5.2 Avbryt peker | A | Aktivering skjer på pekeropp; et klikk kan avbrytes ved å dra bort før slipp. |
| 2.5.4 Bevegelsesaktivering | A | Ingen bevegelsesbasert interaksjon. |
| 2.5.6 Samtidige inndatamekanismer | A | |
| 2.5.7 Drabevegelser | A | Ingen drag-and-drop. |
| 3.1.1 Språk på siden | A | Sidekrav — gjelder ikke enkeltkomponenter. |
| 3.1.2 Språk på deler av innhold | AA | Komponenten setter ikke lang-attributt — innhold er på sidespråket. |
| 3.2.3 Konsistent navigasjon | AA | Sidekrav — gjelder ikke enkeltkomponenter. |
| 3.2.4 Konsistent identifikasjon | AA | Systemkrav — gjelder konsistens på tvers av sider, ikke enkeltkomponenter. |
| 3.2.6 Konsistent hjelp | A | Sidekrav — gjelder plassering av hjelpefunksjon på tvers av sider. |
| 3.3.1 Identifikasjon av feil | A | |
| 3.3.2 Ledetekster eller instruksjoner | A | |
| 3.3.3 Forslag ved feil | AA | |
| 3.3.4 Forhindring av feil (juridisk, økonomisk, data) | AA | Flytkrav — gjelder bekreftelse/reversering av transaksjoner, ikke enkeltfelter. |
| 3.3.7 Redundant oppføring | A | Flytkrav — gjelder at brukeren ikke skal gjenta informasjon i en prosess. |
| 3.3.8 Tilgjengelig autentisering (minimum) | AA | Ikke en autentiseringskomponent. |
Props / API
Props-tabellen genereres automatisk fra Storybook (tags: ['autodocs']).
Tilpasning med CSS
Trenger du ix-tabs-stylingen på HTML du setter sammen selv, uten React-komponenten, kan du bruke klassene direkte. Web componenten <ix-tabs> kobler roller, aria-controls, roving tabindex, tastatur og panel-visning ved mount; du skriver semantisk markup, gir hver fane og sitt panel et delt data-value, og markerer start-fanen med aria-selected="true" og de skjulte panelene med hidden.
Tilgjengelige klasser og selektorer
| Element/tilstand | Selektor / attributt |
|---|---|
| Rot | .ix-tabs på <ix-tabs> |
| Fane-liste (tablist) | .ix-tabs__list på <ix-tab-list> |
| Enkelt-fane | .ix-tabs__tab på <ix-tab> |
| Fane↔panel-kobling | delt data-value på <ix-tab> og <ix-tab-panel> |
| Aktiv fane | [aria-selected="true"] på fanen |
| Innholdspanel | .ix-tabs__panel på <ix-tab-panel> |
| Skjult panel | [hidden] på panelet (native) |
Understreken er synlig i alle tilstander og markerer tilstand med farge: passiv bruker --ix-color-border-main-default, hover --ix-color-border-main-hover og aktiv --ix-color-fill-main-default (brand-farge). Passiv fane-tekst bruker --ix-color-foreground-main-subtle, aktiv/hover-tekst --ix-color-foreground-main-default. Overstyr disse tokenene for å tilpasse fargene.
Eksempel: ren HTML
<ix-tabs class="ix-tabs">
<ix-tab-list class="ix-tabs__list" aria-label="Kontoinformasjon">
<ix-tab class="ix-tabs__tab" data-value="oversikt" aria-selected="true">Oversikt</ix-tab>
<ix-tab class="ix-tabs__tab" data-value="detaljer" aria-selected="false">Detaljer</ix-tab>
</ix-tab-list>
<ix-tab-panel class="ix-tabs__panel" data-value="oversikt">
<p>Innhold for oversikt.</p>
</ix-tab-panel>
<ix-tab-panel class="ix-tabs__panel" data-value="detaljer" hidden>
<p>Innhold for detaljer.</p>
</ix-tab-panel>
</ix-tabs>