# Indeks Designsystem > Felles retningslinjer og komponenter for SpareBank 1. Inneholder tokens, utility-klasser, React- og web components samt mønstre og maler. ## docs ### adr - [ADR-DS-001: Monorepo og byggverktøy](/docs/adr/ADR-DS-001-monorepo-og-byggverktoy.md): Alle pakker i én monorepo med pnpm (sikkerhetsisolasjon) og Turborepo (intelligent caching). Workspace-protokoll for interne avhengigheter. - [ADR-DS-002: Versjonering og publisering](/docs/adr/ADR-DS-002-versjonering-og-publisering.md): CSS, Web Components og React har alltid identisk versjonsnummer. Changesets for versjonering. Dual publishing til CDN (anbefalt) og npm. - [ADR-DS-003: CI/CD med GitHub Actions](/docs/adr/ADR-DS-003-ci-cd.md): GitHub Actions for all CI/CD med spesialiserte workflows gruppert etter prefiks — pr-, release-, deploy- og security-. - [ADR-DS-004: Web Components](/docs/adr/ADR-DS-004-web-components.md): Web Components brukes der ren HTML + CSS ikke er nok. React-pakken eksponerer samme funksjonalitet med idiomatisk React API. - [ADR-DS-005: React-bibliotek (Vite, ESM, React 18/19)](/docs/adr/ADR-DS-005-react-bibliotek.md): React-biblioteket bygges med Vite i library mode, distribueres som ESM-only, og støtter React 18 og 19 som peer dependency. - [ADR-DS-006: Design tokens](/docs/adr/ADR-DS-006-tokens-og-farger.md): Design tokens som JSON er single source of truth for web, iOS og Android. Toveis Figma-synkronisering med klare ansvarsgrenser. - [ADR-DS-007: Fargesystem](/docs/adr/ADR-DS-007-fargesystem.md): Farger genereres med OKLCH for perseptuelt uniforme skalaer. HSL forkastet fordi opplevd lysstyrke varierer mellom fargetoner. - [ADR-DS-008: Spacing-system (faste breakpoints + density)](/docs/adr/ADR-DS-008-spacing-system.md): Spacing bruker faste px-verdier på tre mobile-first breakpoints kombinert med et density-system (Compact/Default/Comfortable). Typografi bruker en rem-basert geometrisk skala uten density. - [ADR-DS-009: CSS-arkitektur](/docs/adr/ADR-DS-009-css-only-styling.md): All styling bruker ren HTML og CSS. Ingen CSS-in-JS. ix-prefix på alle klasser og variabler. - [ADR-DS-010: Komponentutvikling og testing](/docs/adr/ADR-DS-010-komponentutvikling-og-testing.md): Storybook for komponentutvikling. Docker-basert Playwright for reproduserbare visuelle tester og accessibility. - [ADR-DS-011: Dokumentasjon (Docusaurus, midlertidig)](/docs/adr/ADR-DS-011-dokumentasjon.md): Docusaurus 3 som midlertidig dokumentasjonsplattform. Migreres når CMS-avklaringer med merkevare er på plass. - [Kort fortalt](/docs/adr/oversikt.md): En rask, folkelig oversikt over hvorfor vi bygger Indeks selv og hvilke valg vi har tatt. For deg som vil ha helheten uten å lese alle ADR-ene. - [Retningslinjer for Indeks designsystem](/docs/adr/retningslinjer.md): Disse retningslinjene er ikke arkitekturbeslutninger, men konvensjoner teamet har blitt enige om. - [ADR-DS-XXX: [Beskrivende tittel]](/docs/adr/template.md): Mal for nye arkitekturbeslutninger i Indeks designsystem. ### grunnleggende - [Native](/docs/grunnleggende/native.md): Indeks brukes i hybridapper der webinnhold vises i native-appens WebView. For brukeren skal web-innholdet oppleves som en naturlig del av den native appen. - [Border](/docs/grunnleggende/tokens/border.md): Komponentene vi tilbyr har riktig border-radius og border-width som standard. Hvis du skal lage noe eget, kan du bruke border-variablene vi tilbyr. - [Farger for Native](/docs/grunnleggende/tokens/farger-native.md): Pakken @sb1/indeks-tokens inneholder fargetokens som kan bygges til forskjellige plattformer, inkludert native (iOS og Android). - [Farger for Web](/docs/grunnleggende/tokens/farger-web.md): Pakken @sb1/indeks-tokens inneholder fargetokens som brukes i hele designsystemet. På web trenger de aller fleste ikke å generere farger selv — den ferdig bygde CSS-en inneholder alt du trenger. Men du kan generere din egen web-CSS med et eget theme ved hjelp av den samme build-colors-kommandoen som brukes for native (iOS/Android). - [Fargeskalaer](/docs/grunnleggende/tokens/fargeskalaer.md): Et theme defineres med sju basisfarger — brand, success, info, danger, warning, gray og neutral. Ved build utvides hver av disse til en 20-trinns fargeskala (0–950), som blir til primitivene (--ii-primitive-*) de semantiske fargene peker på. - [Introduksjon](/docs/grunnleggende/tokens/introduksjon.md): Design tokens er de minste byggesteinene i designsystemet. De representerer visuelle verdier som farger, typografi, spacing, radius og skygger osv. definert som navngitte variabler i stedet for faste verdier. - [Spacing](/docs/grunnleggende/tokens/spacing.md): Spacing-systemet i Indeks sikrer konsistente avstander mellom elementer på tvers av flater. Systemet bruker faste px-verdier som justeres på tre breakpoints, og kan tilpasses behov for mer eller mindre kompakt visning. - [Z Index](/docs/grunnleggende/tokens/z-index.md): Z-index er en CSS-egenskap som styrer stablingsrekkefølgen til elementer på en nettside. Med z-index kan du bestemme hvilke elementer som skal ligge over eller under andre, spesielt når de overlapper hverandre. For å sikre konsistens og forutsigbarhet i designet, har vi definert en rekke z-index tokens som dekker vanlige brukstilfeller i SpareBank 1 sitt designsystem. - [Typografi](/docs/grunnleggende/typografi.md): Våre fonter ### hjem Indeks er SpareBank 1 sitt designsystem - et verktøy for å lage helhetlige, brukervennlige og inkluderende løsninger. - [Indeks](/docs/hjem.md): Indeks er SpareBank 1 sitt designsystem - et verktøy for å lage helhetlige, brukervennlige og inkluderende løsninger. ### kom-i-gang - [Bidra](/docs/kom-i-gang/bidra.md): Enten du mangler en komponent, har forslag til forbedringer, eller har funnet noe som ikke fungerer som det skal, vil vi gjerne høre fra deg. - [Designer](/docs/kom-i-gang/designer.md): Før du begynner - [Introduksjon](/docs/kom-i-gang/grunnleggende.md): Visuell identitet - [Kontakt](/docs/kom-i-gang/kontakt.md): Indeks blir best når vi snakker sammen. Vi setter stor pris på alle innspill, spørsmål og bidrag fra dere som bruker systemet. - [Migrering fra FFE til Indeks](/docs/kom-i-gang/migrering.md): Indeks er et helt nytt designsystem, bygget opp fra grunnen med en annen arkitektur og struktur enn FFE. For deg som skal migrere fra FFE betyr dette at enkelte ting må gjøres litt annerledes enn før. - [Utvikler](/docs/kom-i-gang/utvikler.md): Kom i gang med Indeks i prosjektet ditt. Velg teknologi under, så tilpasser guiden seg. ### komponenter - [Accordion](/docs/komponenter/accordion.md): Accordion viser og skjuler innhold i seksjoner. Den er nyttig når mye innhold skal gjøres oversiktlig: brukeren ser overskriftene og åpner kun det som er relevant. Komponenten bygger på native `/`, så tastatur og skjermleser fungerer uten ekstra oppsett. - [Button](/docs/komponenter/button.md): Button lar brukeren utføre en handling, som å sende inn et skjema, lagre endringer eller navigere videre i en prosess. - [Card](/docs/komponenter/card.md): Card er én ting: en avgrenset, selvstendig innholdsenhet med fast ramme og bakgrunn. Et kort kan - [Chip](/docs/komponenter/chip.md): Chip er små, interaktive komponenter som lar brukeren gjøre raske valg, filtrere innhold eller trigge handlinger. Chips brukes ofte i grupper og gir en kompakt og oversiktlig måte å presentere valg på. - [Button chip](/docs/komponenter/chip/button.md): En button chip fungerer som en knapp og trigger en handling — for eksempel et hurtigvalg, et forslag eller et filter brukeren aktiverer. Den har ingen vedvarende valgt tilstand. - [Checkbox chip](/docs/komponenter/chip/checkbox.md): En checkbox chip er en gruppe chips der brukeren kan velge ett eller flere alternativer samtidig — som kompakte filter- eller preferansevalg. Hvert valg er uavhengig av de andre. - [Radio chip](/docs/komponenter/chip/radio.md): En radio chip er en gruppe chips der brukeren velger nøyaktig ett alternativ — som en kompakt segment-velger eller filtervalg. Å velge én chip fjerner automatisk valget på den forrige. - [Removable chip](/docs/komponenter/chip/removable.md): En removable chip representerer et aktivt valg eller en verdi som brukeren kan fjerne — for eksempel et valgt filter. Den finnes kun i valgt tilstand (den eksisterer ikke før den er valgt) og vises med fylt aksentfarge og et kryss til høyre. - [Icon](/docs/komponenter/icon.md): Ikon-komponenten viser SVG-ikoner fra SpareBank 1s CDN ved hjelp av CSS mask-image. Ikoner arver farge fra omgivende tekst. - [Ikonbruk](/docs/komponenter/icon-analyse.md): Oversikt over alle Material Design-ikoner brukt i SB1-apper, med hvor mange apper som bruker hvert ikon. Basert på bruksdata fra SpareBank 1-apper. - [InteractiveIcon](/docs/komponenter/interactive-icon.md): InteractiveIcon er en klikkbar ikon-flate — en kompakt knapp som bare viser et ikon. Den gir tydelig visuell tilbakemelding ved pekehvil, trykk og fokus, med en fargetone som kan styres av en status. - [Message](/docs/komponenter/message.md): Message formidler status eller resultatet av en handling — informasjon, suksess, advarsel eller feil — uten å avbryte flyten. Komponenten brukes inline, tett på innholdet den forklarer, og kan strekkes til full bredde av forelderen. - [Modal](/docs/komponenter/modal.md): Modal brukes til å vise innhold oppå eksisterende side og krever at brukeren forholder seg til innholdet før de kan fortsette. Komponenten fungerer som en tom container som fylles med innhold basert på behov. Den bygger på det native ``-elementet, så fokushåndtering, tastatur og skjermleser fungerer uten ekstra oppsett. - [Grid](/docs/komponenter/primitives/grid.md): Grid er en layout-primitiv for å stable innhold i to dimensjoner — vertikalt og horisontalt. Den fungerer både som custom element (`) og som CSS-klasse (.ix-grid`). - [Stack](/docs/komponenter/primitives/stack.md): Stack er en layout-primitiv for å stable innhold i én dimensjon — vertikalt eller horisontalt. Den fungerer både som custom element (`) og som CSS-klasse (.ix-stack`). - [ProgressBar](/docs/komponenter/progress-bar.md): ProgressBar viser fremdriften i én sammenhengende prosess — enten som pågående progresjon (for eksempel opplasting) eller som status for at prosessen er fullført eller feilet. Komponenten er rent informativ og kan ikke motta brukerinput. - [ReadMore](/docs/komponenter/read-more.md): ReadMore viser og skjuler én frittstående tekstblokk bak en klikkbar label. Den er nyttig for utdypende, sekundær informasjon som ikke alle trenger med en gang: brukeren ser labelen og åpner forklaringen kun ved behov. Komponenten bygger på native `/`, så tastatur og skjermleser fungerer uten ekstra oppsett. - [Checkbox](/docs/komponenter/skjema/checkbox.md): Checkbox lar brukeren velge én eller flere alternativer fra en liste. Hvert valg er uavhengig av de andre, og flere kan være valgt samtidig. - [CheckboxGroup](/docs/komponenter/skjema/checkbox-group.md): CheckboxGroup samler flere relaterte checkboxer i én gruppe der brukeren kan velge ett eller flere alternativer samtidig. Hvert valg er uavhengig av de andre. - [Designvalg for CheckboxGroup](/docs/komponenter/skjema/checkbox-group-designvalg.md): Denne siden forklarer hvorfor CheckboxGroup er bygget som den er. Den er ment for de som er nysgjerrige på avveiningene bak komponenten — du trenger den ikke for å bruke den. For bruk og API, se CheckboxGroup. - [Combobox](/docs/komponenter/skjema/combobox.md): Combobox lar brukeren søke etter og velge ett eller flere alternativer fra en liste. Brukeren skriver for å filtrere, og valgte alternativer vises enten som verdi i feltet (single) eller som chips over feltet (flervalg). - [Combobox i ren HTML](/docs/komponenter/skjema/combobox-html.md): Denne siden forklarer i detalj hvordan ` fungerer når du skriver ren HTML, Astro eller et annet ikke-React-miljø. Bruker du React, holder det å lese Combobox — der er hele strukturen skjult bak Combobox`-komponenten. For bruk, tilstander og API, se hovedsiden. - [DateField](/docs/komponenter/skjema/date-field.md): DateField lar brukeren taste en dato i norsk format (dd.mm.åååå) eller åpne enhetens innebygde kalender via en knapp i feltet. Verdien som sendes videre er alltid ISO (åååå-mm-dd), uavhengig av hva som vises i feltet. - [Label](/docs/komponenter/skjema/label.md): Label er ledeteksten til et skjemafelt. - [PhoneNumberField](/docs/komponenter/skjema/phone-number-field.md): PhoneNumberField lar brukeren oppgi et telefonnummer med landkode. Komponenten setter sammen en søkbar landvelger (der brukeren velger land, ikke skriver tallkode) og et nummerfelt som formateres mens man skriver — under én felles label og én felles feilmelding. - [RadioGroup](/docs/komponenter/skjema/radio-group.md): RadioGroup lar brukeren velge ett alternativ fra en liste av gjensidig utelukkende valg. Når ett valg gjøres, blir eventuelle tidligere valg automatisk fjernet. - [Designvalg for RadioGroup](/docs/komponenter/skjema/radio-group-designvalg.md): Denne siden forklarer hvorfor RadioGroup er bygget som den er. Den er ment for de som er nysgjerrige på avveiningene bak komponenten — du trenger den ikke for å bruke den. For bruk og API, se RadioGroup. - [Select](/docs/komponenter/skjema/select.md): Select lar brukeren velge ett alternativ fra en nedtrekksliste. Komponenten skjuler alternativene til brukeren åpner listen, og brukes når det ikke er nødvendig å vise alle valg samtidig. - [TextArea](/docs/komponenter/skjema/textarea.md): TextArea lar brukeren skrive inn lengre fritekst over flere linjer, som beskrivelser, meldinger eller begrunnelser. - [TextField](/docs/komponenter/skjema/textfield.md): TextField er et inputfelt for kortere tekst eller tall, som kontonummer, e-postadresse eller beløp. - [Formatering](/docs/komponenter/skjema/textfield-formatering.md): TextField kan formatere innholdet automatisk mens brukeren fyller ut — beløp med tusenskille, telefonnummer i grupper, kontonummer, fødselsnummer. Denne siden forklarer hvordan formatering virker, de to modusene, de tre måtene å definere en formatter på, og tilgjengelighetshensynene bak. For vanlig bruk og API, se TextField. - [Tooltip](/docs/komponenter/skjema/tooltip.md): En Tooltip er en liten informasjonsboks som vises når brukeren holder musepekeren over, fokuserer på eller berører et element. Den brukes til å gi ekstra kontekst, forklaringer eller detaljer uten å forstyrre hovedinnholdet. - [ValidationMessage](/docs/komponenter/skjema/validation-message.md): ValidationMessage viser en feilmelding knyttet til et skjemafelt eller en feltgruppe. - [Spinner](/docs/komponenter/spinner.md): Spinner viser at noe lastes inn eller at en operasjon pågår. Den er ikke-interaktiv og kommuniserer utelukkende tilstand. - [Surface](/docs/komponenter/surface.md): Surface er flaten flere ting ligger på: en region som samler flere beslektede elementer og - [Tabs](/docs/komponenter/tabs.md): 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. - [Tag](/docs/komponenter/tag.md): Etter Figma-designet skal subtle-varianten ha farget tekst per status (blå på - [Typografi](/docs/komponenter/typografi.md): Typografikomponenter i Indeks. Størrelse settes med data-size-attributtet — se oversikten på siden for riktig bruk. ### monstre-og-maler - [Deaktiverte tilstander](/docs/monstre-og-maler/deaktiverte-tilstander.md): I Indeks anbefaler vi som hovedregel å unngå bruk av deaktiverte tilstander som disabled. Deaktiverte komponenter kan virke som en enkel løsning, men fører ofte til dårligere brukeropplevelse, lavere tilgjengelighet og mer frustrasjon enn nødvendig. Når en kontroll er deaktivert, fjernes den i praksis fra samspillet mellom bruker og grensesnitt – uten at det nødvendigvis blir tydelig hvorfor. - [Form-validering](/docs/monstre-og-maler/form-validering.md): Indeks sine form-komponenter er bring-your-own-validation: hver komponent tar en ferdig errorMessage-streng og viser den (og setter aria-invalid selv). Selve valideringen — reglene og feilmeldingene — overlater vi til et form-rammeverk og et skjema. Denne siden viser det anbefalte oppsettet med React Hook Form (RHF) og Valibot. - [Layout](/docs/monstre-og-maler/layout.md): Indeks tilbyr et sett med layout-utilities for å hjelpe med oppsett av elementer på siden ved bruk av Flex og CSS Grid. Disse klassene kan brukes direkte i HTML for raskt å justere layout uten behov for egendefinert CSS. - [Spacing](/docs/monstre-og-maler/spacing.md): For å sikre konsistente og forutsigbare layouter i applikasjoner bygget med Indeks følger vi et sett med retningslinjer for distribusjon av spacing. Klare mønstre for avstand mellom elementer hjelper oss med å skape en harmonisk og brukervennlig visuell struktur på tvers av applikasjoner. Oppsummert dreier det seg om disse prinsippene: ### ordbok Forklaringer på fagbegreper som brukes i Indeks-dokumentasjonen. - [Ordbok](/docs/ordbok.md): Forklaringer på fagbegreper som brukes i Indeks-dokumentasjonen. ### retningslinjer - [Designprinsipper](/docs/retningslinjer/designprinsipper.md): SpareBank 1 sine flater skal være lette å bruke for alle demografier. - [Farger](/docs/retningslinjer/farger.md): I Indeks bruker vi semantiske farger. Det betyr at farger defineres og navngis ut fra hvordan de brukes, ikke hvordan de ser ut. For eksempel navngir vi en farge "Background" i stedet for å bruke det visuelle navnet (f.eks fjell) eller en hex-verdi. - [Fargemodus (light og dark)](/docs/retningslinjer/farger/fargemodus.md): De semantiske fargevariablene i Indeks (--ix-color-*) har egne verdier for light og dark mode. Alle komponenter leser disse variablene, så de tilpasser seg automatisk. ### utility-klasser - [Native](/docs/utility-klasser/native.md): Utility-klasser for å kontrollere tekstmarkering, berøring og dra-og-slipp-oppførsel i hybridapper der webinnhold vises i en native app sin WebView. - [Utility-klasser](/docs/utility-klasser/oversikt.md): Utility-klasser er hjelpeklasser i CSS, designet for å enkelt kunne legge vanlige styling-properties til elementer ved behov. Hver klasse har sitt eget separate formål og består av én enkelt CSS-property, eller et mindre sett med properties for å oppnå en spesifikk effekt. Flere klasser kan brukes samtidig for å bygge opp komplette elementer. Komponentene i Indeks er i stor grad bygget med utility-klasser. --- # Full Documentation Content # ADR-DS-001: Monorepo og byggverktøy StatusBesluttet ## Beslutning[​](#beslutning "Direct link to Beslutning") Alle pakker samles i én [Monorepo](/docs/ordbok.md#Monorepo) med **[pnpm](/docs/ordbok.md#pnpm)** som pakkebehandler og **[Turborepo](/docs/ordbok.md#Turborepo)** for build-orkestrering. ### Monorepo[​](#monorepo "Direct link to Monorepo") Alle pakker i samme repo med workspace-protokoll (`workspace:*`) for interne avhengigheter. Pakker publisert til npm: `indeks-tokens`, `indeks-utils`, `indeks-css`, `indeks-web`, `indeks-react`. Private pakker: `indeks-docs`, `indeks-eksempel` og `indeks-storybook`. ### pnpm[​](#pnpm "Direct link to pnpm") Erstattet npm. To sentrale sikkerhetsmekanismer: `shamefully-hoist=false` sikrer streng isolasjon — pakker kan bare bruke avhengigheter de selv har deklarert i `package.json`. Det forhindrer at kode ved et uhell bruker transitive avhengigheter, noe som reduserer risikoen for at en ondsinnet pakke kan nå kode den ikke skal ha tilgang til. `strict-peer-dependencies=true` tvinger frem eksplisitte [peer dependency]()-erklæringer, slik at versjonskonflikter oppdages tidlig i utviklingen fremfor hos konsumenter i produksjon. Content-addressable storage betyr at hver pakkeversjon lagres én gang på disken og verifiseres med en hash ved installasjon — manipulasjon av nedlastede pakker oppdages umiddelbart. ### Turborepo[​](#turborepo "Direct link to Turborepo") Erstattet Lerna for bygging. `^build` sikrer riktig byggerekkefølge basert på dependency-grafen — `indeks-css` bygges aldri før `indeks-tokens` er ferdig. Caching baseres på innholdshasher av kildefiler og avhengigheter: hvis ingenting har endret seg siden forrige bygg, hoppes pakken over. Parallell bygging der det er mulig. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Tett kobling mellom pakker krever koordinert utvikling i samme repo * Kjent monorepo-mønster fra eksisterende SpareBank 1 designsystem (`@sb1/ffe-*`) * Bedre sikkerhet enn npm for pakkebehandling * Intelligent caching for raskere CI og lokal utvikling ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") Designsystemet har tette avhengigheter mellom pakkene: ``` indeks-tokens → indeks-utils → indeks-css → indeks-web → indeks-react ``` En endring i tokens påvirker hele kjeden. Pakkene må kunne utvikles og testes i sammenheng, ikke isolert. Vi startet med npm workspaces og Lerna, men npm manglet sikkerhetsfunksjoner og Lerna var utdatert og treg. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvilken monorepo-strategi og verktøykjede støtter koordinert utvikling og testing på tvers av tett koblede pakker, med god sikkerhet og intelligent caching? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Alle utviklere som jobber med designsystemet må bruke pnpm og forstå workspace-konsepter. ### Ulemper[​](#ulemper "Direct link to Ulemper") * Hele repoet må klones (ikke bare én pakke) * Utviklere må installere pnpm — ikke alle har det fra før * CI-miljøer må konfigureres med pnpm * Noen eldre pakker kan ha problemer med pnpms strenge node\_modules-struktur ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * Turborepo-caching og parallellisering gjør CI raskt til tross for én stor repo * Dokumentasjon veileder nye utviklere gjennom oppsett ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### Separate repositories per pakke[​](#separate-repositories-per-pakke "Direct link to Separate repositories per pakke") Hver pakke i sitt eget git-repository, publisert uavhengig. **Forkastet fordi:** Vanskelig å koordinere endringer på tvers av pakker. En token-endring krever PR i fire separate repos med nøye rekkefølge — i praksis upraktisk. ### Én stor pakke[​](#én-stor-pakke "Direct link to Én stor pakke") Slå sammen alle pakker til ett npm-pakke. **Forkastet fordi:** Konsumenter som bare trenger tokens eller CSS må ta inn React-kode. Umuliggjør uavhengig versjonering. ### npm (i stedet for pnpm)[​](#npm-i-stedet-for-pnpm "Direct link to npm (i stedet for pnpm)") npm er standard og forhåndsinstallert hos alle Node.js-brukere. **Forkastet fordi:** Mangler pnpms sikkerhetsisolasjon og er tregere, særlig ved store dependency-grafer. Gammel npm-basert løsning var allerede en kilde til problemer. ### Yarn Berry (Plug'n'Play)[​](#yarn-berry-plugnplay "Direct link to Yarn Berry (Plug'n'Play)") Yarns nye arkitektur med zero-installs og PnP-resolver i stedet for node\_modules. **Forkastet fordi:** Plug'n'Play bryter mange verktøy som forventer en tradisjonell node\_modules-mappe (Jest, Storybook m.fl.) og krever stor migrasjonsoverhead for å gjøre eksisterende tooling kompatibelt. ### Nx[​](#nx "Direct link to Nx") Et build-system med monorepo-støtte og avansert dependency-graf. **Forkastet fordi:** Mer komplekst enn nødvendig for dette prosjektet. Turborepo dekker behovene med vesentlig enklere konfigurasjon. ### Lerna[​](#lerna "Direct link to Lerna") Det opprinnelige verktøyet vi brukte for monorepo-håndtering. **Forkastet fordi:** Utdatert, treg, og Lerna-teamet anbefaler selv Nx eller Turborepo for nye prosjekter. Vi opplevde konkrete ytelses- og vedlikeholdsproblemer. Deltakere Utarbeidet avTeam Designsystem --- # ADR-DS-002: Versjonering og publisering StatusBesluttet ## Beslutning[​](#beslutning "Direct link to Beslutning") `indeks-css`, `indeks-web` og `indeks-react` har alltid identisk versjonsnummer og bumpes alltid sammen. Endringer dokumenteres med **[Changesets](/docs/ordbok.md#Changesets)**. Pakker publiseres til både **[CDN](/docs/ordbok.md#CDN)** (anbefalt) og **npm**. ### Versjonering[​](#versjonering "Direct link to Versjonering") `indeks-css`, `indeks-web` og `indeks-react` har alltid identisk versjonsnummer — en endring i én bumper alle tre. `indeks-tokens` og `indeks-utils` versjoneres uavhengig. Changesets er konfigurert slik at en endring i `indeks-tokens` eller `indeks-utils` automatisk utløser en patch-bump i `indeks-css`, som igjen bumper `indeks-web` og `indeks-react`. `indeks-web` er pakken med Web Components (rammeverk-uavhengig komponentlogikk) — se [ADR-DS-004](/docs/adr/ADR-DS-004-web-components.md) for mer om arkitekturen. ### Changesets[​](#changesets "Direct link to Changesets") Erstattet Lerna + Conventional Commits. `pnpm changeset` dokumenterer endringer i en fil uavhengig av commit-meldinger. Ingen krav til commit-format. ### Distribusjon[​](#distribusjon "Direct link to Distribusjon") **CDN (anbefalt):** `cdn.sparebank1.no/indeks/css/{versjon}/index.css` — versjonerte URLer kan caches "for alltid" i nettleseren. CDN-bygget publiserer `indeks-css`, `indeks-tokens`, `indeks-utils` og `indeks-web`. `indeks-css` henter automatisk inn tokens og utils, slik at konsumenter bare trenger én ``-tag. CDN-bygget er et eget build-target der PostCSS-plugin erstatter interne npm-imports med absolutte CDN-URLer, slik at CSS-filen er selvforsynt uten bundler. **npm (alternativ):** `@sb1/indeks-css`, `@sb1/indeks-web` og `@sb1/indeks-react` for bundler-baserte apps. Avhengigheter håndteres automatisk via `workspace:*`. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Garantert kompatibilitet mellom CSS og React — konsumenter slipper å teste kombinasjoner * Optimal CDN-caching med versjonerte URLer * Lavere terskel for bidragsytere uten krav om commit-format * Fleksibilitet for team med ulik teknisk infrastruktur ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") `indeks-web` og `indeks-react` avhenger av CSS-klasser fra `indeks-css` — versjoner ute av sync gir feil styling. Konsumenter trenger garantert kompatibilitet uten å måtte teste kombinasjoner. I tillegg må CSS kunne konsumeres på to måter: via bundler (npm) og direkte via ``-tag (CDN). CDN-distribusjon krever versjonerte URLer for å muliggjøre evig caching. Vi brukte tidligere Lerna med Conventional Commits, men brukte mye tid på å rette commit-meldinger og terskelen for å bidra var høy. Verktøyet var i tillegg utdatert. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvordan sikrer vi garantert kompatibilitet mellom CSS og React-pakker, støtter både CDN og npm-distribusjon, og holder terskelen for bidrag lav? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Alle konsumenter velger mellom CDN og npm. Alle bidragsytere bruker `pnpm changeset` i stedet for Conventional Commits. ### Ulemper[​](#ulemper "Direct link to Ulemper") * Små CSS-endringer bumper React-versjon og omvendt, selv uten funksjonell endring * Ekstra steg (`pnpm changeset`) i utviklingsflyten * To build-outputs å vedlikeholde (npm + CDN) * CDN-brukere må manuelt oppdatere versjonsnummer i ``-tag ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * CI blokkerer merge hvis det allerede finnes en åpen release-PR — sikrer at ikke to versjonsoppdateringer havner i køen samtidig * CDN-versjoner publiseres automatisk ved release ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### Alle pakker samme versjon (som @sb1/ffe)[​](#alle-pakker-samme-versjon-som-sb1ffe "Direct link to Alle pakker samme versjon (som @sb1/ffe)") Tokens, CSS og React bumpes alltid til samme versjon, som i SpareBank 1s eksisterende designsystem FFE. **Forkastet fordi:** `indeks-tokens` og `indeks-utils` endres sjelden, og skal beholde et stabilt versjonsnummer slik at deres egne CDN-artefakter kan caches lengst mulig. Cascade-bumpingen går bevisst kun én vei — en token- eller utils-endring patch-bumper `indeks-css` (og dermed `indeks-web` og `indeks-react`), men en css/web/react-endring bumper *aldri* tokens/utils tilbake. Å låse alle fire til samme versjon (FFE-stil) ville bumpet tokens/utils ved hver minste css- eller react-endring og ugyldiggjort cachen deres helt unødvendig. ### Helt uavhengige versjoner[​](#helt-uavhengige-versjoner "Direct link to Helt uavhengige versjoner") Alle pakker versjoneres uavhengig uten noen form for synkronisering. **Forkastet fordi:** Vanskelig for konsumenter å vite hvilke kombinasjoner av CSS og React som fungerer sammen. Øker supportbyrden. ### Lerna + Conventional Commits[​](#lerna--conventional-commits "Direct link to Lerna + Conventional Commits") Det opprinnelige verktøyet vi brukte. **Forkastet fordi:** Utdatert verktøy, høy terskel grunnet krav om spesifikk commit-format, og vi brukte faktisk tid på å fikse commit-meldinger i stedet for å lage produktet. ### semantic-release[​](#semantic-release "Direct link to semantic-release") Automatisk versjonering basert på commit-meldinger. **Forkastet fordi:** Krever fortsatt Conventional Commits — løser ikke terskelen for bidrag. ### Kun npm eller kun CDN[​](#kun-npm-eller-kun-cdn "Direct link to Kun npm eller kun CDN") Publisere bare til én distribusjonskjøre i stedet for begge. **Forkastet fordi:** Team med ulik infrastruktur trenger begge. Kun CDN fungerer ikke for bundler-baserte apper som trenger [tree-shaking](/docs/ordbok.md#tree-shaking). Kun npm mister CDN-caching-fordelene. Deltakere Utarbeidet avTeam Designsystem --- # ADR-DS-003: CI/CD med GitHub Actions StatusBesluttet ## Beslutning[​](#beslutning "Direct link to Beslutning") All CI/CD kjøres med **GitHub Actions**, organisert i spesialiserte workflows gruppert etter prefiks: `pr-`, `release-`, `deploy-` og `security-`. ### PR-workflows[​](#pr-workflows "Direct link to PR-workflows") Kjøres på pull requests mot main. * **`pr-build-and-preview.yml`** — Bygger alle pakker, kjører lint og tester, bygger [Storybook](/docs/ordbok.md#Storybook), og deployer forhåndsvisning til Azure Static Web Apps. Inkluderer lisenssjekk og sikkerhetsaudit. * **`pr-playwright.yml`** — Kjører [Playwright](/docs/ordbok.md#Playwright)-tester i [Docker](/docs/ordbok.md#Docker) mot Storybook. Trigges bare ved endringer i komponent- og stilpakker. * **`pr-cleanup.yml`** — Sletter Azure-forhåndsvisningen når en PR lukkes. ### Release-workflow[​](#release-workflow "Direct link to Release-workflow") * **`release-tag-and-publish.yml`** — Trigger: push til main. Bruker `dotansimha/changesets-action` med to utfall: hvis det finnes uforbrukte changesets opprettes en versjonerings-PR; hvis en versjonerings-PR nettopp er merget publiseres pakkene til npm. Pakkene publiseres med [npm provenance]() — en kryptografisk kobling mellom npm-pakken og GitHub Actions-kjøringen som produserte den, slik at konsumenter kan verifisere at pakken faktisk ble bygget fra kildekoden i repoet. ### Deploy-workflow[​](#deploy-workflow "Direct link to Deploy-workflow") * **`deploy-docs.yml`** — Trigger: push til main (ved endringer i docs, storybook, komponenter). Bygger docs, Storybook og eksempel-app, og deployer til Azure Static Web Apps (design.sparebank1.no). Kan kjøres manuelt med valgfri commit-SHA. ### Security-workflows[​](#security-workflows "Direct link to Security-workflows") * **`security-codeql.yml`** — CodeQL-skanning av JavaScript på PR, push til main og ukentlig schedule. * **`security-zizmor.yml`** — Skanner workflow-filer med [Zizmor](https://github.com/zizmorcore/zizmor), et statisk analyseverktøy som finner sikkerhetsproblemer i GitHub Actions-konfigurasjoner (f.eks. script injection, overprivilegerte tokens). Kjøres ved endringer i `.github/workflows/`. Funn blokkerer merge via branch protection rules. * **`security-npm-deprecate.yml`** — Manuell workflow for å deprecate eller unpublish npm-pakker ved sikkerhetshendelser. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Tett integrasjon med GitHub — ingen separate tokens, bruker GITHUB\_TOKEN * God marketplace med ferdige actions for pnpm, Azure og GitHub Pages * Innebygd secrets management via GitHub Secrets * Alle på teamet kjenner GitHub Actions fra andre prosjekter ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") Prosjektet trenger automatisert bygging, testing, publisering og deployment. Kilden er GitHub, og vi ønsker sterk integrasjon mellom kode og CI/CD — ikke et separat verktøy som må autentiseres og vedlikeholdes ved siden av. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvilken CI/CD-løsning gir best integrasjon med GitHub-basert kildekode, uten å innføre ekstra verktøy og autentiseringskompleksitet? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Alle utviklere som pusher kode trigger workflows. Teamet vedlikeholder workflow-filer. ### Ulemper[​](#ulemper "Direct link to Ulemper") * Vendor lock-in til GitHub — vanskelig å flytte til annen platform uten å skrive om workflows * YAML-konfigurasjon kan bli kompleks og er vanskelig å teste lokalt ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * Workflows holdes enkle og modulære med klare ansvarsgrenser per prefiks * Kompleks logikk flyttes til scripts som kan kjøres lokalt ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### CircleCI[​](#circleci "Direct link to CircleCI") En populær CI/CD-plattform med god ytelse og parallelliseringsevne. **Forkastet fordi:** Ekstra integrasjon og kostnad. GitHub Actions gir tilsvarende funksjonalitet uten ekstra verktøy og med bedre GitHub-integrasjon. ### GitLab CI[​](#gitlab-ci "Direct link to GitLab CI") CI/CD integrert i GitLab, med sterk integrasjon mellom kode og pipelines. **Forkastet fordi:** Kildekoden er på GitHub, og å flytte til GitLab bare for CI gir ekstra kompleksitet. Fordelene GitLab CI gir er de samme som GitHub Actions allerede tilbyr på GitHub-siden. ### Jenkins[​](#jenkins "Direct link to Jenkins") Et selvhostet, svært fleksibelt CI/CD-system med lang historikk. **Forkastet fordi:** Krever egen infrastruktur å vedlikeholde. For et lite team er vedlikeholdsoverheaden ikke verdt fleksibiliteten. ### Azure DevOps[​](#azure-devops "Direct link to Azure DevOps") Microsofts ALM-platform med Pipelines for CI/CD. **Forkastet fordi:** Ekstra verktøy utenfor GitHub. SpareBank 1 bruker Azure for hosting, men kodeplatformen er GitHub — å splitte CI/CD til Azure DevOps gir unødvendig kompleksitet. Deltakere Utarbeidet avTeam Designsystem --- # ADR-DS-004: Web Components StatusBesluttet | Statuslogg | | | ---------- | --------- | | 2026-07-29 | Besluttet | | 2026-07-24 | Besluttet | ## Beslutning[​](#beslutning "Direct link to Beslutning") Komponentlogikk implementeres som **[Web Components]()** i `indeks-web` og eksponeres til React-konsumenter via `indeks-react`. [Shadow DOM]() unngås som hovedregel. Eksempel: `ix-field` er ikke et input-felt — det er et omgivende lag som knytter label, input og feilmelding sammen med korrekte ARIA-relasjoner. Alt dette kan også gjøres med ren HTML; Web Component-en gjør det bare enklere og feilsikkert. **Shadow DOM:** Vi unngår Shadow DOM som hovedregel. Shadow DOM isolerer markup fra resten av dokumentet, noe som gjør tilgjengelighetsarbeid vanskeligere — skjermlesere og ARIA-relasjoner må fungere på tvers av shadow boundaries, og konsumenter mister muligheten til å style med CSS-variabler. Unntaket er komponenter som viser visuelt innhold basert på universelt utformet data i markup — for eksempel et chart-element som rendres visuelt i Shadow DOM mens tabelldata forblir tilgjengelig i vanlig DOM. **Arkitektur:** `indeks-web` (Web Components) → `indeks-react` (wrapper). React-pakken eksponerer komponentene med idiomatisk React API. Det meste av funksjonaliteten ligger i Web Component-en — React-laget håndterer React-spesifikke ting som event-mapping og prop-konvertering, slik at en ren-HTML-konsument får nøyaktig samme fullverdige komponent. Hvordan `indeks-react` bygges og distribueres er beskrevet i [ADR-DS-005](/docs/adr/ADR-DS-005-react-bibliotek.md). **Bevisste rammeverk-tilpasninger:** React-laget kan ha målrettede tilpasninger for å fungere godt med utbredte React-verktøy — for eksempel props som gjør en komponent kompatibel med React Hook Form (`register()`), slik at skjemakobling blir idiomatisk. Slike tilpasninger handler utelukkende om *integrasjon* — å få React til å fungere — aldri om å gi React-konsumenter mer funksjonalitet eller en annen brukeropplevelse. **UI og UX skal være identisk uansett konsument.** En bruker skal ikke kunne se eller kjenne — verken visuelt eller via tastatur og skjermleser — om et felt er bygget med ren HTML eller React. HTML-versjonen av hver komponent er fullverdig i seg selv; React-wrapperen legger ikke til noe ekstra, den kabler bare det som allerede finnes lenger ned i stacken. Det som *skal* skille seg, er API-flaten: React får idiomatiske props, typer og JSX, mens HTML får attributter og web component. Ulikt grensesnitt, lik komponent. Tilpasninger er tillatt så lenge to ting holder: (1) Web Component-en forblir kilden til sannhet — logikken legges i WC-en når den også gagner ikke-React-konsumenter (f.eks. native `change`-events og fokushåndtering på riktig element), og React-laget begrenser seg til tynn kabling; og (2) HTML-pariteten bevares — en ren-HTML- eller Vue/Angular-konsument får samme fullverdige komponent, ikke en redusert variant. En React-only-egenskap som ikke lar seg uttrykke i WC-en, skal være liten, veldokumentert og ikke bryte de andre konsumentene. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Rammeverk-uavhengighet — webstandard fungerer i React, Vue, Angular, Astro og ren HTML * Én kilde til sannhet for komponentlogikk * Fremtidssikring uavhengig av rammeverk-trender * Nettleser-native uten ekstra runtime ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") De fleste komponentene i Indeks er ren HTML-markup med CSS-styling — React wrapper bare dette, og man kan like gjerne bruke ren HTML. Men noen komponenter trenger mer: logikk, tilstandshåndtering eller sammensatt atferd som knytter flere elementer sammen. SpareBank 1 har team som bruker ulike teknologier — ikke bare React. En løsning som låser kompleks komponentlogikk til React er ikke fremtidssikret. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvordan implementerer vi komponentlogikk slik at den er tilgjengelig for alle team, uavhengig av hvilke JavaScript-rammeverk de bruker? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") * **Team Designsystem** — implementerer Web Components * **React-konsumenter** — bruker React-wrapperen og slipper å forholde seg til maskineriet under; for team som vil bygge frontend uten å tenke på hvordan det fungerer, er dette et godt valg * **Andre team** — får tilgang til komponentlogikk uten React-avhengighet; team som bruker andre rammeverk eller vil tilpasse mer, ser naturlig mer av kompleksiteten bak — men får samme komponent * **Designere** — ingen endring Abstraksjonsnivået skalerer altså med hvor mye konsumenten vil involvere seg: React skjuler mest, ren HTML og andre rammeverk eksponerer mer av maskineriet. Uansett nivå er komponenten — og brukeropplevelsen — den samme. ### Ulemper[​](#ulemper "Direct link to Ulemper") * [SSR](/docs/ordbok.md#SSR): `customElements.define()` er en nettleser-API som ikke finnes i Node.js. Vi har testet SSR i de tilfellene vi har prøvd, og det har fungert godt — men vi har ikke verifisert alle rammeverk (Next.js o.l.) uttømmende * Team Designsystem må beherske Web Components-standarden ([Custom Elements API]()) — i praksis en liten kostnad, siden komponentene vi skriver er forholdsvis enkle og konsumenter merker lite (de bruker React-wrapperen eller ren HTML) * Konsumenter er selv ansvarlige for å laste `indeks-web` én gang — dette forhindrer kollisjoner ved registrering av custom elements ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * Etablere klare mønstre for Web Components-utvikling tidlig * SSR-støtte må kartlegges per komponent — dette er et åpent spørsmål som vil bli adressert når aktuelle komponenter nærmer seg produksjon ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### Kun React-komponenter[​](#kun-react-komponenter "Direct link to Kun React-komponenter") Fortsette med React-only komponenter for all logikk. **Forkastet fordi:** Begrenser gjenbruk til React-prosjekter. Vi skal støtte team som bruker andre teknologier enn React, og disse teamene ville vært utestengt fra de mest komplekse komponentene. ### Lit[​](#lit "Direct link to Lit") Et lett bibliotek fra Google for å skrive Web Components med deklarativ template-syntaks og reaktivitetssystem. Brukes av blant andre Adobe (Spectrum), SAP og ING. **Forkastet fordi:** Vi ønsker å holde `indeks-web` fri for eksterne bibliotek- og rammeverk-avhengigheter. Lits verdi ligger i deklarativ templating og reaktiv rendering *inne i* komponenten — noe vi ikke trenger, fordi vi ikke bruker Shadow DOM. Våre Web Components er tynne wrappere som manipulerer lys-DOM direkte, så native Custom Elements er håndterbart for komponentene vi faktisk skriver. Vi ser også til [designsystemet.no](https://designsystemet.no) som gjør det samme med native Web Components — det gir oss mulighet til å lære av og bygge videre på deres erfaringer. ### Stencil.js (Ionic)[​](#stenciljs-ionic "Direct link to Stencil.js (Ionic)") Et kompilatorbasert rammeverk for Web Components med TypeScript-first API, JSX-syntaks og innebygd støtte for å generere React- og Vue-wrappers automatisk. **Forkastet fordi:** Introduserer et kompilatorlag og en egen komponentmodell som gjør koden avhengig av Stencil — native Custom Elements er håndterbart uten dette. Automatisk wrapper-generering er en fordel vi ikke trenger siden vi uansett skriver React-wrapperen manuelt. ### FAST (Microsoft)[​](#fast-microsoft "Direct link to FAST (Microsoft)") Et bibliotek fra Microsoft for å bygge Web Components, brukt som fundament for Fluent UI Web Components. **Forkastet fordi:** Samme begrunnelse som Lit — vi ønsker å holde `indeks-web` fri for eksterne avhengigheter. FAST introduserer i tillegg en egen komponentmodell og attributt-system som binder komponentene tettere til biblioteket enn native Custom Elements. ### Multi-framework med delt TypeScript-kjerne[​](#multi-framework-med-delt-typescript-kjerne "Direct link to Multi-framework med delt TypeScript-kjerne") Dele forretningslogikk i et rammeverk-agnostisk TypeScript-bibliotek, og skrive rammeverk-spesifikke wrappers for React, Vue og Angular. **Forkastet fordi:** Kompleks build-pipeline med mange wrappers å vedlikeholde. Fortsatt rammeverk-spesifikk kode i alle wrappers. Web Components løser det samme med én implementasjon. ### Mitosis (Builder.io)[​](#mitosis-builderio "Direct link to Mitosis (Builder.io)") Et verktøy som kompilerer én komponentdefinisjon til React, Vue, Angular og Web Components. **Forkastet fordi:** Umodent verktøy med begrenset adopsjon. Abstraksjonslaget over komponentdefinisjonene gjør feilsøking vanskeligere, og output-koden er ikke idiomatisk i noe av målrammeverket. Deltakere Utarbeidet avTeam Designsystem --- # ADR-DS-005: React-bibliotek (Vite, ESM, React 18/19) StatusBesluttet ## Beslutning[​](#beslutning "Direct link to Beslutning") React-biblioteket bygges med **[Vite](/docs/ordbok.md#Vite)** i library mode, distribueres som **[ESM](/docs/ordbok.md#ESM)-only**, og støtter **React 18 og 19** som [peer dependency](). ### Vite[​](#vite "Direct link to Vite") Library mode med `vite-plugin-dts` for TypeScript declarations. React defineres som external (peer dependency) — ikke bundlet inn i biblioteket. God integrasjon med [Storybook](/docs/ordbok.md#Storybook). ### ESM-only[​](#esm-only "Direct link to ESM-only") `"type": "module"` i package.json. Ingen CJS-build. Build-target holdes synkronisert manuelt med `.browserslistrc` (via `vite.shared.ts` — se [ADR-DS-001](/docs/adr/ADR-DS-001-monorepo-og-byggverktoy.md) og nettleserstøtte-baselinen), for å støtte nettlesere tilbake til Safari/iOS 15.4. Optimal [tree-shaking](/docs/ordbok.md#tree-shaking) slik at konsumenter bare betaler for det de bruker. ### React 18 og 19[​](#react-18-og-19 "Direct link to React 18 og 19") Peer dependency `"react": "^18.0.0 || ^19.0.0"` (samme for `react-dom`) — støtter både React 18 og 19. Det senker terskelen for konsumenter som fortsatt er på React 18, samtidig som React 19 anbefales. Vi holder oss til API-er som finnes i begge for å unngå å utestenge React 18-konsumenter. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Rask build og hot-reload for god utvikleropplevelse * ESM er moderne JavaScript-standard og støtter optimal tree-shaking * Bred React-støtte (18 og 19) senker adopsjonsterskelen for early adopters ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") Komponentbiblioteket trenger en bundler, et distribusjonsformat og en strategi for React-versjonsstøtte. ESM (ES Modules) er nå native i alle moderne nettlesere og Node.js-versjoner. React 19 ble sluppet i desember 2024. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvilken bundler, distribusjonsformat og React-versjonsstrategi gir best utvikleropplevelse, optimal tree-shaking og langsiktig holdbarhet for komponentbiblioteket? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Konsumenter med eldre CJS-prosjekter må ta i bruk bundler. Konsumenter på React 18 og 19 kan bruke biblioteket direkte. ### Ulemper[​](#ulemper "Direct link to Ulemper") * Inkompatibel med eldre CJS-prosjekter som ikke bruker bundler * Å støtte både React 18 og 19 begrenser oss til API-er som finnes i begge versjonene * Vite er en abstraksjon over Rollup — feilsøking av edge cases i build kan kreve kunnskap om begge (ingen konkret mitigering, akseptert risiko) ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * De fleste moderne bundlere (webpack, Vite, Parcel) håndterer ESM uten konfigurasjon * React 19-spesifikke API-er brukes bare der de har en trygg fallback på React 18 ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### Rollup direkte[​](#rollup-direkte "Direct link to Rollup direkte") Vite bruker Rollup under panseret — bruke Rollup direkte gir full kontroll uten et abstraksjonslag. **Forkastet fordi:** Krever mer manuell konfigurasjon enn Vite, og vi mister Vites dev server og Storybook-integrasjon som brukes aktivt i utviklingsflyten. ### tsup / esbuild[​](#tsup--esbuild "Direct link to tsup / esbuild") Raskere bundlere enn Rollup/Vite, særlig for TypeScript-prosjekter. **Forkastet fordi:** Dårligere Storybook-integrasjon. Storybook er en sentral del av arbeidsflyten, og god integrasjon veier tyngre enn marginalt raskere build. ### Webpack[​](#webpack "Direct link to Webpack") Det mest utbredte build-verktøyet historisk sett. **Forkastet fordi:** Kompleks konfigurasjon og tregere enn Vite. Library mode er ikke Webpacks primære styrke. ### Dual CJS/ESM (begge formater)[​](#dual-cjsesm-begge-formater "Direct link to Dual CJS/ESM (begge formater)") Publisere både CommonJS og ES Module-versjoner for å støtte alle konsumenter. **Forkastet fordi:** Dobbel vedlikeholdsbyrde og økt pakke-størrelse. CJS er på vei ut av Node.js-økosystemet, og å vedlikeholde det forsinker avviklingen. ### Kun React 19 (`"react": "^19.0.0"`)[​](#kun-react-19-react-1900 "Direct link to kun-react-19-react-1900") Kun støtte React 19 og tvinge konsumenter på React 18 til å oppgradere. **Forkastet fordi:** Utestenger early adopters som fortsatt er på React 18 og gjør adopsjonsterskelen unødvendig høy. Kostnaden ved å holde seg til API-er som finnes i begge versjonene er lav sammenlignet med å låse ute konsumenter. React 19 anbefales fortsatt, men kreves ikke. Deltakere Utarbeidet avTeam Designsystem --- # ADR-DS-006: Design tokens StatusBesluttet ## Beslutning[​](#beslutning "Direct link to Beslutning") De fleste design tokens defineres som JSON i `indeks-tokens/tokens/` og er single source of truth for disse. Synkroniseres toveis med Figma med klare ansvarsgrenser. ### Token-struktur[​](#token-struktur "Direct link to Token-struktur") JSON-filer i `indeks-tokens/tokens/` (colors/, typography.json, border.json, breakpoints.json, z-index.json, transition.json, opacity.json, outline.json). Genererer [CSS custom properties]() (`--ix-*`), iOS Swift-verdier og Android XML. Fargesystemet er beskrevet i [ADR-DS-007](/docs/adr/ADR-DS-007-fargesystem.md). Spacing bor i CSS, ikke JSON Spacing er et bevisst unntak: `spacing.json` er en tom stubb, og spacing-tokenene defineres direkte som håndskrevet CSS i `indeks-utils/css/spacing.css` (faste px per breakpoint + density, se [ADR-DS-008](/docs/adr/ADR-DS-008-spacing-system.md)). Spacing-modellen (breakpoint-varianter × density-nivåer) er mer lesbar som CSS enn som generert JSON, og blir værende der. ### Figma-sync[​](#figma-sync "Direct link to Figma-sync") Synkroniseringen er toveis men med klare ansvarsgrenser: primitive verdier eies i kode og synkroniseres én vei til Figma. Semantisk mapping (f.eks. blue-600 → color-action) eies av designere i Figma og synkroniseres tilbake til kode via GitHub Actions workflow (`sync-figma-tokens.yml`). De to retningene er separate — det oppstår ikke konflikter mellom dem. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Konsistens på tvers av plattformer (web, iOS, Android) * Versjonskontroll av design-verdier — endringer er sporbare i git * Koden er fasit for primitive verdier — designere styrer [semantisk mapping]() * Theming — konsumenter som Spleis kan bytte ut primitive farger og få komplette fargeskalaer og semantiske tokens generert for sitt tema. Se [ADR-DS-007](/docs/adr/ADR-DS-007-fargesystem.md) for detaljer om fargesystemet ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") Et designsystem trenger konsistente verdier for farger, spacing, typografi og andre primitiver. Disse verdiene må brukes på flere plattformer (web, iOS, Android) og holdes synkronisert med Figma. Vi hadde ingen etablert kilde til sannhet for disse verdiene. Designere jobbet med farger i Figma, utviklere hardkodet verdier i CSS, og iOS- og Android-team hadde egne filer. Resultatet var drift mellom plattformene og manuelt arbeid hver gang noe skulle oppdateres. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvordan definerer og distribuerer vi [design tokens]() på en måte som sikrer konsistens på tvers av web, iOS og Android — og holder Figma og kode i sync — uten at det krever manuelt arbeid ved hver endring? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Designere bruker Figma-synkroniseringen og definerer semantisk mapping. Frontend-utviklere bruker CSS tokens direkte. Mobilutviklere får genererte outputs for iOS og Android. ### Ulemper[​](#ulemper "Direct link to Ulemper") Ingen identifiserte ulemper. Figma-sync kjøres manuelt og ad hoc — det er en bevisst prosess der endringer i primitiver vurderes før de synkroniseres til Figma. ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### Style Dictionary / Theo[​](#style-dictionary--theo "Direct link to Style Dictionary / Theo") Industristandard-verktøy (Adobe/Amazon) for å transformere design tokens til plattform-spesifikke outputs. Brukes av mange store designsystemer. **Forkastet fordi:** Gir mindre kontroll over output-formatet enn egne scripts, og løser ikke behovet for OKLCH-generering uten egne plugins uansett. ### CSS-variabler direkte (uten token-pipeline)[​](#css-variabler-direkte-uten-token-pipeline "Direct link to CSS-variabler direkte (uten token-pipeline)") Definere CSS custom properties manuelt i stilark, uten JSON-basert token-pipeline. **Forkastet fordi:** * Kan ikke generere outputs for iOS og Android * Ingen Figma-sync uten separat pipeline * Ingen versjonskontroll av selve verdiene som data ### Tokens Studio plugin[​](#tokens-studio-plugin "Direct link to Tokens Studio plugin") Figma-plugin som håndterer design tokens direkte i Figma og synkroniserer til kode. **Forkastet fordi:** Vanskelig å implementere OKLCH-generering, og gir designerne kontroll over primitive verdier — vi ønsker at primitiver eies i kode og at kun semantisk mapping styres fra Figma. ### Manuell eksport fra Figma[​](#manuell-eksport-fra-figma "Direct link to Manuell eksport fra Figma") Eksportere verdier manuelt fra Figma til CSS-filer ved behov. **Forkastet fordi:** Feilutsatt prosess uten versjonskontroll, og løser ikke behovet for plattform-spesifikke outputs. Deltakere Utarbeidet avTeam Designsystem --- # ADR-DS-007: Fargesystem StatusBesluttet ## Beslutning[​](#beslutning "Direct link to Beslutning") Fargeskalaer **genereres i [OKLCH](/docs/ordbok.md#OKLCH)** — et perseptuelt uniformt fargerom der lik lightness-verdi gir lik opplevd lysstyrke på tvers av fargetoner. Dette gjør det mulig å generere hele fargeskalaer fra én nøkkelfarge og få forutsigbare resultater. OKLCH er altså **genererings-/designrommet**. De **publiserte tokenene er hex-verdier** (`indeks-tokens/.build/css/themes/sb1.css`), ikke `oklch()`-funksjoner i runtime — den perseptuelle uniformiteten er en egenskap ved *hvordan* skalaene beregnes, og «fryses» ned til konkrete hex-verdier ved build. Konsumenter forholder seg til vanlige hex-farger. ### Skala-struktur[​](#skala-struktur "Direct link to Skala-struktur") Fargeskalaer er nummerert fra 0 til 950 (f.eks. blue-0 til blue-950). Fordi OKLCH er perseptuelt uniform gir dette designerne et forutsigbart system å jobbe med — man kan utlede hvilke kombinasjoner som fungerer visuelt og kontrastmessig uten å verifisere hvert par manuelt. Fargegenerering skjer ved build via scripts i `indeks-tokens/scripts/build-colors/`. Primitive fargeverdier defineres manuelt i JSON og er input til genereringen. ### Semantisk mapping og dark mode[​](#semantisk-mapping-og-dark-mode "Direct link to Semantisk mapping og dark mode") Primitive fargeverdier mappes til semantiske tokens som brukes i kode. De semantiske tokenene er organisert etter bruksområde — `foreground` (tekst), `background`, `fill` (flater og knapper), `surface`, `border` — med varianter som `main`, `subtle` og `inverse`. Eksempel på mapping: | Semantisk token | Light mode | Dark mode | | ------------------------------- | ----------- | ----------- | | `color-fill-main-default` | `brand-550` | `brand-450` | | `color-foreground-main-default` | `gray-900` | `gray-0` | Dark mode fungerer ved at de semantiske tokenene peker på andre trinn i samme skala — ingen nye farger defineres, bare andre trinn. Fordi OKLCH-skalaen er perseptuelt uniform fungerer de samme trinnvalgene for alle fargetoner, og [theming](/docs/ordbok.md#theming) for nye konsumenter krever kun at primitive farger byttes ut. ### Merkevarefarger[​](#merkevarefarger "Direct link to Merkevarefarger") Eksisterende merkevarefarger er ikke eksakt representert i OKLCH-skalaene — fargene justeres noe for å passe inn i den perseptuelt uniforme strukturen. Tilpasning mot merkevare er et kontinuerlig arbeid som pågår i samarbeid med merkevareteamet. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Theming — konsumenter som Spleis kan definere egne nøkkelfarger og få komplette skalaer generert automatisk * Forutsigbare fargeskalaer gjør fargearbeid enklere for designere — man slipper å kalibrere hver fargetone manuelt * Kontrastgarantier for universell utforming kan utledes fra skala-trinnet alene * Konsistente skalaer på tvers av alle fargetoner ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") Indeks skal støtte theming — konsumenter som Spleis har behov for å kunne tilpasse farger til sin merkevare. For at theming skal være praktisk, må det holde å definere et fåtall nøkkelfarger som systemet så bruker til å generere fullstendige fargeskalaer automatisk. Tilnærmingen er inspirert av ok-css (Kredittbankens CSS-rammeverk) som tilrettelegger for nettopp dette, og ligner på måten [designsystemet.no](https://designsystemet.no) håndterer farger. Dette stiller krav til fargerommet: genererte skalaer må fungere på tvers av ulike fargetoner uten manuell justering for hver kombinasjon. Med [HSL](/docs/ordbok.md#HSL) er dette ikke tilfellet — blå og gul med identiske S/L-verdier oppleves som ulike lysheter, fordi HSL ikke er perseptuelt uniform. Det betyr at en skala generert fra én farge ikke nødvendigvis fungerer like godt for en annen. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvilket fargerom gir oss fargeskalaer som kan genereres fra en nøkkelfarge og fungere konsistent på tvers av fargetoner — uten manuell kalibrering per farge? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Designere som jobber med farger i Figma. Frontend-utviklere som bruker fargetokens i CSS. ### Ulemper[​](#ulemper "Direct link to Ulemper") * OKLCH gir ikke eksakt match med eksisterende merkevarefarger — fargene blir litt justert * Generering i OKLCH krever egne build-scripts (`indeks-tokens/scripts/build-colors/`) i stedet for et hyllevare-verktøy ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * Fargetilpasning mot merkevare er et kontinuerlig arbeid * Fordi publiserte tokens er hex, er nettleserstøtte ikke et problem — `oklch()` forekommer ikke i utsendt CSS, så det trengs ingen runtime-fallback ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### HSL[​](#hsl "Direct link to HSL") HSL er et utbredt fargerom og allerede godt kjent blant webutviklere. **Forkastet fordi:** HSL er ikke perseptuelt uniform — blå og gul med samme S/L-verdier oppleves som ulike lysheter. OKLCH løser dette eksplisitt og gir mer pålitelige kontrastgarantier. ### sRGB / hex-verdier direkte[​](#srgb--hex-verdier-direkte "Direct link to sRGB / hex-verdier direkte") Definere farger direkte som hex-koder uten et strukturert fargerom. **Forkastet fordi:** Gir ingen systematisk sammenheng mellom skala-trinn. Kontraster må verifiseres manuelt for hvert par. Deltakere Utarbeidet avTeam Designsystem Involvert * Kredittbanken * designsystemet.no --- # ADR-DS-008: Spacing-system (faste breakpoints + density) StatusBesluttet ## Beslutning[​](#beslutning "Direct link to Beslutning") Spacing bruker **faste px-verdier på tre mobile-first breakpoints** kombinert med et **[density-system](/docs/ordbok.md#density-system)** (Compact/Default/Comfortable). Typografi bruker en `rem`-basert geometrisk skala uten density. ### Faste spacing-steg per breakpoint[​](#faste-spacing-steg-per-breakpoint "Direct link to Faste spacing-steg per breakpoint") Spacing er faste px-verdier definert mobile-first på tre breakpoints: * **mobil** (base) * **tablet** (`min-width: 768px`) * **desktop** (`min-width: 1024px`) Trinnene `2xs`–`lg` er konstante på alle breakpoints; kun `xl`–`5xl` øker på større skjermer. Tokens eksponeres som `--ix-spacing-2xs` til `--ix-spacing-5xl`. Eksempel på Default: | Token | mobil | tablet (≥768px) | desktop (≥1024px) | | ------------------ | ----- | --------------- | ----------------- | | `--ix-spacing-md` | 16px | 16px | 16px | | `--ix-spacing-lg` | 24px | 24px | 24px | | `--ix-spacing-xl` | 32px | 40px | 48px | | `--ix-spacing-3xl` | 48px | 64px | 80px | ### Density[​](#density "Direct link to Density") Density styres med `data-density`-attributtet (`default`, `compact`, `comfortable`) på et container-element, og gir hvert nivå sitt eget sett med faste px-verdier. Compact er tettere enn Default, Comfortable er luftigere. Eksempel på `--ix-spacing-md` (mobil): | Compact | Default | Comfortable | | ------- | ------- | ----------- | | 12px | 16px | 24px | ### Typografi[​](#typografi "Direct link to Typografi") Fontstørrelser bruker en geometrisk skala med ratio 1.125, men basen er fast `1rem` og `rem`-basert — det betyr at brukeren kan endre fontstørrelse via nettleserinnstillinger og at typografien skalerer deretter. Trinnene er definert på `.ix-body` og eksponert som tokens (`--ix-font-size-xs` til `--ix-font-size-5xl`). Det finnes ingen density-nivåer og ingen breakpoint-variasjon for typografi. | Token | Verdi (base `1rem`) | | -------------------- | ------------------- | | `--ix-font-size-md` | \~16px (1rem) | | `--ix-font-size-3xl` | \~29px (1.125⁵ rem) | ### Kombinert[​](#kombinert "Direct link to Kombinert") Density settes én gang på et container-element (`data-density`) og arves av alle komponenter inni. ### Figma[​](#figma "Direct link to Figma") Designere setter skjermstørrelse på frame og density for bruksområdet, og ser de beregnede verdiene direkte. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Forutsigbar layout — faste verdier per breakpoint er enklere å resonnere om enn fluid skalering * Responsivitet uten at utviklere håndterer breakpoints manuelt (tokens bytter verdi automatisk) * Ulike bruksområder krever fundamentalt ulik spacing (density) * Spacing og fontstørrelse er bevisst uavhengige — brukeren kan endre font uten at layout brytes, i tråd med [WCAG](/docs/ordbok.md#WCAG) 1.4.4 ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") Designsystemet brukes av team med fundamentalt ulike behov: nettbank og bedriftsløsninger trenger informasjonstett layout, mens salgssider og markedsføring trenger luft og rom. I tillegg skal komponenter automatisk tilpasse seg skjermstørrelse uten at utviklere manuelt håndterer breakpoints. Et tradisjonelt 8px-grid løser ingen av disse problemene — det er ikke responsivt og gir ikke variasjon mellom bruksområder. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvordan definerer vi et spacing-system som håndterer automatisk responsivitet og støtter fundamentalt ulike tetthetsbehov på tvers av bruksområder? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Designere må forstå at verdiene ikke følger 8px-grid. Utviklere får automatisk responsivitet uten ekstra arbeid. ### Ulemper[​](#ulemper "Direct link to Ulemper") * Tre density-nivåer å forholde seg til (Compact, Default, Comfortable) * Verdiene følger ikke et strengt 8px-grid på alle trinn — bevisst, men uvant for designere med 8px-bakgrunn * Kun `xl`–`5xl` varierer per breakpoint; de mindre trinnene er konstante, noe som må kommuniseres slik at man ikke forventer at all spacing skalerer med skjermstørrelse ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * Dokumentasjon forklarer systemet og hvilke trinn som varierer per breakpoint * Figma-bibliotek gjør det enkelt å se faktiske verdier per skjermstørrelse og density ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### Fluid skalering med `clamp()`[​](#fluid-skalering-med-clamp "Direct link to fluid-skalering-med-clamp") Den opprinnelige implementasjonen: spacing og fontstørrelse skalerte flytende med viewport via `clamp()` og en `calc()`-basert base. **Forkastet fordi:** Ga mindre forutsigbar layout — samme token kunne ha «alle» mellomverdier avhengig av viewport-bredde, noe som gjorde det vanskeligere å resonnere om og verifisere design. Faste steg per breakpoint gir designere og utviklere konkrete verdier å forholde seg til. (Density-systemet ble beholdt.) ### Standard 8px-grid[​](#standard-8px-grid "Direct link to Standard 8px-grid") Det dominerende spacing-systemet i designbransjen. Alle verdier er multipler av 8px. **Forkastet fordi:** Løser ikke behovet for ulik tetthet mellom nettbank og salgssider (density). Vårt system er mobile-first per breakpoint og bruker density i stedet for et fast grid. ### Kun viewport units (vw/vh)[​](#kun-viewport-units-vwvh "Direct link to Kun viewport units (vw/vh)") Bruke viewport-relative enheter direkte for spacing. **Forkastet fordi:** Gir ingen kontroll over minimums- og maksimumsstørrelser. Skaper tilgjengelighetsproblemer — brukere som bruker zoom vil ikke få økt spacing som forventet. ### Faste steg uten density[​](#faste-steg-uten-density "Direct link to Faste steg uten density") Implementere faste breakpoint-verdier uten density-nivåer. **Forkastet fordi:** Nettbank og salgssider har fundamentalt ulike tetthetsbehov som ett enkelt sett verdier ikke dekker. ### Separate spacing-systemer per bruksområde[​](#separate-spacing-systemer-per-bruksområde "Direct link to Separate spacing-systemer per bruksområde") Ulike token-sett for nettbank, bedrift og markedsføring. **Forkastet fordi:** Vanskelig å vedlikeholde — endringer må gjøres på tvers av systemer. Mister konsistensen som gjør at produkter fra SpareBank 1 ser ut som én familie. Deltakere Utarbeidet avTeam Designsystem --- # ADR-DS-009: CSS-arkitektur StatusBesluttet ## Beslutning[​](#beslutning "Direct link to Beslutning") All styling bruker ren **HTML + CSS** med `ix-`-prefix på alle klasser og custom properties. ### Tokens som CSS custom properties[​](#tokens-som-css-custom-properties "Direct link to Tokens som CSS custom properties") `--ix-color-primary`, `--ix-spacing-md` etc. Alle tokenverdier er tilgjengelige direkte i CSS uten ekstra byggesteg for konsumenter. ### Utility-klasser[​](#utility-klasser "Direct link to Utility-klasser") Inspirert av ok-css (SpareBank 1s interne CSS-rammeverk), Tailwind og nettbanken: `ix-m-md`, `ix-flex`, `ix-gap-sm`. Dekker \~80% av behovene. For avanserte behov bruker man egne CSS-filer med design tokens. Responsive varianter følger mønsteret `ix-{breakpoint}-{klasse}`, f.eks. `ix-sm-flex` for flex fra 768px og oppover. Breakpoints: sm (768px), md (1024px), lg (1280px), xl (1600px). ### Nettleserstøtte[​](#nettleserstøtte "Direct link to Nettleserstøtte") [PostCSS](/docs/ordbok.md#PostCSS) med `postcss-preset-env` og `autoprefixer` håndterer moderne CSS-syntaks ned til nettleserne i `.browserslistrc`. CSS leveres ferdig kompilert i pakken — konsumenter trenger ikke kjøre PostCSS selv. ### CSS-struktur[​](#css-struktur "Direct link to CSS-struktur") `indeks-css/css/`: components/, icons/, layout/, surface/, typography/. ### Dark mode[​](#dark-mode "Direct link to Dark mode") Temaet styres med CSS-klasser på rotelementet: `ix-light-mode` og `ix-dark-mode` tvinger henholdsvis lyst og mørkt tema. Klassen `ix-regard-color-scheme-preference` følger brukerens OS-preferanse via `prefers-color-scheme`. Åpent spørsmål Vurder om `ix-regard-color-scheme-preference` bør beholdes eller fjernes. Det er ønskelig at konsumenter eksplisitt velger tema (`ix-light-mode` / `ix-dark-mode`) fremfor å arve OS-preferanse automatisk. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Langsiktig holdbarhet — CSS fungerer uavhengig av React-versjoner og JS-trender * Ingen runtime overhead — styling er statisk CSS * Rammeverk-agnostisk — fungerer med React, Vue, Angular og ren HTML * God caching og forutsigbar ytelse * Enkel debugging med standard devtools ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") Vi ønsker et designsystem som varer lenge uavhengig av JavaScript-trender, støtter eldre nettlesere basert på `.browserslistrc`, og er enkelt å ta i bruk uten kompleks tooling. Et designsystem bør fungere for alle konsumenter — ikke bare de som bruker React. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvilken styringstilnærming for styling sikrer at designsystemet er rammeverk-agnostisk, langsiktig holdbart og uten runtime-overhead? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Alle konsumenter av designsystemet — både React-konsumenter og team som kun bruker CSS. ### Ulemper[​](#ulemper "Direct link to Ulemper") * Ingen automatisk scoping — `ix-`-prefix er eneste beskyttelse mot navnekollisjoner * Ingen compile-time type checking av klassenavn * Utility-klasser dekker ikke alle behov (men dette er bevisst — 80/20-regelen) ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * `ix-`-prefix forhindrer navnekollisjoner i praksis * TypeScript-typer for komponent-props gir type safety der det er mulig ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### Tailwind CSS[​](#tailwind-css "Direct link to Tailwind CSS") Et utility-first CSS-rammeverk som genererer kun de klassene som er i bruk. Svært populært og brukes av mange designsystemer. **Forkastet fordi:** * Tailwind forutsetter at konsumenter bruker Tailwinds egen build-pipeline — et eksternt designsystem bør ikke kreve dette av sine konsumenter * Tailwinds klassemodell og vårt token-system er grunnleggende ulike paradigmer som er vanskelig å kombinere uten å tape fordelene med begge ### CSS-in-JS (styled-components, Emotion, vanilla-extract)[​](#css-in-js-styled-components-emotion-vanilla-extract "Direct link to CSS-in-JS (styled-components, Emotion, vanilla-extract)") Styling defineres i JavaScript/TypeScript, nær komponentkoden. **Forkastet fordi:** * Runtime overhead (styled-components/Emotion genererer CSS i nettleseren) * Binder designsystemet til React * Kompliserer SSR * Gjør CSS-only-bruk umulig ### CSS Modules[​](#css-modules "Direct link to CSS Modules") Modulbasert CSS der klassenavn scopet automatisk per komponent ved build. **Forkastet fordi:** Genererte hash-baserte klassenavn er vanskelig å debugge og umulige å dokumentere (klassenavnet `ix-button` er meningsfullt; `_button_a3f2c_1` er det ikke). Eksponerer ikke stabile klassenavn som konsumenter kan bruke direkte. ### Sass/Less[​](#sassless "Direct link to Sass/Less") CSS-preprocessorer med variabler, nesting og mixins. **Forkastet fordi:** Moderne CSS har nå de fleste features som motiverte Sass (custom properties, nesting, container queries). Et ekstra byggesteg gir kompleksitet uten tilsvarende verdi. Deltakere Utarbeidet avTeam Designsystem --- # ADR-DS-010: Komponentutvikling og testing StatusBesluttet ## Beslutning[​](#beslutning "Direct link to Beslutning") **[Storybook](/docs/ordbok.md#Storybook)** for isolert komponentutvikling og **[Docker](/docs/ordbok.md#Docker)-basert [Playwright](/docs/ordbok.md#Playwright)** for reproduserbare visuelle tester og accessibility-sjekk. ### Storybook[​](#storybook "Direct link to Storybook") Hver komponent har en `.stories.tsx`-fil ved siden av implementasjonen. Port 6006 i utvikling. Addons: a11y og docs. Custom preview med theme switching og device context. Publiseres til design.sparebank1.no/storybook. ### Playwright i Docker[​](#playwright-i-docker "Direct link to Playwright i Docker") Base image `mcr.microsoft.com/playwright` (SHA-pinnet i `indeks-storybook/Dockerfile`). Testene kjører mot den statisk bygde Storybooken (`storybook-static`) servert på port 9009 — en egen port slik at Storybook-dev-serveren kan kjøre på port 6006 samtidig. Docker Compose orkestrerer services. Accessibility-testing via [axe-core](/docs/ordbok.md#axe-core) kjøres eksplisitt mot [WCAG](/docs/ordbok.md#WCAG) 2.2 A og AA (`wcag2a`, `wcag2aa`, `wcag22aa`) — se `indeks-storybook/tests/scanAll.dtest.ts`. Violations blokkerer merge. Unntak kan legges til per komponent, men må dokumenteres i komponentens kode. Visuelle tester vurderes som del av PR-review. For nye komponenter godkjenner designer implementasjonen før baseline-screenshots settes. Ved feil lastes Playwright-rapporten ned som CI-artefakt for å se hvilke skjermbilder som avviker. Kommandoer (fra `indeks-storybook`): `pnpm test:playwright` for tester, `pnpm update-snapshots` for å oppdatere baseline-screenshots. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Isolert utvikling — komponenter utvikles og demonstreres uten full app-kontekst * Reproduserbare screenshots uavhengig av utviklerens OS * Accessibility-testing (WCAG 2.2 A/AA) integrert i PR-flyten — violations blokkerer merge * Industri-standard verktøy som utviklere kjenner fra før ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") UI-komponenter trenger et isolert utviklingsmiljø der man kan se og interagere med komponenter uten å kjøre hele appen. I tillegg trenger vi visuelle regresjonstester som fanger uønskede endringer i utseende. Problemet med visuelle tester er at screenshots varierer mellom operativsystemer — fonter rendres ulikt på macOS og Linux, og anti-aliasing varierer. Dette betyr at en test som passerer lokalt kan feile i CI, og omvendt. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvordan sikrer vi reproduserbare visuelle regresjonstester på tvers av operativsystemer, og et godt isolert utviklingsmiljø for UI-komponenter? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Utviklere som jobber med React-komponenter bruker Storybook daglig og trenger Docker for visuelle tester. ### Ulemper[​](#ulemper "Direct link to Ulemper") * Docker kreves for visuelle tester — ikke alle har det installert * Tregere enn å kjøre Playwright native, grunnet Docker-overhead * Store Docker-image-størrelser * Storybook-versjoner må holdes oppdatert ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * Docker Compose gjør det enkelt å kjøre tester med én kommando * Storybook-oppgraderinger inngår i løpende vedlikehold ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### Chromatic / Percy[​](#chromatic--percy "Direct link to Chromatic / Percy") Skybaserte tjenester for visuell regresjonstesting som tar seg av screenshot-infrastrukturen. **Forkastet fordi:** * Ekstern tjeneste med kostnad per screenshot * Mindre kontroll over testmiljøet og data * Avhengighet av tredjepart for en kritisk del av CI-flyten ### Native Playwright (uten Docker)[​](#native-playwright-uten-docker "Direct link to Native Playwright (uten Docker)") Kjøre Playwright direkte på utviklerens maskin og i CI uten containerisering. **Forkastet fordi:** Screenshots er ikke reproduserbare på tvers av macOS, Windows og Linux. En baseline tatt på macOS vil feile i CI som kjører på Linux, og omvendt. ### Cypress[​](#cypress "Direct link to Cypress") Et E2E-testverktøy med god utvikleropplevelse og interaktiv testrunner. **Forkastet fordi:** Dårligere ytelse og mer begrenset multi-browser-støtte enn Playwright. Cypress er primært rettet mot E2E-tester, ikke komponenttesting og screenshot-sammenligning. ### Ladle / Histoire[​](#ladle--histoire "Direct link to Ladle / Histoire") Lettere alternativer til Storybook med raskere oppstartstid. **Forkastet fordi:** Mindre modne og med færre addons. a11y-integrasjon og Playwright-kobling er veldokumentert for Storybook, men ikke disse alternativene. Risikoen for å velge et verktøy som ikke er bredt adoptert er høy. Deltakere Utarbeidet avTeam Designsystem --- # ADR-DS-011: Dokumentasjon (Docusaurus, midlertidig) StatusBesluttet ## Beslutning[​](#beslutning "Direct link to Beslutning") **[Docusaurus](/docs/ordbok.md#Docusaurus) 3** brukes som midlertidig dokumentasjonsplattform med fokus på portabelt innhold. ### Docusaurus 3[​](#docusaurus-3 "Direct link to Docusaurus 3") Markdown-basert, minimal konfigurasjon, raskt å komme i gang. Hostet på Azure Static Web Apps (design.sparebank1.no). Norsk som standard. [MDX](/docs/ordbok.md#MDX) for interaktive eksempler med live React-komponenter. Vedlikeholdes av Team Designsystem. ### Struktur[​](#struktur "Direct link to Struktur") grunnleggende/, kom-i-gang/, komponenter/, monstre-og-maler/, retningslinjer/ (og adr/) ### Migreringsstrategi[​](#migreringsstrategi "Direct link to Migreringsstrategi") Markdown-innhold er portabelt og kan mappes til CMS-felter. Custom MDX-komponenter (som `AdrStatusLogg`, `AdrDeltakere`) må reimplementeres på ny plattform, men logikken er enkel og gjenbrukbar. Informasjonsarkitektur-erfaringer er plattformuavhengige. Migrering initieres når CMS-avklaringer med merkevare og redaktørene er på plass. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Raskt behov for dokumentasjon — kan ikke vente på CMS-avklaringer * Lavt risiko — Docusaurus er enkelt å bytte ut når riktig løsning er klar * Portabelt markdown-innhold — investering i innhold og IA er ikke tapt (custom komponenter må reimplementeres, men er enkle) * Mulighet for å teste og justere informasjonsarkitektur med ekte brukere ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") Vi trenger dokumentasjon nå for å komme i gang, teste informasjonsarkitektur og få feedback fra konsumenter. På sikt ønsker vi en egen løsning med CMS-integrasjon og tilpasset design, men det krever avklaringer med merkevare og redaktørene — og utviklingstid vi ikke har nå. Valget her er bevisst midlertidig. Målet er å komme i gang raskt uten å binde oss til en løsning vi ikke kan bytte ut. ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Hvilken dokumentasjonsplattform lar oss komme raskt i gang og teste informasjonsarkitektur, uten å låse oss til en løsning vi ikke kan bytte ut? ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Alle som leser eller bidrar til dokumentasjonen. Ikke-tekniske bidragsytere møter git-workflow i stedet for [CMS](/docs/ordbok.md#CMS). ### Ulemper[​](#ulemper "Direct link to Ulemper") * Midlertidig — vi vil ikke investere i dype Docusaurus-tilpasninger * Ingen CMS — ikke-tekniske bidragsytere må gjennom git-workflow * React-låst (Docusaurus er React-basert) * Noe dobbeltarbeid når vi migrerer til permanent løsning * Dokumentasjonen dekker bare siste versjon av designsystemet — eldre versjoner er ikke tilgjengelige ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * Begrenser Docusaurus-spesifikke tilpasninger * Fokus på portabelt markdown-innhold fra dag én ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") ### Vente på egen løsning[​](#vente-på-egen-løsning "Direct link to Vente på egen løsning") Ikke publisere dokumentasjon før en permanent, tilpasset løsning er klar. **Forkastet fordi:** For lang tid uten dokumentasjon. Konsumenter trenger veiledning, og vi trenger feedback for å forbedre designsystemet. ### VitePress[​](#vitepress "Direct link to VitePress") Et statisk nettstedsrammeverk bygget på Vite og Vue, primært for dokumentasjon. **Forkastet fordi:** Vue-basert, noe som gjør det vanskelig å vise live React-komponenter i dokumentasjonen. Innholdet er portabelt, men den tekniske tilnærmingen passer dårligere med en React-basert komponentleveranse. ### Storybook Docs[​](#storybook-docs "Direct link to Storybook Docs") Docusaurus-alternativ der Storybook er dokumentasjonsplattformen. **Forkastet fordi:** Storybook er primært en komponentworkshop, ikke et dokumentasjonsverktøy. Begrenset til komponentdokumentasjon — tokens, veiledere og konsepter passer dårlig inn. ### Notion / Confluence[​](#notion--confluence "Direct link to Notion / Confluence") Veletablerte CMS-verktøy som mange i SpareBank 1 allerede bruker. **Forkastet fordi:** Ikke integrert med kode — eksempler og token-verdier må oppdateres manuelt. Vanskelig å holde synkronisert med kodebasen. ### Bygge eget fra start[​](#bygge-eget-fra-start "Direct link to Bygge eget fra start") Lage en tilpasset dokumentasjonssite med CMS-integrasjon og designet av merkevare. **Forkastet fordi:** Krever CMS-avklaringer og utviklingstid vi ikke har nå. Riktig valg på sikt, men feil prioritering akkurat nå. Deltakere Utarbeidet avTeam Designsystem --- # Kort fortalt Denne siden er snarveien. Vil du ha helheten på fem minutter — hvorfor vi bygger Indeks selv og hva vi faktisk har bestemt — så er det her. Detaljene, avveiningene og de forkastede alternativene ligger i de enkelte [ADR-ene](#de-store-valgene). ## Hvorfor et eget designsystem?[​](#hvorfor-et-eget-designsystem "Direct link to Hvorfor et eget designsystem?") Vi kunne tatt et ferdig bibliotek fra hylla. Vi lot være, av én grunn: **behovene våre passer ikke helt med det ferdige alternativene løser.** * **Vi må virke på gamle enheter.** Kundene våre bruker telefoner og nettlesere som er flere år gamle. De fleste moderne bibliotek forutsetter ferske nettlesere. Vi setter et bevisst gulv og håndhever det automatisk. * **Vi må virke overalt.** Nettsider, React-apper og hybrid-apper (webview i en mobilapp). Da kan vi ikke låse oss til ett rammeverk. * **Tilgjengelighet er ikke valgfritt.** Som bank har vi et lovkrav, men vi vil også faktisk at alle skal kunne bruke tjenestene våre. Det må være bygget inn fra bunnen, ikke limt på til slutt. * **Vi vil eie våre egne farger, avstander og mønstre.** SpareBank 1 har en visuell identitet. Et eget system lar oss uttrykke den presist, i stedet for å presse den inn i noen andres. * **Vi satser på ren web-teknologi der det er mulig.** Rammeverk kommer og går; nettleseren består. Ved å lene oss på det plattformen allerede kan, bygger vi noe som holder på lang sikt og ikke må skrives om hver gang moten skifter. ## De fem målene — og hvordan vi løser dem[​](#de-fem-målene--og-hvordan-vi-løser-dem "Direct link to De fem målene — og hvordan vi løser dem") Alt vi har bestemt kan spores tilbake til fem mål. ### 1. Mobil-først[​](#1-mobil-først "Direct link to 1. Mobil-først") Vi designer for den minste skjermen først og bygger oppover. Avstander og størrelser er faste, forutsigbare steg per skjermbredde — ikke noe som flyter ukontrollert. Berøringsflater er store nok til en tommel. → [ADR-DS-008 Spacing-system](/docs/adr/ADR-DS-008-spacing-system.md) ### 2. Virker overalt (hybrid-app-støtte)[​](#2-virker-overalt-hybrid-app-støtte "Direct link to 2. Virker overalt (hybrid-app-støtte)") Kjernen er **web components** — byggeklosser som fungerer i ren HTML, i React, og i en mobilapp uten å dra med seg et helt rammeverk. React-laget vårt er et tynt skall utenpå. Da slipper vi å vedlikeholde logikken to ganger. → [ADR-DS-004 Web components](/docs/adr/ADR-DS-004-web-components.md) · [ADR-DS-005 React-bibliotek](/docs/adr/ADR-DS-005-react-bibliotek.md) ### 3. Støtte for gamle enheter[​](#3-støtte-for-gamle-enheter "Direct link to 3. Støtte for gamle enheter") Vi har ett gulv for hvilke nettlesere vi støtter, og tre uavhengige verktøy passer på at vi ikke ved et uhell bruker noe som er for nytt. Bommer du, sier byggesteget fra — ikke kunden. ### 4. Tilgjengelighet (a11y)[​](#4-tilgjengelighet-a11y "Direct link to 4. Tilgjengelighet (a11y)") Dette er systemets sterkeste side. Hver komponent har et eget regnskap mot alle WCAG 2.2-kriteriene. Automatiske tester blokkerer sammenslåing hvis noe er utilgjengelig. Og ingen tekst er hardkodet — alt som vises eller leses opp kan settes på bokmål, nynorsk eller engelsk. → [ADR-DS-010 Komponentutvikling og testing](/docs/adr/ADR-DS-010-komponentutvikling-og-testing.md) ### 5. Egne behov[​](#5-egne-behov "Direct link to 5. Egne behov") Vi bruker **tokens** — navngitte verdier for farger, avstander og mer — som én felles kilde. Farger designes i et fargerom (OKLCH) som gir jevne, harmoniske skalaer. Og konsumenter kan trygt overstyre utseendet der de trenger det, uten å kjempe mot systemet. → [ADR-DS-006 Tokens og farger](/docs/adr/ADR-DS-006-tokens-og-farger.md) · [ADR-DS-007 Fargesystem](/docs/adr/ADR-DS-007-fargesystem.md) ## De store valgene[​](#de-store-valgene "Direct link to De store valgene") Resten av ADR-ene handler om hvordan vi jobber for at systemet skal holde over tid: * **Alt i ett repo** med felles byggverktøy — enklere å holde pakkene i takt. [ADR-DS-001](/docs/adr/ADR-DS-001-monorepo-og-byggverktoy.md) * **Versjonering og publisering** styres av changesets, med sporbar kobling mellom pakke og kildekode. [ADR-DS-002](/docs/adr/ADR-DS-002-versjonering-og-publisering.md) * **Ressurser serveres fra CDN**, slik at flere apper deler og cacher de samme filene i stedet for å laste dem på nytt hver for seg. [ADR-DS-002](/docs/adr/ADR-DS-002-versjonering-og-publisering.md) * **CI/CD** kjøres i GitHub Actions. [ADR-DS-003](/docs/adr/ADR-DS-003-ci-cd.md) * **Styling er ren CSS** — ingen runtime, virker uansett rammeverk. [ADR-DS-009](/docs/adr/ADR-DS-009-css-only-styling.md) * **Komponenter utvikles og testes** etter en fast oppskrift med visuelle tester og a11y-tester. [ADR-DS-010](/docs/adr/ADR-DS-010-komponentutvikling-og-testing.md) * **Dokumentasjon** bor sammen med koden. [ADR-DS-011](/docs/adr/ADR-DS-011-dokumentasjon.md) ## Vil du grave dypere?[​](#kilde "Direct link to Vil du grave dypere?") * Hver [ADR](/docs/adr/ADR-DS-001-monorepo-og-byggverktoy.md) forklarer bakgrunn, problemstilling, konsekvenser og hvilke alternativer vi forkastet. * [Retningslinjene](/docs/adr/retningslinjer.md) beskriver konvensjoner teamet er enige om (som ikke er arkitekturbeslutninger). --- # Retningslinjer for Indeks designsystem Disse retningslinjene er ikke arkitekturbeslutninger, men konvensjoner teamet har blitt enige om. ## Hvor en komponent bor[​](#hvor-en-komponent-bor "Direct link to Hvor en komponent bor") Indeks er en monorepo (se [ADR-DS-001](/docs/adr/ADR-DS-001-monorepo-og-byggverktoy.md)), og en komponent er ofte spredt over flere pakker etter ansvar: ``` indeks-css/css/components// # styling (.ix-) indeks-web/lib/components// # web component (hvis komponenten trenger logikk) indeks-react/lib/ui/ # tynn React-wrapper (components/, layout/, typography/, icons/) indeks-storybook/stories/ # .stories.tsx indeks-docs/docs/komponenter/.mdx # dokumentasjon ``` React-komponentene grupperes i `indeks-react/lib/ui/` etter kategori (`components/`, `layout/`, `typography/`, `icons/`). Delte React-hooks ligger i `indeks-react/lib/hooks/` og delte typer i `indeks-react/lib/types/`. ## Språkvalg i kode og dokumentasjon[​](#språkvalg-i-kode-og-dokumentasjon "Direct link to Språkvalg i kode og dokumentasjon") **Kode** skrives på engelsk: komponentnavn (`Button`, `Card`), props (`variant`, `size`), CSS-klasser (`.ix-button`), token-navn, variabelnavn. **Dokumentasjon** skrives på norsk: ADR-er, README, docs, kommentarer, commits, PR-beskrivelser, issues, code reviews. Engelske fagbegrep brukes i norsk tekst (props, tokens, hooks, components). Eksempel: *"Button-komponenten har en `variant`-prop som styrer utseendet."* ## AI-bruk og ansvar[​](#ai-bruk-og-ansvar "Direct link to AI-bruk og ansvar") Den som genererer innhold med AI er fullt ansvarlig for resultatet. AI er et verktøy, ikke en unnskyldning. * Alt AI-generert innhold skal gjennomgås og forstås før commit * Samme kvalitetskrav gjelder uavhengig av opphav * "AI skrev det" er ikke en gyldig forklaring på feil --- # ADR-DS-XXX: \[Beskrivende tittel] StatusUtkast ## Bakgrunn[​](#bakgrunn "Direct link to Bakgrunn") Beskriv konteksten en utenforstående trenger for å forstå beslutningsbehovet. Hva er situasjonen? Hvilke tidligere beslutninger eller oppgaver har utløst dette behovet? ## Problemstilling[​](#problemstilling "Direct link to Problemstilling") Den konkrete problemstillingen denne beslutningen skal svare på. Én eller to setninger. ## Beslutning[​](#beslutning "Direct link to Beslutning") Hva ble besluttet, konkret og tydelig. Bruk korte avsnitt per del av beslutningen, eller en bulletet liste hvis det er flere sidestilte punkter. Ved Utkast/Forslag: beskriv anbefalingen og mulige valg. ### Drivere for beslutningen[​](#drivere-for-beslutningen "Direct link to Drivere for beslutningen") * Driver 1: f.eks. kostnader, driftsmodell, prinsipp, kvalitetsegenskap, tid, begrensning * Driver 2 * Driver 3 ## Konsekvenser[​](#konsekvenser "Direct link to Konsekvenser") ### Hvem påvirkes?[​](#hvem-påvirkes "Direct link to Hvem påvirkes?") Scope for beslutningen og konsekvenser for ulike grupperinger. ### Ulemper[​](#ulemper "Direct link to Ulemper") Utfordringer som må løses, konsekvenser ved at man valgte bort andre løsninger. ### Tiltak mot ulemper[​](#tiltak-mot-ulemper "Direct link to Tiltak mot ulemper") * Konkret tiltak mot en spesifikk ulempe ## Forkastede alternativer[​](#forkastede-alternativer "Direct link to Forkastede alternativer") Hvert forkastet alternativ får sin egen seksjon. Beskriv alternativet kort (én setning for lesere som ikke kjenner det), og gi et konkret avvisningsargument. ### \[Navn på alternativ 1][​](#navn-på-alternativ-1 "Direct link to \[Navn på alternativ 1]") Kort beskrivelse av fordeler og ulemper. **Forkastet fordi:** Kjerneargumentet i én setning. ### \[Navn på alternativ 2][​](#navn-på-alternativ-2 "Direct link to \[Navn på alternativ 2]") ... Deltakere Utarbeidet avNavn, rolle --- # Native Indeks brukes i hybridapper der webinnhold vises i native-appens WebView. For brukeren skal web-innholdet oppleves som en naturlig del av den native appen. Denne siden samler hensyn og verktøy som er relevante når Indeks-komponenter brukes i en native kontekst. ## WebView-oppførsel[​](#webview-oppførsel "Direct link to WebView-oppførsel") Uten tilpasning vil WebView-innhold oppføre seg som en vanlig nettside: tekst kan markeres ved langt trykk, elementer kan dras, og trykk har en merkbar forsinkelse. Dette bryter med forventningene til en native app. Indeks tilbyr utility-klasser som gjør at webinnholdet oppfører seg som native UI — med mulighet for å slippe gjennom tekstmarkering der det trengs. Se [Native (utility-klasser)](/docs/utility-klasser/native.md) for fullstendig oversikt over klassene `.ix-native`, `.ix-selectable` og `.ix-selectable-all`. --- # Border Komponentene vi tilbyr har riktig border-radius og border-width som standard. Hvis du skal lage noe eget, kan du bruke border-variablene vi tilbyr. Bruk util-klassen `.ix-border-default` for å få standard border-stil, oftest brukt på kort. Klassen setter `--ix-border-width-default` og farge `--ix-color-border-main-default`. ## Border width[​](#border-width "Direct link to Border width") Vi har 2 forskjellige border-tykkelser. For fokus på skjemaelementer skal du bruke [outline](#outline). | CSS custom property | Verdi | Beskrivelse | | --------------------------- | ----- | ------------------------- | | `--ix-border-width-default` | 1px | Standard border-width. | | `--ix-border-width-bold` | 2px | Border-width for buttons. | ## Border radius[​](#border-radius "Direct link to Border radius") Vi har border radius i størrelsene xs, sm, md, lg og xl. Det er egne border radius for pilleformede elementer hvis man trenger det, samt checkbox, input og knapp. Bruk `ix-border-radius-circle` for helt runde elementer. | CSS custom property | Verdi | Beskrivelse | | ----------------------------- | ---------------------------- | --------------------------------------------------------- | | `--ix-border-radius-circle` | 50% | Fullt avrundet border-radius. | | `--ix-border-radius-pill` | 9999px | Border-radius for pille-formede elementer. Feks. knapper. | | `--ix-border-radius-checkbox` | 4px | Border-radius for avkrysningsbokser. | | `--ix-border-radius-input` | 8px | Border-radius for input-felt. | | `--ix-border-radius-button` | var(--ix-border-radius-pill) | Border-radius for knapper. | | `--ix-border-radius-xs` | 4px | Liten border-radius. | | `--ix-border-radius-sm` | 8px | Medium border-radius. Brukes til input-felt. | | `--ix-border-radius-md` | 16px | Stor border-radius. Brukes til kort. | | `--ix-border-radius-lg` | 24px | Ekstra stor border-radius. Brukes til modaler. | | `--ix-border-radius-xl` | 40px | Ekstra stor border-radius. | ## Outline[​](#outline "Direct link to Outline") Outline brukes ved fokus på skjemaelementer. Outline burde være satt til transparent når elementet ikke er i fokus for å unngå hopping i layouten.
Bruk `--ix-outline-default` for standard outline-stil, og legg til outline-offset med `--ix-outline-offset-default`. | CSS custom property | Verdi | Beskrivelse | | ---------------------------- | ----- | ------------------------ | | `--ix-outline-width-default` | 2px | Standard outline-bredde. | | CSS custom property | Verdi | Beskrivelse | | ----------------------------- | ----- | ------------------------ | | `--ix-outline-offset-default` | 3px | Standard outline-offset. | ## Farger[​](#farger "Direct link to Farger") Se [farger](/docs/retningslinjer/farger/.md#border) for å finne riktige farger til border og outline. --- # Farger for Native Pakken `@sb1/indeks-tokens` inneholder fargetokens som kan bygges til forskjellige plattformer, inkludert native (iOS og Android). For å bruke fargene i native-apper er det enkleste å bygge dem til den relevante plattformen ved hjelp av `build-colors`-kommandoen som følger med pakken. ## Hvordan bygge fargene[​](#hvordan-bygge-fargene "Direct link to Hvordan bygge fargene") Pakken `@sb1/indeks-tokens` eksponerer en `build-colors`-kommando som genererer fargetokens for den plattformen du velger. Du kan kjøre den med `npx` uten å installere pakken. Kommandoen har samme signatur uansett plattform — du styrer resultatet med `platform=`, `path=` og valgfritt `theme=`. Den samme generatoren brukes også for [web](/docs/grunnleggende/tokens/farger-web.md). Versjonering Vi anbefaler at dere commiter scriptet dere bruker for å bygge fargene, slik at dere har kontroll på når fargene endrer seg. Ved å ha dette committet blir det enklere å spore når fargene endrer seg og å vite hvilken versjon en er på. ## Android[​](#android "Direct link to Android") For å bygge farger til Android (Kotlin): ``` npx @sb1/indeks-tokens build-colors platform=android path=./android/colors ``` Dette genererer en `Colors.kt`-fil med semantiske farger for både light og dark mode. ### Output-eksempel[​](#output-eksempel "Direct link to Output-eksempel") ``` object Colors { object LightDefault { val backgroundDefault = Color(0xFFFFFFFF) val backgroundNeutral = Color(0xFFF4F5F6) // ... flere farger } object DarkDefault { val backgroundDefault = Color(0xFF1E2632) val backgroundNeutral = Color(0xFF323B49) // ... flere farger } } ``` ### Parametere[​](#parametere "Direct link to Parametere") * `platform=android` - Spesifiserer at du vil bygge for Android * `path=` - Hvor filene skal lagres (f.eks. `./android/colors`) * `theme=` - (Valgfri) Sti til egen theme-fil (default: `sb1`) ## iOS[​](#ios "Direct link to iOS") For å bygge farger til iOS (Xcode Color Assets): ``` npx @sb1/indeks-tokens build-colors platform=ios path=./ios/colors ``` Dette genererer en `.xcassets`-mappe med semantiske farger for både light og dark mode. ### Output-struktur[​](#output-struktur "Direct link to Output-struktur") ``` SemanticColors.xcassets/ ├── Contents.json ├── README.md └── default/ ├── Contents.json ├── background.default.colorset/ │ └── Contents.json ├── background.neutral.colorset/ │ └── Contents.json └── ... flere farger ``` ### Parametere[​](#parametere-1 "Direct link to Parametere") * `platform=ios` - Spesifiserer at du vil bygge for iOS * `path=` - Hvor filene skal lagres (f.eks. `./ios/colors`) * `theme=` - (Valgfri) Sti til egen theme-fil (default: `sb1`) ## Egne themes[​](#egne-themes "Direct link to Egne themes") Du kan lage ditt eget theme ved å opprette en JSON-fil med et theme-objekt. Generatoren vil da bruke dette themet i stedet for det innebygde sb1-themet. ### Eksempel på egen theme-fil[​](#eksempel-på-egen-theme-fil "Direct link to Eksempel på egen theme-fil") Lag en fil `my-theme.json`: ``` { "name": "my-custom-theme", "identityColor": "#005aa4", "colors": { "brand": "#0078D8", "success": "#00885B", "info": "#467CA4", "danger": "#C94E4F", "warning": "#AF6500", "gray": "#6D7888", "neutral": "#AF6516" }, "themeable": { "font-family": { "normal": "System", "heading": "System" }, "font-weight": { "normal": 400, "bold": 600, "heading": 700 }, "border": { "radius": { "button": 25, "checkbox": 4, "input": 8 } } } } ``` De sju basisfargene under `colors` er påkrevd. `identityColor` og `themeable` er valgfrie. ### Bruke eget theme[​](#bruke-eget-theme "Direct link to Bruke eget theme") ``` npx @sb1/indeks-tokens build-colors platform=android path=./android/colors theme=./my-theme.json ``` Eller for iOS: ``` npx @sb1/indeks-tokens build-colors platform=ios path=./ios/colors theme=./my-theme.json ``` ## Fargeskalaer[​](#fargeskalaer "Direct link to Fargeskalaer") Alle farger bygges fra fargeskalaer med 20 steg (0-950) for hver basisfarge: * **brand** - Merkevarefarge * **success** - Suksess/positiv * **info** - Informasjon * **warning** - Advarsel * **danger** - Feil/negativ * **gray** - Nøytral grå * **neutral** - Nøytral brun/beige De semantiske fargene (f.eks. `background.default`, `foreground.main`) er mappet til disse fargeskalaene og justeres automatisk for light og dark mode. Se [Fargeskalaer](/docs/grunnleggende/tokens/fargeskalaer.md) for hvordan skalaene genereres — og hvorfor det å justere mørkhetsgraden på en basisfarge ikke påvirker resultatet. ## Oppdatere farger[​](#oppdatere-farger "Direct link to Oppdatere farger") For å oppdatere fargene i native-appen din: 1. Oppdater versjonen av `@sb1/indeks-tokens` i kommandoen 2. Kjør build-scriptet på nytt 3. Commit de nye filene til versjonskontroll 4. De nye fargene vil være tilgjengelige i appen Dette sikrer at fargeendringer er sporbare og at teamet har kontroll over når oppdateringer skjer. --- # Farger for Web Pakken `@sb1/indeks-tokens` inneholder fargetokens som brukes i hele designsystemet. På web trenger de aller fleste ikke å generere farger selv — den ferdig bygde CSS-en inneholder alt du trenger. Men du kan generere din egen web-CSS med et eget theme ved hjelp av den samme `build-colors`-kommandoen som brukes for [native (iOS/Android)](/docs/grunnleggende/tokens/farger-native.md). ## Standard bruk: importer ferdig CSS[​](#standard-bruk-importer-ferdig-css "Direct link to Standard bruk: importer ferdig CSS") I de aller fleste tilfeller skal du **ikke** generere farger selv. Bruk den ferdig bygde CSS-en, som allerede inneholder alle fargetokens: ``` @import url('https://cdn.sparebank1.no/indeks/css//index.css'); ``` Eller via npm med `@sb1/indeks-css` (som inkluderer tokens): ``` npm install @sb1/indeks-css ``` Da får du alle `--ix-color-*`-variablene ferdig satt opp med både light og dark mode. Du trenger ikke resten av denne siden. ## Egen web-CSS fra eget theme[​](#egen-web-css-fra-eget-theme "Direct link to Egen web-CSS fra eget theme") Har du behov for et eget theme (egne merkevarefarger), kan du generere web-CSS med `build-colors`: ``` npx @sb1/indeks-tokens build-colors platform=web path=./css theme=./my-theme.json ``` Uten `theme=` genereres CSS-en med standard `sb1`-theme. ### Output[​](#output "Direct link to Output") Kommandoen skriver to slags filer til `path`: ``` css/ ├── colors.css └── themes/ └── .css ``` * **`themes/.css`** — primitivene (`--ii-primitive-*`), altså de fullstendige [fargeskalaene](/docs/grunnleggende/tokens/fargeskalaer.md) generert fra basisfargene i themet ditt. Merk at basisfargen kun styrer fargetone og metning — lysheten settes per trinn, så å gjøre en basisfarge lysere eller mørkere endrer ikke skalaen. * **`colors.css`** — de semantiske fargene (`--ix-color-*`), som peker inn i primitivene. Denne inneholder både light mode (`:root`, `.ix-light-mode`), dark mode (`.ix-dark-mode`) og `prefers-color-scheme`-håndtering. `--ii-` vs `--ix-` `--ii-primitive-*` er interne primitiver (implementasjonsdetalj) — ikke bruk dem direkte i applikasjonskoden din. `--ix-color-*` er det offentlige API-et du styler mot. ### Rekkefølge og overstyring[​](#rekkefølge-og-overstyring "Direct link to Rekkefølge og overstyring") Importér begge de genererte filene. **Rekkefølgen dem imellom spiller ingen rolle** — `--ix-color-*` refererer til `--ii-primitive-*` via `var()`, og CSS custom properties slås opp når de brukes, uavhengig av import-/deklarasjonsrekkefølge: ``` @import './css/themes/my-theme.css'; @import './css/colors.css'; ``` Bruker du både `@sb1/indeks-css` (for komponent-CSS) og ditt eget theme, er det derimot rekkefølgen mot indeks-css som avgjør. Den ferdige CSS-en inlirer de samme tokenene under nøyaktig samme selektorer og spesifisitet, og det finnes ingen `@layer` som skiller dem — så det er «sist vinner» som gjelder: ``` @import url('https://cdn.sparebank1.no/indeks/css//index.css'); @import './css/themes/my-theme.css'; @import './css/colors.css'; ``` Eget theme må lastes sist Ditt eget theme overstyrer bare indeks-css hvis det importeres **etter** indeks-css. Lastes det før — eller uten kontroll på rekkefølgen i bundleren — vinner indeks-css, og temaet får stille ingen effekt. ## Generere farger i runtime[​](#generere-farger-i-runtime "Direct link to Generere farger i runtime") Trenger du å endre farger **on-the-fly** — typisk å bytte `brand`-fargen basert på brukervalg eller merkevare — kan du generere fargeskalaer i runtime, både i nettleseren og i en Node-backend. Da bruker du subpath-eksporten `@sb1/indeks-tokens/generate`. Da blir `@sb1/indeks-tokens` en ekte avhengighet Ved standard bruk (ferdig CSS) trenger du bare `@sb1/indeks-css`. Men bruker du runtime-API-et, importerer applikasjonskoden din faktisk JavaScript fra `@sb1/indeks-tokens` — da må pakken ligge under `dependencies` (ikke `devDependencies`) i din `package.json`: ``` npm install @sb1/indeks-tokens ``` Fargematematikken (`colorjs.io`) er bundlet inn i eksporten, så du får ingen ekstra avhengigheter å forholde deg til. ### Slik henger det sammen[​](#slik-henger-det-sammen "Direct link to Slik henger det sammen") De semantiske fargetokenene (`--ix-color-*`) peker på primitivene via `var(--ii-primitive-*)`. For å rethem-e i runtime trenger du derfor **bare** å regenerere primitiv-skalaen for de(n) basisfargen(e) du vil endre og sette `--ii-primitive--` på et scope — alle de semantiske tokenene re-resolver seg selv via `var()`-kaskaden. Du skal **aldri** regenerere det semantiske laget selv. Eneste tillatte bruk av `--ii-` `--ii-primitive-*` er ellers interne (se over). Runtime-generering er det ene stedet der du bevisst setter dem. API-et eier navnekonvensjonen og `gray-0 = #FFFFFF`-unntaket for deg, så du slipper å hardkode dem. ### API[​](#api "Direct link to API") * **`buildColorScaleVariables(navn, farge)`** — bygger en 20-trinns skala fra én basisfarge og returnerer en ferdig CSS-variabel-map: `{ '--ii-primitive-brand-0': '#…', … }`. * **`applyColorScaleVariables(element, variabler)`** — setter map-en som inline-styling på et element (nettleser). * **`colorScaleVariablesToCss(variabler, { selector })`** — serialiserer map-en til en CSS-streng (Node-backend / injeksjon i ``). `selector` er valgfri, standard `:root`. De to hjelperne tar en variabel-map, så du kan slå sammen flere skalaer: `{ ...buildColorScaleVariables('brand', a), ...buildColorScaleVariables('info', b) }`. ### I nettleseren[​](#i-nettleseren "Direct link to I nettleseren") ``` import { buildColorScaleVariables, applyColorScaleVariables } from '@sb1/indeks-tokens/generate'; const vars = buildColorScaleVariables('brand', '#E4002B'); applyColorScaleVariables(document.documentElement, vars); // Alle --ix-color-* som bygger på brand oppdateres nå automatisk. ``` Vil du se det i praksis — skriv inn en basisfarge og se hele appen rethem-e seg live: **[Prøv fargegenerering i eksempelappen →](https://design.sparebank1.no/eksempel/#/internTesting/generer-farger)** ### I en Node-backend[​](#i-en-node-backend "Direct link to I en Node-backend") Generér en CSS-streng du kan sende til klienten (f.eks. injisert i ``): ``` import { buildColorScaleVariables, colorScaleVariablesToCss } from '@sb1/indeks-tokens/generate'; const vars = buildColorScaleVariables('brand', '#E4002B'); const css = colorScaleVariablesToCss(vars); // ':root {\n --ii-primitive-brand-0: #…;\n … \n}' // Vil du scope temaet til et delområde i stedet for hele siden: const scoped = colorScaleVariablesToCss(vars, { selector: '.min-merkevare' }); ``` Se [Fargeskalaer](/docs/grunnleggende/tokens/fargeskalaer.md) for hva basisfargen faktisk styrer (fargetone og metning — ikke lyshet). ## Eksempel på egen theme-fil[​](#eksempel-på-egen-theme-fil "Direct link to Eksempel på egen theme-fil") Theme-fila er en JSON-fil med de sju basisfargene. `identityColor` og `themeable` (font, border-radius) er valgfrie. Lag en fil `my-theme.json`: ``` { "name": "my-custom-theme", "identityColor": "#005aa4", "colors": { "brand": "#0078D8", "success": "#00885B", "info": "#467CA4", "danger": "#C94E4F", "warning": "#AF6500", "gray": "#6D7888", "neutral": "#AF6516" }, "themeable": { "font-family": { "normal": "Inter, sans-serif", "heading": "Inter, sans-serif" } } } ``` Filnavnet på theme-CSS-en følger `name`-feltet i JSON-fila — themet over gir `css/themes/my-custom-theme.css`. ## Parametere[​](#parametere "Direct link to Parametere") * `platform=web` — spesifiserer at du vil bygge web-CSS * `path=` — hvor filene skal lagres (f.eks. `./css`) * `theme=` — (valgfri) sti til egen JSON-theme-fil (default: `sb1`) Den samme kommandoen bygger også farger for iOS og Android — se [Farger for Native](/docs/grunnleggende/tokens/farger-native.md). --- # Fargeskalaer Et theme defineres med sju **basisfarger** — `brand`, `success`, `info`, `danger`, `warning`, `gray` og `neutral`. Ved build utvides hver av disse til en **20-trinns fargeskala** (0–950), som blir til primitivene (`--ii-primitive-*`) de semantiske fargene peker på. Skalaene genereres i [OKLCH](/docs/ordbok.md#OKLCH), et [perseptuelt uniform]()t fargerom. Det betyr at samme trinn gir samme opplevde lysstyrke på tvers av fargetoner, slik at de semantiske mappingene (hvilke trinn som brukes til tekst, bakgrunn osv.) fungerer likt for alle basisfarger. ## Hva basisfargen faktisk styrer[​](#hva-basisfargen-faktisk-styrer "Direct link to Hva basisfargen faktisk styrer") Generatoren bruker **ikke** basisfargen som den er og lysner/mørkner rundt den. Den konverterer basisfargen til OKLCH og bruker bare deler av den: * **Fargetone (hue)** — beholdes uendret gjennom hele skalaen. * **Metning (chroma)** — brukes fra basisfargen, men skaleres langs en fast kurve som er lav i endene og høyest på midten av skalaen. * **Lyshet (lightness)** — **overstyres** med en fast verdi per trinn (fra \~0.99 på trinn 0 til \~0.17 på trinn 950). Basisfargens egen lyshet brukes ikke. Å justere mørkhetsgraden på en basisfarge har ingen effekt Fordi lysheten settes per trinn, endrer det **ikke** skalaen om du gjør basisfargen lysere eller mørkere — to hex-verdier med samme fargetone og metning, men ulik lyshet, gir nøyaktig samme skala. Trenger du en lysere eller mørkere farge i grensesnittet, velg et **annet trinn** på skalaen. Endre selve basis-hexen kun når du vil endre **fargetone eller metning**. Ett unntak: `gray-0` tvinges alltid til `#FFFFFF`, uavhengig av `gray`-basisfargen. ## Se skalaene[​](#se-skalaene "Direct link to Se skalaene") Alle sju skalaene med alle 20 trinn vises i eksempelappen — trinn 600 er markert som nøkkelfargen: **[Fargeskalaer i eksempelappen →](https://design.sparebank1.no/eksempel/#/internTesting/fargeskalaer-eksempler)** ## Mer om beslutningen[​](#mer-om-beslutningen "Direct link to Mer om beslutningen") Bakgrunnen for valget av OKLCH — hvorfor HSL ble forkastet, hvorfor de publiserte tokenene er frosne hex-verdier (ikke `oklch()` i runtime), og hvordan dark mode bruker andre trinn i samme skala — er dokumentert i [ADR-DS-007: Fargesystem](/docs/adr/ADR-DS-007-fargesystem.md). --- # Introduksjon Design tokens er de minste byggesteinene i designsystemet. De representerer visuelle verdier som farger, typografi, spacing, radius og skygger osv. definert som navngitte variabler i stedet for faste verdier. Ved å bruke tokens samler vi visuelle verdier på ett sted. Når en verdi endres, oppdateres den automatisk der tokenet er i bruk, uten behov for manuelle justeringer i hver enkelt komponent eller flate. Dette gjør designsystemet enklere å vedlikeholde, mindre sårbart for feil og mer robust over tid. I stedet for å bruke konkrete verdier som 16px eller #002776, bruker vi tokens som for eksempel `ix-spacing-sm` eller `ix-color-foreground-main-default`. Dette gjør det mulig å skape konsistens på tvers av design og kode, og gjør endringer enklere å håndtere over tid. ## Hvorfor bruke tokens?[​](#hvorfor-bruke-tokens "Direct link to Hvorfor bruke tokens?") ### Konsistens[​](#konsistens "Direct link to Konsistens") Samme verdier brukes på tvers av komponenter, flater og team. ### Skalerbarhet[​](#skalerbarhet "Direct link to Skalerbarhet") Endringer kan gjøres ett sted og slår gjennom overalt. ### Felles språk[​](#felles-språk "Direct link to Felles språk") Tokens fungerer som et felles språk mellom designere og utviklere. ### Tilpasning[​](#tilpasning "Direct link to Tilpasning") Gjør det mulig å støtte flere temaer, moduser eller merkevarer (f.eks. light/dark eller accent). ## Tokens i praksis[​](#tokens-i-praksis "Direct link to Tokens i praksis") * I Figma brukes tokens for å sikre at design følger systemets regler * I kode eksponeres de som variabler (CSS, JSON, etc.) * I komponenter brukes kun semantiske eller kontekstuelle tokens – aldri rå verdier --- # Spacing Spacing-systemet i Indeks sikrer konsistente avstander mellom elementer på tvers av flater. Systemet bruker faste px-verdier som justeres på tre breakpoints, og kan tilpasses behov for mer eller mindre kompakt visning. ## Breakpoints[​](#breakpoints "Direct link to Breakpoints") Spacing er **mobile-first** og bruker tre breakpoints: * **Mobil**: grunnverdi (opptil 768px) * **Tablet**: fra `768px` * **Desktop**: fra `1024px` De minste verdiene (`2xs`–`lg`) er like på alle breakpoints. Kun de store verdiene (`xl`–`5xl`) øker på tablet og desktop, slik at layouten får mer luft på større skjermer uten at små detaljavstander endrer seg. Fontstørrelser er faste og skalerer **ikke** med skjermbredden — grunnstørrelsen er alltid 16px (`1rem`). Spacing er definert i `px`, mens typografi bruker `rem`. ## Density-moduser[​](#density-moduser "Direct link to Density-moduser") Spacing-systemet i Indeks kan justeres basert på hvor kompakt eller romslig (desinsity) en flate skal være. Dette gjør det mulig å vise mer eller mindre innhold på samme flate, uten å gå på bekostning av lesbarhet. Indeks støtter tre ulike moduser som påvirker alle spacing-verdier. * **Default**: Standard visning med balanserte spacing-verdier som gir god lesbarhet og tydelig struktur. Dette er anbefalt valg for de fleste flater og brukstilfeller. * **Compact**: Kompakt visning med reduserte spacing-verdier. Er godt egnet for flater med behov for høy informasjonstetthet, som for eksempel rådgiverflater og andre interne systemer. Et kompakt område kan settes ved bruk av attributtet `data-density="compact"`. * **Comfortable**: Komfortabel visning med økte spacing-verdier som gir et mer romslig uttrykk. Egner seg godt for åpne nettsider, salgskanaler og kampanjer, der innholdet skal få mer luft og oppmerksomhet. Et komfortabelt område kan settes ved bruk av attributtet `data-density="comfortable"`. ```
...
...
...
``` ## Spacing-skala[​](#spacing-skala "Direct link to Spacing-skala") Spacing-tokens følger en konsistent skala fra `2xs` til `5xl`, med faste px-verdier. `2xs`–`lg` er like på alle breakpoints; kun `xl`–`5xl` øker på tablet og desktop. ### Mobil (grunnverdi)[​](#mobil-grunnverdi "Direct link to Mobil (grunnverdi)") | Token | Beskrivelse | Default | Compact | Comfortable | | ----- | -------------- | ------- | ------- | ----------- | | `2xs` | Ekstra liten | 4px | 2px | 8px | | `xs` | Liten | 8px | 4px | 12px | | `sm` | Small | 12px | 8px | 16px | | `md` | Medium | 16px | 12px | 24px | | `lg` | Large | 24px | 16px | 32px | | `xl` | Extra large | 32px | 24px | 40px | | `2xl` | 2x extra large | 40px | 32px | 48px | | `3xl` | 3x extra large | 48px | 40px | 64px | | `4xl` | 4x extra large | 64px | 48px | 80px | | `5xl` | 5x extra large | 80px | 64px | 96px | ### Tablet (fra 768px)[​](#tablet-fra-768px "Direct link to Tablet (fra 768px)") | Token | Default | Compact | Comfortable | | ----- | ------- | ------- | ----------- | | `xl` | 40px | 32px | 48px | | `2xl` | 48px | 40px | 64px | | `3xl` | 64px | 48px | 80px | | `4xl` | 80px | 64px | 96px | | `5xl` | 96px | 80px | 128px | ### Desktop (fra 1024px)[​](#desktop-fra-1024px "Direct link to Desktop (fra 1024px)") | Token | Default | Compact | Comfortable | | ----- | ------- | ------- | ----------- | | `xl` | 48px | 32px | 64px | | `2xl` | 64px | 40px | 80px | | `3xl` | 80px | 48px | 96px | | `4xl` | 96px | 64px | 128px | | `5xl` | 128px | 80px | 128px | *`Compact` har samme verdier på tablet og desktop.* ## Bruk[​](#bruk "Direct link to Bruk") ### Utility-klasser[​](#utility-klasser "Direct link to Utility-klasser") Full oversikt over utility-klassene finner du [i oversikten over utility-klasser](/docs/utility-klasser/oversikt.md#spacing). ### CSS Custom Properties[​](#css-custom-properties "Direct link to CSS Custom Properties") Spacing finnes også i variabler: `--ix-spacing-{size}`. Variablene skiller ikke mellom padding, margin eller gap. ``` .min-komponent { padding: var(--ix-spacing-md); margin-bottom: var(--ix-spacing-lg); gap: (var--ix-spacing-md); } ``` ## Migreringsguider[​](#migreringsguider "Direct link to Migreringsguider") ### Migrere fra FFE[​](#migrere-fra-ffe "Direct link to Migrere fra FFE") Indeks sine verdier på spacing-variabler justerer seg etter skjermstørrelse og [density-modus](#density-moduser). | FFE-token | Indeks-tokens | FFE verdi | Indeks verdi mobil | Indeks verdi desktop | | ----------------- | ---------------- | --------- | ------------------ | -------------------- | | `ffe-spacing-2xs` | `ix-spacing-2xs` | 4px | 4px | 4px | | `ffe-spacing-xs` | `ix-spacing-xs` | 8px | 8px | 8px | | | `ix-spacing-sm` | | 12px | 12px | | `ffe-spacing-sm` | `ix-spacing-md` | 16px | 16px | 16px | | `ffe-spacing-md` | `ix-spacing-lg` | 24px | 24px | 24px | | `ffe-spacing-lg` | `ix-spacing-xl` | 32px | 32px | 48px | | `ffe-spacing-xl` | `ix-spacing-xl` | 40px | 32px | 48px | | `ffe-spacing-2xl` | `ix-spacing-2xl` | 48px | 40px | 64px | | `ffe-spacing-3xl` | `ix-spacing-3xl` | 64px | 48px | 80px | | `ffe-spacing-4xl` | `ix-spacing-4xl` | 80px | 64px | 96px | | `ffe-spacing-5xl` | `ix-spacing-5xl` | 160px | 80px | 128px | Det er mulig å migrere til disse spacing-variablene ved bruk av search-replace-all, men det er viktig å dobbeltsjekke endringen (også på flere skjermstørrelser), da oversettelsen ikke er direkte for alle variablene. ### Migrere fra tailwind[​](#migrere-fra-tailwind "Direct link to Migrere fra tailwind") Hvis prosjektet ditt er satt opp med tailwind som bruker spacing-skalaen fra FFE slik som det her: ``` { 0: 0, 0.5: spacing.spacing2xs, 1: spacing.spacing, 2: spacing.spacingSm, 3: spacing.spacingMd, 4: spacing.spacingLg, 5: spacing.spacingXl, 6: spacing.spacing2xl, 8: spacing.spacing3xl, 10: spacing.spacing4xl, 20: spacing.spacing5xl } ``` Kan du ta utgangspunkt i disse tabellene: ### Padding[​](#padding "Direct link to Padding") Verdiene er de samme for `pt`, `pb`, `pl` og `pr`. Se [responsiv spacing](/docs/utility-klasser/oversikt.md#responsiv-spacing) for padding på forskjellige skjermstørrelser. | Tailwind-token | Indeks Util-klasse | FFE/Tailwind verdi | Indeks verdi mobil | Indeks desktop | | -------------- | ------------------ | ------------------ | ------------------ | -------------- | | `p-0` | `ix-p-0` | 0px | 0px | 0px | | `p-0.5` | `ix-p-2xs` | 4px | 4px | 4px | | `p-1` | `ix-p-xs` | 8px | 8px | 8px | | | `ix-p-sm` | | 12px | 12px | | `p-2` | `ix-p-md` | 16px | 16px | 16px | | `p-3` | `ix-p-lg` | 24px | 24px | 24px | | `p-4` | `ix-p-xl` | 32px | 32px | 48px | | `p-5` | `ix-p-xl` | 40px | 32px | 48px | | `p-6` | `ix-p-2xl` | 48px | 40px | 64px | | `p-8` | `ix-p-3xl` | 64px | 48px | 80px | | `p-10` | `ix-p-4xl` | 80px | 64px | 96px | | `p-20` | `ix-p-5xl` | 160px | 80px | 128px | ### Margin[​](#margin "Direct link to Margin") Verdiene er de samme for `mt`, `mb`, `ml` og `mr`. Se [responsiv spacing](/docs/utility-klasser/oversikt.md#responsiv-spacing) for margin på forskjellige skjermstørrelser. | Tailwind-token | Indeks Util-klasse | FFE/Tailwind verdi | Indeks verdi mobil | Indeks desktop | | -------------- | ------------------ | ------------------ | ------------------ | -------------- | | `m-0` | `ix-m-0` | 0px | 0px | 0px | | `m-0.5` | `ix-m-2xs` | 4px | 4px | 4px | | `m-1` | `ix-m-xs` | 8px | 8px | 8px | | | `ix-m-sm` | | 12px | 12px | | `m-2` | `ix-m-md` | 16px | 16px | 16px | | `m-3` | `ix-m-lg` | 24px | 24px | 24px | | `m-4` | `ix-m-xl` | 32px | 32px | 48px | | `m-5` | `ix-m-xl` | 40px | 32px | 48px | | `m-6` | `ix-m-2xl` | 48px | 40px | 64px | | `m-8` | `ix-m-3xl` | 64px | 48px | 80px | | `m-10` | `ix-m-4xl` | 80px | 64px | 96px | | `m-20` | `ix-m-5xl` | 160px | 80px | 128px | ### Gap[​](#gap "Direct link to Gap") | Tailwind-token | Indeks Util-klasse | FFE/Tailwind verdi | Indeks verdi mobil | Indeks desktop | | -------------- | ------------------ | ------------------ | ------------------ | -------------- | | `gap-0` | `ix-gap-0` | 0px | 0px | 0px | | `gap-0.5` | `ix-gap-2xs` | 4px | 4px | 4px | | `gap-1` | `ix-gap-xs` | 8px | 8px | 8px | | | `ix-gap-sm` | | 12px | 12px | | `gap-2` | `ix-gap-md` | 16px | 16px | 16px | | `gap-3` | `ix-gap-lg` | 24px | 24px | 24px | | `gap-4` | `ix-gap-xl` | 32px | 32px | 48px | | `gap-5` | `ix-gap-xl` | 40px | 32px | 48px | | `gap-6` | `ix-gap-2xl` | 48px | 40px | 64px | | `gap-8` | `ix-gap-3xl` | 64px | 48px | 80px | | `gap-10` | `ix-gap-4xl` | 80px | 64px | 96px | | `gap-20` | `ix-gap-5xl` | 160px | 80px | 128px | Ta gjerne kontakt med oss om du har andre behov enn det Indeks tilbyr. --- # Z Index Z-index er en CSS-egenskap som styrer stablingsrekkefølgen til elementer på en nettside. Med z-index kan du bestemme hvilke elementer som skal ligge over eller under andre, spesielt når de overlapper hverandre. For å sikre konsistens og forutsigbarhet i designet, har vi definert en rekke z-index tokens som dekker vanlige brukstilfeller i SpareBank 1 sitt designsystem. Hver token representerer en CSS custom property, som gjør det enkelt å bruke og vedlikeholde z-index-verdier på tvers av prosjekter. Tokenene er navngitt etter formålet de skal dekke, og verdiene er nøye valgt for å unngå konflikter mellom ulike komponenter og overlays. Ved å bruke disse tokenene sikrer du at grensesnittet oppfører seg konsistent, og at viktige elementer alltid vises i riktig rekkefølge. | CSS custom property | Verdi | Beskrivelse | | ------------------- | ----- | -------------------------------------------------------------------------------------------------------------------- | | `--ix-z-background` | -1 | Bakgrunnselementer som alltid skal ligge bak alt annet. | | `--ix-z-default` | 0 | Standard z-index for vanlige komponenter og innhold. | | `--ix-z-elevated` | 1 | Brukes for elementer som skal ligge over standard innhold. | | `--ix-z-overlay` | 20 | Overlay som skal ligge over innholdet på siden. | | `--ix-z-dialog` | 60 | Dialoger som skal ligge over alt annet. | | `--ix-z-max` | 100 | For når du har noe som må ligge øverst uansett hva. Vi annbefaler å bruke denne like mye som !important. Dvs. aldri. | --- # Typografi ## Våre fonter[​](#våre-fonter "Direct link to Våre fonter") Vår egenutviklede skrifttype er en viktig del av identiteten vår. Den gjør at vi skiller oss tydelig fra konkurrentene, bygger personlighet og gir oss en gjenkjennelig stemme på tvers av flater. Skrifttypene er basert på vårt sirkulære formspråk og bidrar til å knytte identiteten tettere sammen. Vi bruker to fonter: SpareBank 1 Title til de største overskriftene og SpareBank 1 til all øvrig tekst. ### SpareBank 1 Title[​](#sparebank-1-title "Direct link to SpareBank 1 Title") Brukes på de største overskriftene og er derfor ekstra distinkt. Fonten kjennetegnes av tydelige, sirkulære former som skaper kontrast mot de smalere bokstavene og gir et sterkt visuelt uttrykk. SpareBank 1 Title skal ikke brukes i lengre brødtekster, da den ikke er optimalisert for lesbarhet i mengdetekst. ### SpareBank 1[​](#sparebank-1 "Direct link to SpareBank 1") I brødtekst og lengre tekster bruker vi en mindre distinkt font som er optimalisert for lesbarhet i mengdetekst. Begge fontene er tilgjengelige i Figma og kan brukes direkte, uten behov for lokal installasjon. ## Store bokstaver og kursiv[​](#store-bokstaver-og-kursiv "Direct link to Store bokstaver og kursiv") Unngå å bruke tekst med kun store bokstaver, da dette gir dårligere lesbarhet. Det samme gjelder kursiv, som ikke bør brukes i overskrifter eller i større tekstmengder, ettersom det kan gjøre teksten vanskeligere å lese. ## Fontstørrelse[​](#fontstørrelse "Direct link to Fontstørrelse") Basestørrelsen er alltid 16px (`1rem`) og skalerer ikke med skjermstørrelsen. Overskriftsstørrelsene er faste og beregnes ut fra basestørrelsen, slik at proporsjonene er konsistente på tvers av enheter og kontekster. ## Størrelse på overskrifter og semantikk[​](#størrelse-på-overskrifter-og-semantikk "Direct link to Størrelse på overskrifter og semantikk") Du står fritt til å velge størrelse på overskrifter basert på behov og kontekst. Semantikk og visuell utforming er bevisst holdt adskilt, slik at riktig HTML-struktur kan brukes uavhengig av ønsket uttrykk. ## Linjelengde[​](#linjelengde "Direct link to Linjelengde") WCAG anbefaler å begrense linjelengden for å sikre god lesbarhet og tilgjengelighet. Både for lange og for korte linjer kan ha negativ effekt på leseflyten. Optimal linjelengde for brødtekst på større skjermer er mellom 50 og 75 tegn per linje, inkludert mellomrom. Dette gir en god balanse mellom flyt og lesbarhet, og gjør det enklere for øyet å finne starten på neste linje. Linjer som er for korte kan gjøre teksten hakkete, mens for lange linjer kan gjøre det mer krevende å følge teksten over tid. På mobil anbefales kortere linjelengder, typisk 35–50 tegn per linje, for å sikre god lesbarhet på små skjermer. Unngå linjer med færre enn 20 tegn, da dette fører til mange linjeskift og gjør teksten mer krevende å lese. ## Linjehøyde[​](#linjehøyde "Direct link to Linjehøyde") Standard linjehøyde i Indeks er 1.2. Brødtekst som er lengre enn noen få linjer trenger større linjehøyde for bedre lesbarhet, og kan overstyres til 1.4 med henholdsvis `Text/Body long/md - regular` i Figma, `long`-propen i `Text`-komponenten, eller CSS-klassen `.ix-text--long`. ## Venstrestilt tekst er standard[​](#venstrestilt-tekst-er-standard "Direct link to Venstrestilt tekst er standard") Venstrestilt tekst gir best lesbarhet. Midtstilt tekst kan på lengre tekster gjør det vanskeligere å lese, men kan brukes varsomt på korte tekstmengder, for eksempel i overskrifter med enkel støttetekst. ## Farge på tekst[​](#farge-på-tekst "Direct link to Farge på tekst") Bruk ix-color-foreground-main-emphasis på overskrifter for tydelig hierarki. Til brødtekst og vanlig tekst brukes ix-color-foreground-main-default, mens For mindre fremtredende tekst, som støttetekst eller sekundær informasjon, kan ix-color-foreground-main-subtle benyttes. ## Stiler[​](#stiler "Direct link to Stiler") I Indeks bruker vi fire typografiske stiler: Heading, BodyLong, BodyShort og Label. Beskrivelse av når og hvordan de ulike stilene brukes, finner du under typografikomponentene. --- # Indeks Indeks er SpareBank 1 sitt designsystem - et verktøy for å lage helhetlige, brukervennlige og inkluderende løsninger. ## Tilpass dokumentasjonen Velg teknologi og andre innstillinger så tilpasser vi eksemplene til stacken din. Åpne innstillinger [Utility-klasser](/docs/utility-klasser/oversikt.md) [Spacing-tokens](/docs/grunnleggende/tokens/spacing.md) [Farge-tokens og -utils](/docs/retningslinjer/farger/.md) ## Kom i gang[​](#kom-i-gang "Direct link to Kom i gang") [Designer](/docs/kom-i-gang/designer.md) [Utvikler](/docs/kom-i-gang/utvikler.md) ## Bruk Indeks med AI-assistenter[​](#bruk-indeks-med-ai-assistenter "Direct link to Bruk Indeks med AI-assistenter") Hele dokumentasjonen er tilgjengelig som ren tekst som kan limes direkte inn i Claude, ChatGPT, Cursor eller andre LLM-verktøy: * [`llms-full.txt`](/llms-full.txt) — hele dokumentasjonen i én fil, klar til å limes inn som kontekst * [`llms.txt`](/llms.txt) — hierarkisk indeks hvis du vil at AI-en skal slå opp enkeltsider Hver dokumentasjonsside finnes også som `.md`-variant — legg `.md` etter URL-en, for eksempel [`/docs/komponenter/textfield.md`](/docs/komponenter/textfield.md). --- # Bidra Enten du mangler en komponent, har forslag til forbedringer, eller har funnet noe som ikke fungerer som det skal, vil vi gjerne høre fra deg. ## Registrer feil eller mangler[​](#registrer-feil-eller-mangler "Direct link to Registrer feil eller mangler") Bruk én av disse malene i GitHub: * [Kodefeil](https://github.com/SpareBank1/indeks/issues/new?template=kodefeil.yml) — feil i en komponent, token eller stil * [Dokumentasjonsfeil](https://github.com/SpareBank1/indeks/issues/new?template=dokumentasjonsfeil.yml) — noe er feil, utdatert eller uklart i dokumentasjonen * [Ny komponent](https://github.com/SpareBank1/indeks/issues/new?template=ny-komponent.yml) — foreslå en ny komponent eller større utvidelse Du kan også bruke "Rapporter feil på denne siden"-lenken nederst på hver dokumentasjonsside for å åpne et forhåndsutfylt skjema. ## Ny komponent[​](#ny-komponent "Direct link to Ny komponent") Når vi vurderer nye bidrag til Indeks ser vi på hvordan de kan støtte arbeidet ditt og hvordan de passer inn i helheten av systemet. Målet er å gi deg fleksible og pålitelige byggeklosser som gjør det enklere å lage gode løsninger, både nå og over tid. Med Atomic Design som utgangspunkt bygger vi Indeks slik at du kan sette sammen det du trenger, på en måte som fungerer godt sammen med resten av systemet. Ved vurdering av nye komponenter ser vi på: * **Gjenbrukbarhet**: Er det flere som vil ha nytte av den? * **Verdi**: Hvilket problem løser den, og kan det løses av en annen komponent? * **Fleksibilitet**: Kan den tilpasses ulike behov? * **Konsistens**: Stemmer den overens med våre designprinsipper og helheten i systemet? Huskeliste: * Kan komponentene brukes i flere kontekster? * Er komponenten navigerbar med tastatur og i tråd med WCAG-krav? * Har alle states god nok kontrast? * Hvordan blir opplevelsen på mobil vs desktop? Er det best med andre løsninger på mobil, som f.eks sheets eller haptic feedback? ## Mønstre og retningslinjer[​](#mønstre-og-retningslinjer "Direct link to Mønstre og retningslinjer") God dokumentasjon og tydelige retningslinjer hjelper oss å trekke i samme retning og redusere usikkerhet i hverdagen. Derfor setter vi stor pris på bidrag også her, enten det er noe som er uklart, mangler, eller kan forklares bedre. ## Slik bidrar du[​](#slik-bidrar-du "Direct link to Slik bidrar du") Du trenger ikke å komme med et ferdig forslag. En tidlig idé eller et spørsmål er mer enn nok til å starte en god dialog. * **Ta kontakt med oss**: Send oss en melding på Slack eller kom bort og prat med oss når et behov, en idé eller et problem dukker opp. * **Beskriv situasjonen**: Fortell oss hva du prøver å løse for brukerne dine, eller hva som ikke fungerer som forventet. * **Vi ser på det sammen**: Sammen vurderer vi hvordan behovet best kan løses og hvordan det passer inn i helheten av Indeks. * **Vi blir enige om veien videre**: Vi avklarer om det betyr en justering, ny funksjonalitet, bedre dokumentasjon og hvem som gjør hva. * **Vi følger det til mål**: Når vi er enige om retningen, sørger vi for at arbeidet blir tatt videre på en god måte. Vi vil at Indeks skal være så nyttig og relevant som mulig, og det får vi bare til sammen med dere! --- # Designer ## Før du begynner[​](#før-du-begynner "Direct link to Før du begynner") 1. Les [merkevaren og vår visuelle identitet](https://merkevare.sparebank1.no/portal) for å forstå SpareBank 1s designprinsipper 2. [Sett opp Figma](/docs/kom-i-gang/designer.md) og få tilgang til designsystembiblioteket 3. Bli med i Slack-kanalene `#ext-design` og `#ext-designsystem` ## Viktig dokumentasjon[​](#viktig-dokumentasjon "Direct link to Viktig dokumentasjon") Før du begynner å designe, anbefaler vi at du setter deg inn i følgende: * **[Tokens](/docs/grunnleggende/tokens/introduksjon.md)** - farger, spacing, typografi og andre designtokens * **[Mønstre og maler](/docs/monstre-og-maler/layout.md)** - vanlige designmønstre og layoutmaler ## Verktøy[​](#verktøy "Direct link to Verktøy") ### Figma[​](#figma "Direct link to Figma") I SpareBank 1 bruker vi Figma til å designe for digitale flater. Designsystemet og illustrasjonsbiblioteket er tilgjengelig som standard i alle Figma-filer. ### Slack[​](#slack "Direct link to Slack") Vi bruker Slack til kommunikasjon på tvers av team. Viktige kanaler for designere: * **`#ext-design`** - felleskanal for alle designere * **`#ext-designsystem`** - tilbakemeldinger og hjelp fra designsystemteamet * **`#sb1u-restefest`** - bli med i kampen mot matsvinn ### Ønskeliste[​](#ønskeliste "Direct link to Ønskeliste") Vi har laget en ønskeliste i Figma hvor du kan komme med forslag og ønsker om forbedringer på komponenter. ## Samarbeid og møter[​](#samarbeid-og-møter "Direct link to Samarbeid og møter") ### Felles designmøter[​](#felles-designmøter "Direct link to Felles designmøter") * **DesignLab** (hver 4. uke) - en lavterskel møteplass for å styrke dialogen, bryte ned siloer og sikre en rød tråd i våre flater. Ta med egne oppgaver og utfordringer knyttet til teamet ditt, og få hjelp eller diskuter dem etter egne behov. * **Designsystem-forum** (hver 4. uke) - felles møteplass for designere og utviklere sammen med designsystemteamet. Vi tar opp både konkrete komponentspørsmål og større strategiske temaer. Meld gjerne inn saker på forhånd i `#ext-designsystem`. ### Fagtid[​](#fagtid "Direct link to Fagtid") På torsdager har alle fast ansatte i SpareBank 1 Utvikling fagtid. Før lunsj samles designerne til avdelingsmøte, hvor vi deler erfaringer fra teamene våre og tar opp andre fagrelaterte temaer. Resten av dagen kan brukes til kompetansebygging eller deltakelse i fagrupper, for eksempel faggruppen for universell utforming. --- # Introduksjon Visuell identitet --- # Kontakt Indeks blir best når vi snakker sammen. Vi setter stor pris på alle innspill, spørsmål og bidrag fra dere som bruker systemet. ## Slack[​](#slack "Direct link to Slack") Vi kan nås på: [#ext-designsystem](slack://channel?team=\&id=ext-designsystem) Her kan du stille spørsmål, dele erfaringer, rapportere bugs, eller diskutere nye ideer og forbedringer. Vi svarer gjerne på spørsmål om bruk av komponenter, konvensjoner og hjelper til med utfordringer du måtte ha. ## Epost[​](#epost "Direct link to Epost") **E-post**: ## Designsystemforum[​](#designsystemforum "Direct link to Designsystemforum") Designsystemforum er et tverrfagelig møtested hver fjerde uke, hvor vi diskuterer fremtidige planer, tar opp utfordringer og deler erfaringer på tvers av team og fagfelt. Gi bedskjed om du ikke har fått invitasjon, så fikser vi det! ## Teamet[​](#teamet "Direct link to Teamet") Team Designsystem består av * **Martin Gaard**: Design Lead * **Dag Frode Solberg**: Tech lead, utvikler * **Anders Johnsen**: Utvikler * **Tuva Ødegård**: Utvikler * **Karina Hammermark Holme**: Produktleder Det er bare å ta kontakt hvis det er noe, eller slå av en prat hvis du ser oss i gangene. --- # Migrering fra FFE til Indeks Indeks er et helt nytt designsystem, bygget opp fra grunnen med en annen arkitektur og struktur enn FFE. For deg som skal migrere fra FFE betyr dette at enkelte ting må gjøres litt annerledes enn før. ## Atomic design[​](#atomic-design "Direct link to Atomic design") Atomic design er en metodikk for å bygge brukergrensesnitt ved å dele dem opp i små, gjenbrukbare deler. Metoden ble introdusert av Brad Frost og tar inspirasjon fra hvordan ting bygges opp i naturen. I atomic design organiseres komponenter i ulike nivåer: * **Atoms** er de minste byggesteinene i et grensesnitt, som for eksempel knapper, input-felt, labels eller ikoner. * **Molecules** er kombinasjoner av flere atoms, for eksempel et søkefelt som består av et input-felt og en knapp. * **Organisms** er større og mer sammensatte komponenter, som for eksempel et navigasjonsfelt eller et kort med flere elementer. Tanken er at små, enkle deler kan kombineres til mer komplekse komponenter og til slutt komplette brukergrensesnitt. I Indeks bygger vi komponenter etter prinsippene i atomic design. Atomic design er en metode for å strukturere komponenter der små, enkle byggeklosser settes sammen til større og mer komplekse løsninger I praksis betyr dette at Indeks primært tilbyr grunnleggende basekomponenter. Disse kan settes sammen til mer avanserte komponenter etter behov. Designsystemet tar ansvar for å utvikle og vedlikeholde disse basekomponentene, mens produktteamene selv har ansvar for å bygge og forvalte større og mer komplekse komponenter. En viktig grunn til denne tilnærmingen er å gi teamene større fleksibilitet og kreativ frihet. Samtidig bidrar det til å hindre at designsystemet blir en flaskehals i produktutviklingen. Dersom designsystemteamet også skulle vedlikeholde alle komplekse komponenter som ulike team trenger, ville det raskt kunne skape avhengigheter og redusere tempoet i utviklingen for produktteamene. Ved å holde designsystemet fokusert på stabile og gjenbrukbare byggeklosser, kan produktteamene jobbe mer selvstendig og utvikle løsninger raskere. ## Webstandarder fremfor rammeverk[​](#webstandarder-fremfor-rammeverk "Direct link to Webstandarder fremfor rammeverk") Indeks er bygget på webstandarder i stedet for å baseres på et spesifikt rammeverk som React eller Vue. Dette betyr at du kan bruke Indeks-komponenter i hvilken som helst frontend-teknologi du foretrekker, uten å måtte bekymre deg for kompatibilitet eller avhengigheter. Komponentene er i utgangspunktet skrevet som ren HTML og CSS, og utvidet i form av web components der det er nødvendig. Likevel tilbyr Indeks også React-komponenter for de som ønsker å bruke det, men det er ikke et krav for å kunne bruke designsystemet. React-komponentene er i praksis tynne wrapper-komponenter som gjør det enklere å bruke Indeks i React-prosjekter. ## Utility-klasser[​](#utility-klasser "Direct link to Utility-klasser") Indeks tilbyr et omfattende sett med utility-klasser i Tailwind-stil for å hjelpe deg med å bygge og tilpasse komponenter raskt og effektivt. Disse klassene dekker alt fra layout og spacing til farger og typografi, og kan brukes direkte i HTML for å justere utseendet og oppførselen til elementene dine uten behov for egendefinert CSS. For en fullstendig oversikt over tilgjengelige utility-klasser, se [Utility-dokumentasjonen](/docs/utility-klasser/oversikt.md). ## CDN og NPM-pakker[​](#cdn-og-npm-pakker "Direct link to CDN og NPM-pakker") Indeks tilbyr både CDN og NPM-pakker for å gjøre det enkelt å integrere designsystemet i dine prosjekter. CDN-alternativet lar deg raskt inkludere styling, fonter og ikoner i prosjektet ditt med en enkel ``-tag, mens NPM-pakkene gir deg mer kontroll og fleksibilitet ved å la deg installere og administrere Indeks som en avhengighet i prosjektet ditt på samme måte som i FFE. Styling, utilities, komponenter og tokens er samlet i hver sin NPM-pakke, i motsetning til i FFE der alle komponenter ble distribuert i egne pakker. I Indeks trenger du for eksempel kun å installere én pakke for å bruke alle React-komponentene. Dette forenkler installasjon og bruk av designsystemet, og gjør det mindre sårbart for endringer som påvirker avhengigheter frem og tilbake mellom pakkene og eksternt. Disse pakkene er tilgjengelige i Indeks: * [Indeks-CSS](https://www.npmjs.com/package/@sb1/indeks-css) * [Indeks-Utils](https://www.npmjs.com/package/@sb1/indeks-utils) * [Indeks-React](https://www.npmjs.com/package/@sb1/indeks-react) * [Indeks-Tokens](https://www.npmjs.com/package/@sb1/indeks-tokens) ## Farger[​](#farger "Direct link to Farger") Indeks har en mer begrenset og konsistent fargepalett enn FFE. Dette er gjort for å sikre en mer helhetlig og gjenkjennelig visuell identitet på tvers av alle produkter som bruker Indeks. Ved å bruke et standardisert sett med farger, kan vi skape en sterkere merkevare og forbedre brukeropplevelsen ved å gi en mer sammenhengende og profesjonell visuell stil. For mer informasjon om tilgjengelige farger i Indeks, se [Farge-dokumentasjonen](/docs/retningslinjer/farger/.md). --- # Utvikler Kom i gang med Indeks i prosjektet ditt. Velg teknologi under, så tilpasser guiden seg. ## Velg teknologi[​](#velg-teknologi "Direct link to Velg teknologi") Bruk Indeks med ReactNår av vises HTML og web component-eksempler (\).\[x]Vis kodeeksemplerNår av kollapses koden under live-eksemplet. Du kan alltid åpne 'Kode'.\[ ]Mobilbank-modusSlå på hvis du utvikler for mobilbanken eller andre MBC-apper.\[ ] ## Installasjon[​](#installasjon "Direct link to Installasjon") ### 1. Fonter og CDN-tilkobling[​](#1-fonter-og-cdn-tilkobling "Direct link to 1. Fonter og CDN-tilkobling") Legg til SB1-fontene i `` i HTML-dokumentet ditt. Monorepo-generatoren gjør dette automatisk. Indeks henter fonter, CSS, web components og ikon-SVG-er fra `cdn.sparebank1.no` ved runtime. Legg derfor en `preconnect` øverst i `` — da rekker nettleseren DNS-oppslag, TLS-handshake og tilkobling før den første ressursen faktisk skal lastes, og du sparer ventetid på den kritiske gjengivingsstien. ``` ``` `crossorigin` er nødvendig fordi fontene lastes med CORS; uten det åpner nettleseren en egen tilkobling for dem og preconnect-en blir bortkastet. ### 2. Styling[​](#2-styling "Direct link to 2. Styling") Importer CSS-en fra CDN inn i hoved-CSS-filen din, og legg `ix-body`-klassen på ``. CDN-URL-en er den samme på tvers av SB1-applikasjoner, så nettleseren kan gjenbruke samme cachede CSS. ``` @import url('https://cdn.sparebank1.no/indeks/css/0.17.0/index.css'); ``` ``` ``` Du får komponentstyling, [utility-klasser](/docs/utility-klasser/oversikt.md) og [designtokens](/docs/grunnleggende/tokens/introduksjon.md) i samme pakke. ### 3. Web components[​](#3-web-components "Direct link to 3. Web components") Last inn web components-scriptet fra CDN i `index.html`. ``` ``` Komponentene er nå tilgjengelige som HTML-elementer: ```
``` ### 3. Web components[​](#3-web-components-1 "Direct link to 3. Web components") Last inn web components-scriptet fra CDN i `index.html`. `@sb1/indeks-react` er et tynt lag oppå web components og rendrer ``-elementer internt, så scriptet må være lastet for at React-komponentene skal virke. ``` ``` ### 3a. TypeScript-typer (valgfritt)[​](#3a-typescript-typer-valgfritt "Direct link to 3a. TypeScript-typer (valgfritt)") Bruker du TypeScript? Installer `@sb1/indeks-web` som `devDependency` for å få TS-kjennskap til `` og andre `ix-*`-elementer. Runtime lastes fortsatt fra CDN (steg 3), så pakken havner ikke i produksjonsbundlen. ``` npm install --save-dev @sb1/indeks-web ``` Aktiver typene ved å legge pakken i `tsconfig.json`: ``` { "compilerOptions": { "types": ["@sb1/indeks-web"] } } ``` Pakken bruker `declare global` for å utvide `HTMLElementTagNameMap` og `JSX.IntrinsicElements`. TypeScript plukker bare opp dette hvis pakken er listet i `types` eller importert. ### 3b. Autocomplete i editor (valgfritt)[​](#3b-autocomplete-i-editor-valgfritt "Direct link to 3b. Autocomplete i editor (valgfritt)") Få forslag på klassenavn og CSS-variabler når du skriver. VSCode-utvidelser gir dette — men krever to utvidelser (ingen enkelt-utvidelse dekker begge): * [HTML CSS Support](https://marketplace.visualstudio.com/items?itemName=ecmel.vscode-html-css) — autocomplete på `className="ix-..."` i HTML, JSX og TSX. * [CSS Variable Autocomplete](https://marketplace.visualstudio.com/items?itemName=vunguyentuan.vscode-css-variables) — autocomplete på `var(--ix-*)`. Legg til workspace-konfig som peker til CSS-filen i `@sb1/indeks-css`. Siden tokens og utils er inlinet i `index.css`, er det bare én fil å peke til: ``` // .vscode/settings.json { "css.styleSheets": [ "node_modules/@sb1/indeks-css/dist/npm/index.css" ], "cssVariables.lookupFiles": [ "node_modules/@sb1/indeks-css/dist/npm/index.css" ] } ``` Anbefal utvidelsene for alle team-medlemmer: ``` // .vscode/extensions.json { "recommendations": [ "ecmel.vscode-html-css", "vunguyentuan.vscode-css-variables" ] } ``` Reload VSCode-vinduet etter `npm install` for at utvidelsene skal plukke opp filen. Autocomplete virker på rene string-literaler — `clsx(...)` og template-strings mister delvis støtte. Andre editorer (Cursor, WebStorm, Zed) har tilsvarende utvidelser fra sine markedsplasser. ### 4. React-komponenter[​](#4-react-komponenter "Direct link to 4. React-komponenter") Installer React-pakken: ``` npm install @sb1/indeks-react ``` Importer komponentene der du skal bruke dem: ``` import { Button, Text } from '@sb1/indeks-react'; ``` ``` function App() { return (
Innhold
); } ``` ### 5. Hold CDN-URL-er i takt[​](#5-hold-cdn-url-er-i-takt "Direct link to 5. Hold CDN-URL-er i takt") `@sb1/indeks-css` og `@sb1/indeks-web` versjonslåses til samme versjon som `@sb1/indeks-react`. Når Dependabot bumper React-pakken i `package.json`, må CDN-URL-ene i `index.html` og CSS-filene dine oppdateres til samme versjon — ellers får du drift mellom det React-komponentene forventer og det som faktisk er lastet i nettleseren. Scriptet `indeks-react sync-cdn` oppdaterer URL-ene til å matche versjonen du har installert. Legg til to scripts i `package.json`: ``` { "scripts": { "prebuild": "indeks-react sync-cdn --check", "sync-indeks": "indeks-react sync-cdn" } } ``` * `prebuild` kjører før hver `npm run build` og **feiler** hvis URL-ene ikke matcher installert versjon. Dette er med vilje: hvis builden auto-fikser driften, vil det som deployes kunne bruke andre klasser enn det du har testet lokalt. La utvikleren se feilen og kjøre sync eksplisitt. * `sync-indeks` kjører du selv etter en dependency-bump — eller når `prebuild` feiler. Den oppdaterer filene, du commit-er endringene og kjører builden på nytt. Typisk flyt etter en Dependabot-bump: ``` npm install # ny indeks-react-versjon låst i package-lock npm run build # prebuild feiler: drift funnet npm run sync-indeks # URL-ene oppdateres git add -A && git commit -m "sync CDN til " npm run build # passer nå ``` Vi anbefaler `npm install --ignore-scripts` av sikkerhetsgrunner, og det hopper over alle lifecycle-hooks — derfor kan vi ikke sette dette opp som `postinstall`. CDN-sync må hektes på en kommando du eksplisitt kjører. ## Installere via npm i stedet for CDN[​](#installere-via-npm-i-stedet-for-cdn "Direct link to Installere via npm i stedet for CDN") `@sb1/indeks-css` og `@sb1/indeks-web` finnes også på npm, men vi anbefaler CDN. Med CDN deler alle SB1-applikasjoner samme URL, så nettleseren kan gjenbruke cachen på tvers av apper — brukerne slipper å laste ned CSS og web components på nytt når de bytter mellom SB1-tjenester. Hvis du likevel vil bundle det selv (f.eks. intern app uten CDN-tilgang): ``` npm install @sb1/indeks-css @sb1/indeks-web ``` ## Hva nå?[​](#hva-nå "Direct link to Hva nå?") * Lær om [designtokens](/docs/grunnleggende/tokens/introduksjon.md) for å lage egne komponenter * Bruk [utility-klasser](/docs/utility-klasser/oversikt.md) for rask styling * Se [mønstre og maler](/docs/monstre-og-maler/layout.md) for vanlige bruksområder * Migrering: [spacing fra FFE](/docs/grunnleggende/tokens/spacing.md#migrere-fra-ffe), [spacing fra Tailwind](/docs/grunnleggende/tokens/spacing.md#migrere-fra-tailwind), [farger fra FFE](/docs/retningslinjer/farger/.md#migrere-fra-ffe) ## Teknisk struktur[​](#teknisk-struktur "Direct link to Teknisk struktur") De fleste trenger ikke å forholde seg til dette, men du kan lese videre hvis du er spesielt interessert. Indeks er bygget opp av 5 pakker: * indeks-tokens * indeks-utils * indeks-css * indeks-web * indeks-react Vi har også en mappe med dokumentasjonen og en eksempel-app vi bruker til å teste. ![](/img/kom-i-gang/teknisk-struktur.png) --- # Accordion Accordion viser og skjuler innhold i seksjoner. Den er nyttig når mye innhold skal gjøres oversiktlig: brukeren ser overskriftene og åpner kun det som er relevant. Komponenten bygger på native `
`/``, så tastatur og skjermleser fungerer uten ekstra oppsett. ## Egnet til[​](#egnet-til "Direct link to Egnet til") * Vanlige spørsmål (FAQ) og hjelpeinnhold * Lange skjemaer eller innstillinger delt i logiske bolker * Sekundær informasjon som ikke alle trenger samtidig * Å gjøre tett innhold skannbart uten å skjule det helt ## Uegnet til[​](#uegnet-til "Direct link to Uegnet til") * Innhold brukeren må se for å komme videre — vis det åpent * Én enkelt seksjon — bruk heller en vanlig overskrift + tekst * Navigasjon mellom sider — bruk lenker eller meny * Når alt innholdet uansett må leses i rekkefølge ## Kom i gang[​](#kom-i-gang "Direct link to Kom i gang") Result Loading... Kode Live Editor Reset ``` Hvordan logger jeg inn?

Du logger inn med BankID eller BankID på mobil øverst til høyre.

Hvordan endrer jeg passord?

Gå til Innstillinger → Sikkerhet og velg «Endre passord».

``` Result Loading... Kode Live Editor Reset ```
Hvordan logger jeg inn?

Du logger inn med BankID eller BankID på mobil øverst til høyre.

Hvordan endrer jeg passord?

Gå til Innstillinger → Sikkerhet og velg «Endre passord».

``` ## Eksempler[​](#eksempler "Direct link to Eksempler") ### Default-åpne seksjoner[​](#default-åpne-seksjoner "Direct link to Default-åpne seksjoner") Seksjonene er uavhengige — flere kan stå åpne samtidig. Marker de seksjonene som bør være åpne ved start med `defaultOpen`. Result Loading... Kode Live Editor Reset ``` Første seksjon

Denne er åpen som standard.

Andre seksjon

Denne er også åpen — begge kan stå åpne samtidig.

``` ### Med prefiks-ikon[​](#med-prefiks-ikon "Direct link to Med prefiks-ikon") `Accordion.Header` tar `ReactNode`, så du kan sette et ikon foran tittelen. Teksten er alltid hovedbæreren — ikonet er kun støtte. Result Loading... Kode Live Editor Reset ``` Kort og betaling

Administrer kortene dine, sperr kort og se betalinger.

Sikkerhet

Endre passord og se påloggingshistorikk.

``` ### Rikt innhold[​](#rikt-innhold "Direct link to Rikt innhold") Innholdet kan bestå av tekst, lister, lenker og andre komponenter. Result Loading... Kode Live Editor Reset ``` Hva er inkludert?

Avtalen inkluderer blant annet:

  • Nettbank og mobilbank
  • Gratis kortbruk i Norge
  • Varsling på SMS
  • Les mer i vilkårene.

    Hva koster det?

    Se gjeldende priser i prislisten.

    ``` ## Retningslinjer[​](#retningslinjer "Direct link to Retningslinjer") ### Innhold og formulering[​](#innhold-og-formulering "Direct link to Innhold og formulering") * Skriv korte, beskrivende headere som gir mening lest alene. * Start med det viktigste ordet i headeren — den skal være lett å skanne. * Unngå at brukeren må åpne seksjoner for å forstå hva de inneholder. ### Unngå overdreven nøsting[​](#unngå-overdreven-nøsting "Direct link to Unngå overdreven nøsting") Accordion i accordion blir fort uoversiktlig. Vurder å dele opp innholdet på en annen måte hvis du trenger flere nivåer. ### Default-åpne seksjoner[​](#default-åpne-seksjoner-1 "Direct link to Default-åpne seksjoner") Marker den eller de viktigste seksjonene med `defaultOpen` slik at brukeren ser noe innhold med en gang. Seksjonene er uavhengige, så du kan starte flere åpne samtidig. ## Universell utforming[​](#universell-utforming "Direct link to Universell utforming") ### Hva du selv må sørge for[​](#hva-du-selv-må-sørge-for "Direct link to Hva du selv må sørge for") * **Skriv kort og beskrivende header-tekst** — headeren er klikkflaten og må gi mening alene. Et valgfritt prefiks-ikon støtter, men teksten er alltid hovedbæreren. * **Plasser `Accordion.Header` først** i hver `Accordion.Item` — native `
    ` krever at `` er første barn. * **Bruk overskriftsnivå ved behov** — inngår headerne i en dokumentstruktur, kan du legge en ``/`

    ` inni `Accordion.Header` for korrekt overskriftshierarki. ### Hva komponenten gjør automatisk[​](#hva-komponenten-gjør-automatisk "Direct link to Hva komponenten gjør automatisk") * **Disclosure-semantikk** — header er en native ``: fokuserbar med Tab, åpnes/lukkes med Enter og Space, og åpen/lukket-tilstand annonseres av skjermlesere. Ingen ekstra ARIA er nødvendig. * **Programmessig kobling** — innholdet ligger inne i samme `
    ` som headeren, så de er knyttet sammen uten `aria-controls`/`id`. * **Tilstandsindikator** — en chevron roterer for å vise åpen/lukket. Animasjonen er kort og respekterer `prefers-reduced-motion`. * **Fokusindikator** — tydelig fokusring på header (`:focus-visible`). Avvik fra akseptansekriteriene: `` framfor ` ``` Result Loading... Kode Live Editor Reset ``` ``` ## Eksempler[​](#eksempler "Direct link to Eksempler") ### Varianter[​](#varianter "Direct link to Varianter") `primary` er standardvarianten og bør brukes for den viktigste handlingen på siden. Unngå to primary-knapper ved siden av hverandre. Result Loading... Kode Live Editor Reset ``` <> ``` Result Loading... Kode Live Editor Reset ``` <> ``` ### Fare[​](#fare "Direct link to Fare") Bruk `danger` for destruktive handlinger som sletting eller avbryt-operasjoner der konsekvensen er vanskelig å reversere. Result Loading... Kode Live Editor Reset ``` <> ``` Result Loading... Kode Live Editor Reset ``` <> ``` ### Størrelser[​](#størrelser "Direct link to Størrelser") Result Loading... Kode Live Editor Reset ``` <> ``` Result Loading... Kode Live Editor Reset ``` <> ``` ### Full bredde[​](#full-bredde "Direct link to Full bredde") Result Loading... Kode Live Editor Reset ``` ``` Result Loading... Kode Live Editor Reset ``` ``` ### Med ikon[​](#med-ikon "Direct link to Med ikon") Ikon-knapper med tekst trenger ingen ekstra ARIA — teksten er den tilgjengelige labelen. Plasser ikonet foran teksten. Result Loading... Kode Live Editor Reset ``` ``` Result Loading... Kode Live Editor Reset ``` ``` ### Ikonknapp (uten tekst)[​](#ikonknapp-uten-tekst "Direct link to Ikonknapp (uten tekst)") Knapper med bare ikon **må** ha `aria-label` som beskriver handlingen. Bruk `iconOnly` for å gjøre knappen rund. Result Loading... Kode Live Editor Reset ``` ``` Result Loading... Kode Live Editor Reset ``` ``` Ikonknapp uten aria-label En knapp med bare ikon og ingen `aria-label` er usynlig for skjermlesere. Brukeren hører bare "knapp" — ingen beskrivelse av hva den gjør. ### Laster[​](#laster "Direct link to Laster") Når en asynkron operasjon er i gang, sett `loading` og `loadingLabel`. Knappen deaktiveres, en spinner vises, og `loadingLabel` annonseres til skjermleseren. I React erstattes children (inkludert ikon) automatisk med spinner og `loadingLabel`. I HTML må du selv erstatte innholdet og sette `disabled` + `data-loading="true"`. Spinneren arver knappens tekstfarge, så den får riktig kontrast i alle varianter — også på fylt primary-bakgrunn. Result Loading... Kode Live Editor Reset ``` <> ``` Result Loading... Kode Live Editor Reset ``` ``` ### Deaktivert[​](#deaktivert "Direct link to Deaktivert") Result Loading... Kode Live Editor Reset ``` ``` Result Loading... Kode Live Editor Reset ``` ``` Vurder om brukeren i stedet bør se en forklaring på hvorfor handlingen ikke er tilgjengelig. En disabled-knapp uten kontekst er forvirrende. ### Som lenke[​](#som-lenke "Direct link to Som lenke") Bruk `as="a"` når knappen navigerer til en URL. Den beholder button-styling, men rendres som ``. Result Loading... Kode Live Editor Reset ``` ``` Result Loading... Kode Live Editor Reset ``` Gå til sparebank1.no ``` ## Retningslinjer[​](#retningslinjer "Direct link to Retningslinjer") ### Bruk riktig komponent: handling vs. navigasjon[​](#bruk-riktig-komponent-handling-vs-navigasjon "Direct link to Bruk riktig komponent: handling vs. navigasjon") Knapper skal brukes når brukeren utfører en handling som påvirker systemet — som å lagre, sende eller bekrefte noe. Dersom brukeren kun skal navigere til en ny side uten at noe behandles, skal lenke brukes i stedet. Skillet er viktig både for brukerens forventninger og for tilgjengelighet. ### Tydelig handling i label gir forutsigbarhet[​](#tydelig-handling-i-label-gir-forutsigbarhet "Direct link to Tydelig handling i label gir forutsigbarhet") Knappetekst skal beskrive hva som skjer når brukeren klikker. Den bør være handlingsorientert og konkret. "Lagre endringer" er tydeligere enn "OK", fordi den forklarer hva handlingen faktisk gjør. ### Unngå generiske labels[​](#unngå-generiske-labels "Direct link to Unngå generiske labels") Generiske tekster som "OK", "Send" eller "Neste" kan være uklare uten kontekst. Der det er mulig, bør teksten spesifisere hva som skjer — som "Send søknad" eller "Gå til betaling". ### Teksten skal være kort og énlinjet[​](#teksten-skal-være-kort-og-énlinjet "Direct link to Teksten skal være kort og énlinjet") Knappetekst skal være kort og presis. Korte tekster gjør knapper lettere å skanne og sikrer at layouten holder seg stabil på tvers av skjermstørrelser. ### Hierarki skaper struktur og prioritering[​](#hierarki-skaper-struktur-og-prioritering "Direct link to Hierarki skaper struktur og prioritering") Knapper skal ha et tydelig visuelt hierarki som viser hva som er viktigst å gjøre: * **Primærknapp** — hovedhandlingen i en visning * **Sekundærknapp** — alternative handlinger * **Tertiærknapp** — mindre viktige eller støttende handlinger * **Destruktiv knapp** — handlinger som sletter eller endrer data permanent Dersom en tertiær knapp brukes alene, skal den alltid kombineres med ikon. Dette sikrer at den fremstår som en handling og ikke forveksles med vanlig tekst. ### Én primær handling per visning[​](#én-primær-handling-per-visning "Direct link to Én primær handling per visning") Hver side eller seksjon bør ha én tydelig primær handling. Denne bør fremheves visuelt slik at det er klart hva brukeren skal gjøre videre. Flere primære knapper skaper konkurranse om oppmerksomheten og gjør det vanskeligere å ta en beslutning. ### Plassering og rekkefølge påvirker valg[​](#plassering-og-rekkefølge-påvirker-valg "Direct link to Plassering og rekkefølge påvirker valg") Når flere knapper plasseres ved siden av hverandre, skal primærknappen stå først. Et unntak er navigasjon mellom steg, som "Forrige" og "Neste" — der skal den sekundære knappen "Forrige" stå først. Dette samsvarer med brukerens forventning om retning og progresjon. ### Ikonknapper krever ekstra tydelighet[​](#ikonknapper-krever-ekstra-tydelighet "Direct link to Ikonknapper krever ekstra tydelighet") Knapper som kun består av ikon er forbeholdt løsninger for mer erfarne brukere, siden handlingen ikke beskrives med tekst. Unntak kan gjøres for godt etablerte ikoner som lukk eller slett — men knappen må alltid ha en tilgjengelig tekst via `aria-label`. ### Bekreft destruktive handlinger[​](#bekreft-destruktive-handlinger "Direct link to Bekreft destruktive handlinger") Handlinger som sletter eller endrer data permanent bør enten kreve en ekstra bekreftelse (f.eks. en modal) eller tydelig merkes som destruktive med `danger`-prop. ### Ikke bruk disabled uten forklaring[​](#ikke-bruk-disabled-uten-forklaring "Direct link to Ikke bruk disabled uten forklaring") Disabled-knapper kan være vanskelig å forstå hvis det ikke er tydelig hvorfor de ikke kan brukes. Vurder om handlingen heller bør skjules, eller om det bør forklares hva som mangler for at knappen skal bli aktiv. ### Tilpass bredde til innhold og kontekst[​](#tilpass-bredde-til-innhold-og-kontekst "Direct link to Tilpass bredde til innhold og kontekst") Knapper bør som hovedregel tilpasse seg innholdet sitt. Full bredde kan brukes der det gir mening — for eksempel på mobil — men bør brukes bevisst for å unngå at alle handlinger fremstår som like viktige. ## Universell utforming[​](#universell-utforming "Direct link to Universell utforming") ### Hva du selv må sørge for[​](#hva-du-selv-må-sørge-for "Direct link to Hva du selv må sørge for") * **Ikonknapper må ha `aria-label`** — knapper uten synlig tekst er meningsløse for skjermlesere uten en beskrivende label. Labelen skal beskrive handlingen, ikke ikonet: `aria-label="Slett melding"`, ikke `aria-label="Søppelkasse-ikon"`. * **Gi `loadingLabel` ved loading-tilstand** — uten denne er knappen anonym for skjermlesere mens den laster. * **Unngå disabled som standard** — disabled-knapper sier ikke brukeren hva som mangler. Der det er mulig, la knappen være aktiv og gi tydelig feilmelding ved innsending. * **Bruk riktig element** — bruk ` Avbryt ``` ## Relatert[​](#relatert "Direct link to Relatert") * [Typografi](/docs/grunnleggende/typografi.md) — skriftstørrelser brukt i knapper * [Spacing](/docs/grunnleggende/tokens/spacing.md) — padding-tokens for sm/md/lg * [Farger](/docs/retningslinjer/farger/.md) — fargetokens for varianter og danger * [Deaktiverte tilstander](/docs/monstre-og-maler/deaktiverte-tilstander.md) — retningslinjer for når disabled er riktig valg --- # Card Card er én ting: en avgrenset, selvstendig innholdsenhet med fast ramme og bakgrunn. Et kort kan være rent statisk (en beholder for innhold) eller klikkbart (navigerer til en side eller utfører en handling). ## Egnet til[​](#egnet-til "Direct link to Egnet til") * Gruppere relatert innhold i en visuelt avgrenset enhet * Klikkbare inngangsporter til detaljsider (f.eks. en konto, et produkt) * Lister av likeverdige valg der hele flaten skal være trykkbar ## Uegnet til[​](#uegnet-til "Direct link to Uegnet til") * Som erstatning for en knapp i et skjema — bruk [Button](/docs/komponenter/button.md) * Dypt nøstede interaktive elementer inni et klikkbart kort (ugyldig HTML) * Når innholdet ikke hører naturlig sammen — da skaper kortet falsk gruppering * Kun en flate å gruppere eller skille ut flere elementer på, uten avgrensning eller klikk — bruk [Surface](/docs/komponenter/surface.md) ## Statisk vs. klikkbart — og hvorfor det er synlig på mobil[​](#statisk-vs-klikkbart--og-hvorfor-det-er-synlig-på-mobil "Direct link to Statisk vs. klikkbart — og hvorfor det er synlig på mobil") Et klikkbart kort må se annerledes ut enn et statisk kort **uten** at man trenger å peke på det. På desktop kan klikkbarhet antydes med hover, men hover finnes ikke på touch. Derfor bærer det klikkbare kortet sin affordanse i hviletilstand: * **Chevron (›)** — et eksplisitt «dette gjør noe»-signal, synlig hele tiden. Dette er hovedsignalet: en form, ikke bare en farge, så det holder også kontrastkravet. * **Hover** — på desktop får kortet en bakgrunns-tint når du peker på det. * **Pressed-state** — ved trykk får kortet en tint, som bekrefter klikket på touch. * **Fokusring** — synlig for tastaturbrukere via `:focus-visible`. Du aktiverer klikkbart kort ved å sette `href` (navigasjon → ``) eller `onClick` (handling → ` ``` ### Eget chevron-ikon[​](#eget-chevron-ikon "Direct link to Eget chevron-ikon") Klikkbart kort viser `chevron_right` som standard. Sett `chevronIcon` for å bytte ikon. Skal kortet faktisk åpne lenken i ny fane, setter du `openInNewTab` (som gir `target="_blank"`) — og bytter chevronen til `open_in_new` som visuelt signal. I ren HTML setter du `target`/`rel` og chevron-ikonet selv. Result Loading... Kode Live Editor Reset ``` Åpner i ny fane Lenken åpnes i ny fane, og chevronen viser et eksternt-lenke-ikon. ``` Result Loading... Kode Live Editor Reset ```

    Åpner i ny fane

    Lenken åpnes i ny fane, og chevronen viser et eksternt-lenke-ikon.

    ``` ## Retningslinjer[​](#retningslinjer "Direct link to Retningslinjer") ### Skill statisk og klikkbart tydelig[​](#skill-statisk-og-klikkbart-tydelig "Direct link to Skill statisk og klikkbart tydelig") Et klikkbart kort skal alltid bære en chevron — ikke gjør et statisk kort trykkbart uten å gi det dette signalet. Skill aldri klikkbart fra statisk kun på farge eller kantlinje; det er for svakt på touch og bryter med kontrastkrav. Chevronen er en form, ikke bare en farge, og holder derfor kontrastkravet. ### Bruk riktig semantikk: navigasjon vs. handling[​](#bruk-riktig-semantikk-navigasjon-vs-handling "Direct link to Bruk riktig semantikk: navigasjon vs. handling") Bruk `href` når kortet fører brukeren til en ny side, og `onClick` når kortet utfører en handling i grensesnittet. Dette samsvarer med brukerens forventning og gir riktig skjermleser-annonsering («lenke» vs. «knapp»). ### Ikke nøst interaktive elementer[​](#ikke-nøst-interaktive-elementer "Direct link to Ikke nøst interaktive elementer") Et klikkbart kort er allerede en lenke eller knapp. Å plassere knapper eller lenker inni gir ugyldig, nøstet interaktivt innhold. Trenger du flere handlinger, bruk et statisk kort med egne knapper i stedet — ikke gjør hele flaten klikkbar. ### Gi nok klikkflate[​](#gi-nok-klikkflate "Direct link to Gi nok klikkflate") Hele kortet er trykkbart. Gi kortet tilstrekkelig `padding` slik at klikkflaten blir komfortabel på touch (sikt mot minst 44×44 px). ## Universell utforming[​](#universell-utforming "Direct link to Universell utforming") ### Hva du selv må sørge for[​](#hva-du-selv-må-sørge-for "Direct link to Hva du selv må sørge for") * **Velg `href` eller `onClick` bevisst** — navigasjon skal være ``, handling skal være ` ``` ## Relatert[​](#relatert "Direct link to Relatert") * [Button](/docs/komponenter/button.md) — for primære og sekundære handlinger i en visning * [RadioGroup](/docs/komponenter/skjema/radio-group.md) — standard radiogruppe uten chip-styling * [Typografi](/docs/grunnleggende/typografi.md) — skriftstørrelser brukt i chips * [Spacing](/docs/grunnleggende/tokens/spacing.md) — padding-tokens for sm/md --- # Button chip En button chip fungerer som en knapp og trigger en handling — for eksempel et hurtigvalg, et forslag eller et filter brukeren aktiverer. Den har ingen vedvarende valgt tilstand. ## Kom i gang[​](#kom-i-gang "Direct link to Kom i gang") Result Loading... Kode Live Editor Reset ``` ``` Result Loading... Kode Live Editor Reset ``` Chip label ``` ## Eksempler[​](#eksempler "Direct link to Eksempler") ### Gruppe[​](#gruppe "Direct link to Gruppe") Button chips gir mest verdi i grupper. Da blir det tydelig at de hører sammen og at det finnes flere valg. Result Loading... Kode Live Editor Reset ``` ``` Result Loading... Kode Live Editor Reset ``` Alle Sparing Lån Forsikring ``` ### Størrelser[​](#størrelser "Direct link to Størrelser") Chip finnes i to størrelser: `md` (standard) og `sm`. Result Loading... Kode Live Editor Reset ``` ``` Result Loading... Kode Live Editor Reset ``` Small Medium (standard) ``` ### Deaktivert[​](#deaktivert "Direct link to Deaktivert") Result Loading... Kode Live Editor Reset ``` ``` Result Loading... Kode Live Editor Reset ``` Chip label ``` Vurder om brukeren i stedet bør se en forklaring på hvorfor valget ikke er tilgjengelig. ### Som lenke[​](#som-lenke "Direct link to Som lenke") Bruk `as="a"` når chipen navigerer til en URL. Den beholder chip-styling, men rendres som ``. Result Loading... Kode Live Editor Reset ``` Gå til sparebank1.no ``` Result Loading... Kode Live Editor Reset ``` Gå til sparebank1.no ``` ## Universell utforming[​](#universell-utforming "Direct link to Universell utforming") ### Hva du selv må sørge for[​](#hva-du-selv-må-sørge-for "Direct link to Hva du selv må sørge for") * **Gi chipen en kort og tydelig label** — teksten er det tilgjengelige navnet. Den skal beskrive handlingen. * **Bruk chips i grupper** — en enkeltstående chip gir lite kontekst. Presenter relaterte chips sammen. * **Bruk riktig element** — ` Sparing ``` ## Relatert[​](#relatert "Direct link to Relatert") * [Chip](/docs/komponenter/chip.md) — oversikt over chip-familien og felles retningslinjer * [Removable chip](/docs/komponenter/chip/removable.md) — chip som representerer et aktivt valg og kan fjernes * [Radio chip](/docs/komponenter/chip/radio.md) — gruppe der brukeren velger nøyaktig ett alternativ * [Button](/docs/komponenter/button.md) — for primære og sekundære handlinger i en visning --- # Checkbox chip En checkbox chip er en gruppe chips der brukeren kan velge **ett eller flere** alternativer samtidig — som kompakte filter- eller preferansevalg. Hvert valg er uavhengig av de andre. Hver chip har en indikator til venstre for teksten: en tom firkant når den ikke er valgt, og en fylt firkant med hake når den er valgt. I tillegg fylles den valgte pillen med en lys aksentfarge og får aksent-kant, slik at valgt tilstand kommuniseres med mer enn farge. Checkbox chip gjenbruker checkbox-gruppe-semantikken: gruppen får `role="group"`, og hver chip er et eget tab-stopp som toggles med Space. Gi alltid gruppen en beskrivende `legend`. ## Kom i gang[​](#kom-i-gang "Direct link to Kom i gang") Result Loading... Kode Live Editor Reset ``` Velg interesser
    ``` Result Loading... Kode Live Editor Reset ``` ``` ## Eksempler[​](#eksempler "Direct link to Eksempler") ### Liten størrelse[​](#liten-størrelse "Direct link to Liten størrelse") Result Loading... Kode Live Editor Reset ``` Velg interesser
    ``` Result Loading... Kode Live Editor Reset ``` ``` ## Universell utforming[​](#universell-utforming "Direct link to Universell utforming") ### Hva du selv må sørge for[​](#hva-du-selv-må-sørge-for "Direct link to Hva du selv må sørge for") * **Gi checkbox chip-gruppen en beskrivende `legend`** — det er gruppens tilgjengelige navn. Bruk riktig språk; ingen hardkodet fallback. * **Bruk checkbox chip når flere valg kan kombineres** — skal brukeren kun velge ett alternativ, er det feil semantikk. Bruk radio chip i stedet. * **Gi hvert valg en kort og tydelig label** — label-teksten er det tilgjengelige navnet for valget. * **Ikke stol på farge alene** — ikke overstyr stylingen slik at kun fargen skiller valgt fra ikke-valgt. ### Hva komponenten gjør automatisk[​](#hva-komponenten-gjør-automatisk "Direct link to Hva komponenten gjør automatisk") * **Gruppe-semantikk** — checkbox chip bygger på ``, som setter `role="group"`, kobler `legend` som tilgjengelig navn, propagerer `name` til alle valg og kobler hver label til sin input. Hver chip er et eget tab-stopp. * **Valgt tilstand** kommuniseres med fylt firkant-indikator (hake), aksent-kant og fyll — ikke farge alene — og eksponeres programmatisk via native `aria-checked`. * **Fokusindikator** via `:focus-visible` som følger pill-formen. #### Tastaturnavigasjon | Tast | Handling | | ----------- | ---------------------------------------------- | | `Tab` | Flytter fokus til neste chip i gruppen | | `Shift+Tab` | Flytter fokus til forrige chip | | `Space` | Toggler valgt tilstand på chipen som har fokus | #### Skjermleser * Gruppe ved fokus: "\[legend], gruppe" * Hvert valg: "\[label], avkryssingsboks, avkrysset/ikke avkrysset" * Deaktivert valg: "\[label], avkryssingsboks, deaktivert" ### WCAG-kriterier[​](#wcag-kriterier "Direct link to WCAG-kriterier") Sist gjennomgått: 2026-06-29 — alle 56 WCAG 2.2-kriterier vurdert WCAG-kriterier8 ditt ansvar · 16 håndtert · 39 ikke relevant · 0 ikke på plass Ditt ansvar (8) | Kriterium | Nivå | Hva du må gjøre | | ------------------------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **1.3.1** Informasjon og relasjoner | A | **Gi checkbox chip-gruppen en beskrivende legend.** Checkbox chip-gruppen får sitt tilgjengelige navn fra legend (React: legend-prop; HTML: \[data-field="legend"]). Uten legend annonseres gruppen uten navn, og brukeren vet ikke hva valgene gjelder. Legend er påkrevd og må være på brukerens språk — komponenten har ingen hardkodet fallback. | | **3.3.2** Ledetekster eller instruksjoner | A | **Gi checkbox chip-gruppen en beskrivende legend.** Checkbox chip-gruppen får sitt tilgjengelige navn fra legend (React: legend-prop; HTML: \[data-field="legend"]). Uten legend annonseres gruppen uten navn, og brukeren vet ikke hva valgene gjelder. Legend er påkrevd og må være på brukerens språk — komponenten har ingen hardkodet fallback. | | **4.1.2** Navn, rolle, verdi | A | **Gi checkbox chip-gruppen en beskrivende legend.** Checkbox chip-gruppen får sitt tilgjengelige navn fra legend (React: legend-prop; HTML: \[data-field="legend"]). Uten legend annonseres gruppen uten navn, og brukeren vet ikke hva valgene gjelder. Legend er påkrevd og må være på brukerens språk — komponenten har ingen hardkodet fallback. | | **4.1.2** Navn, rolle, verdi | A | **Bruk checkbox chip når flere valg kan kombineres.** Checkbox chip er for uavhengige valg der null, ett eller flere kan være aktive samtidig. Skal brukeren kun kunne velge ett alternativ, er det feil semantikk — bruk radio chip i stedet. Hvert valg må ha en kort, beskrivende label. | | **1.3.1** Informasjon og relasjoner | A | **Bruk checkbox chip når flere valg kan kombineres.** Checkbox chip er for uavhengige valg der null, ett eller flere kan være aktive samtidig. Skal brukeren kun kunne velge ett alternativ, er det feil semantikk — bruk radio chip i stedet. Hvert valg må ha en kort, beskrivende label. | | **2.4.6** Overskrifter og ledetekster | AA | **Gi hvert valg en kort og tydelig label.** Label-teksten på hvert valg er det tilgjengelige navnet for valget. Den skal være kort og enkel å skanne — f.eks. «Sport». i18n: komponenten har ingen hardkodet fallback. | | **1.3.1** Informasjon og relasjoner | A | **Gi hvert valg en kort og tydelig label.** Label-teksten på hvert valg er det tilgjengelige navnet for valget. Den skal være kort og enkel å skanne — f.eks. «Sport». i18n: komponenten har ingen hardkodet fallback. | | **1.4.1** Bruk av farge | A | **Ikke stol på farge alene for valgt tilstand.** Valgt tilstand kommuniseres med tre samtidige signaler (fylt firkant-indikator med hake, aksent-kant og lys fyll på pillen) — ikke kun farge. Ikke overstyr dette slik at kun fargen skiller valgt fra ikke-valgt. | Håndtert av komponenten (16) | Kriterium | Nivå | Hva komponenten gjør | | ----------------------------------------------------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **1.3.1** Informasjon og relasjoner | A | Gruppen får role=group og navn fra legend via aria-labelledby. Hvert valg er native \ med label koblet via for/id. | | **1.3.2** Meningsfull rekkefølge | A | Innholdet følger naturlig lesrekkefølge i DOM. | | **1.4.1** Bruk av farge | A | Valgt tilstand kommuniseres med fylt firkant-indikator (hake), aksent-kant og fyll — ikke farge alene. | | **1.4.4** Endre tekststørrelse | AA | Relative enheter — skalerer korrekt ved 200 % zoom. | | **1.4.10** Omflyt | AA | Chips wrapper og reflower korrekt ned til 320px viewport. | | **1.4.11** Kontrast for ikke-tekstlig innhold | AA | Fokusindikator og indikator-kant oppfyller 3:1 kontrastkrav. | | **2.1.1** Tastatur | A | Native \ er fullt opererbart med tastatur: Tab flytter fokus til hver chip, Space toggler valgt tilstand. | | **2.1.2** Ingen tastaturfelle | A | Fokus kan navigeres ut av gruppen med Tab og Shift+Tab. Ingen tastaturfelle. | | **2.4.3** Fokusrekkefølge | A | Hver chip er et eget tab-stopp i naturlig DOM-rekkefølge (ingen piltast-mutex — i motsetning til radio chip). | | **2.4.7** Synlig fokus | AA | Tydelig fokusindikator via :focus-visible som følger pill-formen. | | **3.2.1** Ved fokus | A | Fokus trigger ingen kontekstendring. | | **3.2.2** Ved inndata | A | Å toggle en chip endrer kun gruppens verdi, ikke kontekst — ingen uventet navigasjon eller innsending. | | **1.4.3** Kontrast (minimum) | AA | Tekstfarge mot fill-tokens i alle tilstander. Disabled-tilstand (opacity: 0.4) er unntatt fra kravet per WCAG. | | **3.3.2** Ledetekster eller instruksjoner | A | Gruppens legend fungerer som instruksjon/etikett for valgene. | | **2.5.8** Målstørrelse (minimum) | AA | Hele pillen er klikkflate for valget. md-størrelsen gir mål godt over 24×24px. sm-størrelsen (padding-block spacing-2xs + font-size-sm) er nær minimumet; chips wrapper i en gruppe med gap mellom seg, slik at avstands-unntaket i SC 2.5.8 gjelder. Konsumenten må unngå å pakke sm-chips så tett at både mål og avstand kommer under 24px. | | **4.1.2** Navn, rolle, verdi | A | \ setter role=group på gruppen (navn fra legend via aria-labelledby), og native \ gir rolle og valgt/ikke-valgt-tilstand (aria-checked). Native disabled-attributt eksponeres til hjelpemidler. | Ikke relevant (39) | Kriterium | Nivå | Hvorfor ikke relevant | | ---------------------------------------------------------------------- | ---- | ---------------------------------------------------------------------------------------------------------------- | | **1.1.1** Ikke-tekstlig innhold | A | Firkant-/hake-indikatoren er rent dekorativ CSS uten egen markup; tilstanden formidles av native checkbox-input. | | **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 | Chipen formidler ikke instruksjoner utover label/legend. | | **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 | Ingen blinkende eller glimtende innhold. | | **2.4.1** Hoppe over blokker | A | Sidekrav — gjelder ikke enkeltkomponenter. | | **2.4.2** Sidetitler | A | Sidekrav — gjelder ikke enkeltkomponenter. | | **2.4.4** Formål med lenke (i kontekst) | A | | | **2.4.5** Flere måter | AA | Sidekrav — gjelder ikke enkeltkomponenter. | | **2.4.11** Fokus ikke skjult (minimum) | AA | Ingen sticky/overlappende elementer som kan skjule fokus. | | **2.5.1** Pekerbevegelser | A | Ingen drag-and-drop eller sveipebevegelser. | | **2.5.2** Avbryt peker | A | Native checkbox-input — nettleseren håndterer pekerinteraksjon. | | **2.5.3** Label i navn | A | Den synlige label-teksten er det tilgjengelige navnet på hvert valg. | | **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.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. | | **4.1.3** Statusmeldinger | AA | Checkbox chip genererer ingen statusmeldinger selv; en ev. feilmelding settes av konsumenten via errorMessage. | ## Props / API[​](#props--api "Direct link to Props / API") Checkbox chip er `CheckboxGroup` med `variant="chip"`. Se [CheckboxGroup](/docs/komponenter/skjema/checkbox-group.md) for full API — tabellene under viser propsene som er relevante for chip-varianten. ### `CheckboxGroup`[​](#checkboxgroup "Direct link to checkboxgroup") | Prop | Type | Standard | Beskrivelse | | -------------- | -------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ | | `variant` | `'chip'` | | Sett til `'chip'` for chip-styling | | `legend` | `string` | | **Påkrevd.** Tilgjengelig navn for gruppen. i18n — ingen fallback | | `name` | `string` | | Felles `name` for alle checkboxene. Propageres når satt | | `value` | `string[]` | | Valgte verdier (kontrollert) | | `defaultValue` | `string[]` | | Valgte verdier (ukontrollert) | | `onChange` | `ChangeEventHandler` | | Event-basert — toggl-verdien i `event.target.value`, av/på i `event.target.checked`. Lar `{...register()}` spres rett på | | `size` | `'sm' \| 'md'` | `'md'` | Størrelse — kun relevant for `variant="chip"` | | `description` | `string` | | Hjelpetekst over alternativene | | `errorMessage` | `string` | | Feilmelding — setter `aria-invalid` på gruppen | | `disabled` | `boolean` | | Deaktiverer hele gruppen | | `hideLegend` | `boolean` | | Skjuler legend visuelt, men beholder den for skjermlesere | ### `CheckboxButton`[​](#checkboxbutton "Direct link to checkboxbutton") | Prop | Type | Standard | Beskrivelse | | ---------- | --------- | -------- | -------------------------------------------------- | | `value` | `string` | | **Påkrevd.** Verdien dette valget representerer | | `label` | `string` | | **Påkrevd.** Synlig etikett. i18n — ingen fallback | | `disabled` | `boolean` | | Deaktiverer dette enkeltvalget | ## Tilpasning med CSS[​](#tilpasning-med-css "Direct link to Tilpasning med CSS") Checkbox chip gjenbruker `ix-checkbox-group`-web componenten med chip-styling aktivert via `data-variant="chip"` på host-elementet. Trenger du stylingen på HTML du setter sammen selv, kan du bruke markupen under. ### Tilgjengelige klasser og attributter[​](#tilgjengelige-klasser-og-attributter "Direct link to Tilgjengelige klasser og attributter") | Element/tilstand | Selektor / attributt | | ---------------------- | ------------------------------------------------------------------------- | | Checkbox chip (gruppe) | `ix-checkbox-group[data-variant="chip"]` — styler hver `