Skip to main content

PhoneNumberField

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 brukeren skriver, under én felles label. De to er uavhengige felt: hver kan ha sin egen feilmelding, og i React bindes de som to separate React Hook Form-felt.

Sammensatt komponent

PhoneNumberField reimplementerer ingenting selv: den grupperer en Combobox (landkode) og et TextField med formatering (nummer). All filtrering, virtual focus, formatering og form-synk kommer uendret fra de to.

Egnet til

  • Skjemaer der brukeren skal oppgi telefonnummer med landkode
  • Tjenester som møter kunder fra flere land (velg land fremfor å kunne tallkoden)
  • Situasjoner der landkode-feltet ikke bør se like «tungt» ut som nummeret

Uegnet til

  • Rene norske nummer der landkode er unødvendig (bruk et vanlig TextField med format="phone")
  • Fri tekst / nummer som ikke skal valideres som telefon

Bruk

Laster...

Landvelgeren bruker den innebygde landlista (Norge øverst, så Norden, så alfabetisk). Skriv i nummerfeltet: det formateres til 123 45 678 mens du skriver, men onChange og form-innsending gir alltid den verdien uten mellomrom.

Eksempler

Med beskrivelse

Laster...

To felt i React Hook Form

Komponenten er to uavhengige felt: landkode og nummer. I React binder du dem med hver sin registrering, countryField og numberField, som spres rett på delfeltene. Begge indre komponenter (Combobox og TextField) er register-kompatible, så {...register()} fungerer uten lim-kode:

  • countryField={register('landkode')}: onChange får landkoden (uten +) i event.target.value.
  • numberField={register('tlf')}: onChange får den nummer-verdien (uten separatorer) i event.target.value.

Feilmeldinger er per felt: errorMessage vises under nummeret, countryErrorMessage under landvelgeren. defaultCountryCode gir et forhåndsvalgt land når registreringen ikke selv seeder verdien.

function Skjema() {
const { register, handleSubmit, formState: { errors } } = useForm();
return (
<Form onSubmit={handleSubmit(console.log)} noValidate>
<PhoneNumberField
label="Mobilnummer"
description="Norsk format: 123 45 678"
countryLabel="Landkode"
numberLabel="Telefonnummer"
noHitsText="Ingen treff"
toggleLabel="Vis landkoder"
countryField={register('landkode', { required: 'Velg landkode' })}
numberField={register('tlf', { pattern: { value: /^\d{8}$/, message: 'Åtte siffer' } })}
errorMessage={errors.tlf?.message}
countryErrorMessage={errors.landkode?.message}
/>
</Form>
);
}

Å bytte land reformaterer ikke nummeret. Formatet er uavhengig av valgt land. For kontrollert bruk uten RHF: bind hvert delfelt manuelt via numberField/countryField ({ name, onChange, onBlur, ref }), eller bruk <Controller>.

Egen landliste

Utelates countries fyller web-komponenten inn den innebygde standardlista i språket fra locale (nb | nn | en). Send inn din egen countries for å begrense eller utvide: samme form som Combobox-options (value = landkode, label = kallekode +kode (vises som valgt verdi), description = landnavn). I ren HTML tilsvarer dette data-countries med en JSON-array av samme form.

Laster...

Engelsk landliste

Laster...

Med feilmelding

Laster...

Feilene er uavhengige: errorMessage vises under nummeret, countryErrorMessage under landvelgeren. Utelat den ene for å vise feil kun på det andre feltet.

Deaktivert

Laster...

disabled propageres til både landvelgeren og nummerfeltet.

Retningslinjer

La brukeren velge land, ikke skrive tallkode

Ingen skal måtte huske at Sverige er +46. I lista står kallekoden som primærtekst med landnavnet under, og brukeren kan søke på begge. Da blir verdien i det smale landfeltet kort og entydig (+47), mens landnavnet er der som kontekst i lista.

Ikke bruk emoji-flagg

Windows viser dem som «NO» og «SE», skjermlesere leser dem ulikt, og i liten størrelse er Norge og Island samme flagg. Komponenten er derfor laget uten flagg: kallekode og landnavn som tekst oppfører seg likt i alle tjenester.

Gjør nummerfeltet bredere enn landvelgeren

Er de to feltene like brede, ser de ut som to like felt, og brukeren begynner å skrive nummeret i det første. Bredden er det som viser hvilket felt som er hovedfeltet.

Send eget format for andre land enn Norge

Standarden er norsk 8-sifret (123 45 678) uansett hvilket land som er valgt. Andre nummerlengder krever at du sender inn numberFormat/numberFormatPattern. Formateringen er bare visuell: verdien som sendes, er alltid rå og uten mellomrom.

Universell utforming

Gruppe med felles navn

<ix-phone-number-field> setter role="group" og kobler den felles labelen (data-field="legend") via aria-labelledby. Skjermlesere annonserer de to feltene som én gruppe med et felles navn. De to kontrollene beholder sin egen rolle, navn og verdi. Combobox følger ARIA APG combobox-mønsteret, nummerfeltet er en native input.

Feltets formål eksponeres (1.3.5)

Web-komponenten stamper nummerfeltet med type="tel", inputmode="numeric" og autocomplete="tel-national" (når de mangler) slik at mobilt tastatur viser tall, og nettleser/hjelpemidler kan autofylle telefonnummer.

Feilmelding per felt annonseres

Hvert felt eier sin egen feilmelding. I React setter errorMessage feil på nummerfeltet og countryErrorMessage på landvelgeren. Hvert indre ix-field/ix-combobox kobler meldingen via aria-describedby, setter aria-invalid="true" på sin egen input, og annonserer polite via aria-live (avbryter ikke brukeren). I ren HTML kan du fortsatt legge en felles gruppe-feil i [data-field="error"] direkte på host.

Fokusrekkefølge og tastatur

Tab flytter fokus fra landvelger til nummerfelt (samme som leserekkefølgen). Landvelgeren er fullt tastaturopererbar (piltast/Enter/Escape), nummerfeltet er et vanlig tekstfelt.

Send inn oversatt tekst (i18n)

label, countryLabel, numberLabel, noHitsText (påkrevd), toggleLabel og resultsText må sendes inn på riktig språk (bokmål, nynorsk, engelsk). Det finnes ingen fallback. Den innebygde landlista lokaliseres med locale (data-locale i ren HTML), men er også fullt overstyrbar via countries (data-countries).

Tastaturnavigasjon

TastHandling
TabFlytter fokus til landvelgeren, deretter til nummerfeltet
Pil ned / Pil oppÅpner og navigerer i landlista når landvelgeren har fokus
EnterVelger markert land i landlista
EscapeLukker landlista uten å endre valg
SkrivingI landvelgeren filtrerer teksten lista; i nummerfeltet skrives telefonnummeret (formateres til 123 45 678)

Skjermleser

  • Ved fokus inn i komponenten: "[label], gruppe" — leses opp som group med legend som navn
  • Ved fokus på landvelgeren: "[countryLabel], combobox" med APG-annonsering av alternativer og antall treff
  • Hvert alternativ leses i DOM-rekkefølge: kallekoden først, så landnavnet (f.eks. «+47, Norge»). Valgt verdi som vises i landfeltet er kallekoden.
  • Ved fokus på nummerfeltet: "[numberLabel], redigering, tekst"
  • Ved feiltilstand: aria-invalid annonseres som «ugyldig» på gruppa, og feilmeldingsteksten leses opp polite via aria-live
  • Når description er satt: leses opp som del av gruppe-konteksten via aria-describedby

WCAG-kriterier

Sist gjennomgått: 2026-07-15 — alle 56 WCAG 2.2-kriterier vurdert

WCAG-kriterier9 ditt ansvar · 17 håndtert · 37 ikke relevant · 0 ikke på plass
Ditt ansvar (9)
KriteriumNivåHva du må gjøre
1.3.1 Informasjon og relasjonerASkriv beskrivende felles label. label er gruppens tilgjengelige navn (leses som legend av skjermlesere). "Mobilnummer" er bedre enn "Nummer". Den beskriver hva de to feltene til sammen samler inn — ikke handlingen.
2.4.6 Overskrifter og ledeteksterAASkriv beskrivende felles label. label er gruppens tilgjengelige navn (leses som legend av skjermlesere). "Mobilnummer" er bedre enn "Nummer". Den beskriver hva de to feltene til sammen samler inn — ikke handlingen.
3.3.2 Ledetekster eller instruksjonerASkriv beskrivende felles label. label er gruppens tilgjengelige navn (leses som legend av skjermlesere). "Mobilnummer" er bedre enn "Nummer". Den beskriver hva de to feltene til sammen samler inn — ikke handlingen.
3.3.2 Ledetekster eller instruksjonerAGi begge feltene et tilgjengelig navn. countryLabel og numberLabel er påkrevde aria-label på henholdsvis landvelgeren og nummerfeltet. Feltene har ingen egen synlig label — gruppens legend navngir helheten, mens aria-label skiller de to. "Landkode" og "Telefonnummer" på riktig språk.
4.1.2 Navn, rolle, verdiAGi begge feltene et tilgjengelig navn. countryLabel og numberLabel er påkrevde aria-label på henholdsvis landvelgeren og nummerfeltet. Feltene har ingen egen synlig label — gruppens legend navngir helheten, mens aria-label skiller de to. "Landkode" og "Telefonnummer" på riktig språk.
3.3.1 Identifikasjon av feilASkriv konkret feilmelding. errorMessage skal forklare hva brukeren må gjøre. "Skriv inn et gyldig telefonnummer" er bedre enn "Ugyldig". Komponenten viser meldingen på gruppenivå, setter aria-invalid på host og annonserer den polite — men teksten er ditt ansvar.
3.3.3 Forslag ved feilAASkriv konkret feilmelding. errorMessage skal forklare hva brukeren må gjøre. "Skriv inn et gyldig telefonnummer" er bedre enn "Ugyldig". Komponenten viser meldingen på gruppenivå, setter aria-invalid på host og annonserer den polite — men teksten er ditt ansvar.
3.1.2 Språk på deler av innholdAASend inn combobox-tekstene på riktig språk. noHitsText (påkrevd), toggleLabel og resultsText videreføres til landvelgeren og må oversettes (bokmål, nynorsk, engelsk). Den innebygde landlista lokaliseres med locale, men UI-chrome har ingen fallback.
3.3.2 Ledetekster eller instruksjonerAVurder bruk av disabled. Et deaktivert felt er vanskelig å forstå uten forklaring, og disabled bryter kontrastkravet (1.4.3 unntar disabled-elementer). Vurder om feltet heller bør forklares eller skjules.
Håndtert av komponenten (17)
KriteriumNivåHva komponenten gjør
1.3.1 Informasjon og relasjonerAix-phone-number-field setter role="group", aria-labelledby til den felles legend, og aria-describedby til description og error. De to kontrollene (ix-combobox og nummer-input) beholder sin egen ARIA.
1.3.5 Identifiser formål med inndataAANummerfeltet får autocomplete="tel-national", type="tel" og inputmode="numeric" slik at feltets formål eksponeres programmatisk og nettleser/hjelpemidler kan autofylle telefonnummer.
1.4.1 Bruk av fargeAValgt land vises som tekst — kallekoden (f.eks. +47) i landfeltet, med landnavnet som sekundær tekst i lista. Valgt-tilstand i lista markeres med checkmark (form) — ikke kun farge. Feiltilstand vises både med aria-invalid, tekstmelding og farge.
1.4.3 Kontrast (minimum)AATekst bruker --ix-color-foreground-main-default mot standard bakgrunn. Forventes å oppfylle 4,5:1. Verifiser ved egendefinerte bakgrunnsfarger.
1.4.10 OmflytAAReflower korrekt ned til 320 px: den smale landvelgeren (kun kallekode) og nummerfeltet ligger side ved side på én rad hele veien; nummerfeltet krymper (min-width: 0) i stedet for å tvinge horisontal scroll.
1.4.11 Kontrast for ikke-tekstlig innholdAAFeltenes border og fokus-indikatorer arves fra combobox.css og text-field.css (--ix-color-border-main-default / --ix-color-fill-*). Forventes å oppfylle 3:1.
1.4.12 TekstavstandAABruker relative enheter og tåler økt line-height, bokstav- og ordavstand uten tap av innhold.
2.1.1 TastaturAFullt tastaturopererbar: Tab når landvelger så nummerfelt, combobox har eget APG-tastaturmønster (piltast/Enter/Escape), nummerfeltet er en vanlig tekst-input.
2.4.3 FokusrekkefølgeAFokusrekkefølge følger DOM: landvelger før nummerfelt, som samsvarer med leserekkefølgen.
2.4.7 Synlig fokusAA:focus-visible på begge feltene gir tydelig outline (arvet fra underliggende komponenter).
2.5.5 2.5.5?Toggle-knapp, alternativer og inputfelter oppfyller minimum 44×44 px klikkflate (arvet fra combobox/text-field).
2.5.8 Målstørrelse (minimum)AAKlikkeflaten på 44×44 px oppfyller WCAG 2.2 AA-kravet (24×24 px) med god margin.
3.3.1 Identifikasjon av feilAix-phone-number-field setter aria-invalid="true" på host når errorMessage har innhold, og kobler feilmeldingen via aria-describedby.
3.3.2 Ledetekster eller instruksjonerAFelles legend + per-felt aria-label gir instruksjoner/etiketter for begge kontrollene.
3.3.3 Forslag ved feilAAerrorMessage brukes til å gi konkret feilmelding. Komponenten viser den, men teksten er konsumentens ansvar.
4.1.2 Navn, rolle, verdiArole="group" med aria-labelledby gir gruppa navn og rolle. De to kontrollene eksponerer egne roller/navn/verdier (combobox-mønster og native input).
4.1.3 StatusmeldingerAAix-phone-number-field setter aria-live="polite" på error-elementet slik at endringer i feilmeldingen annonseres uten å avbryte brukeren.
Ikke relevant (37)
KriteriumNivåHvorfor ikke relevant
1.1.1 Ikke-tekstlig innholdA
1.2.1 Bare lyd og bare video (forhåndsinnspilt)AIngen medieelementer.
1.2.2 Teksting (forhåndsinnspilt)AIngen medieelementer.
1.2.3 Synstolking eller mediealternativ (forhåndsinnspilt)AIngen medieelementer.
1.2.4 Teksting (direkte)AAIngen medieelementer.
1.2.5 Synstolking (forhåndsinnspilt)AAIngen medieelementer.
1.3.3 Sensoriske egenskaperA
1.3.4 VisningsretningAAIngen fast orientering — tilpasser seg visningsretning.
1.4.2 Styring av lydAIngen lydelementer.
1.4.4 Endre tekststørrelseAA
1.4.5 Bilder av tekstAAIngen bilder av tekst.
1.4.13 Innhold ved hover eller fokusAA
2.1.2 Ingen tastaturfelleA
2.1.4 TastatursnarveierAIngen egendefinerte tastatursnarveier.
2.2.1 Justerbar hastighetAIngen tidsbegrensede funksjoner.
2.2.2 Pause, stopp, skjulAIngen animasjon eller automatisk oppdatering.
2.3.1 Terskelverdi på tre glimtAIngen blinkende eller glimtende innhold.
2.4.1 Hoppe over blokkerASidekrav — gjelder ikke enkeltkomponenter.
2.4.2 SidetitlerASidekrav — gjelder ikke enkeltkomponenter.
2.4.4 Formål med lenke (i kontekst)AIngen lenker i komponenten.
2.4.5 Flere måterAASidekrav — gjelder ikke enkeltkomponenter.
2.4.11 Fokus ikke skjult (minimum)AAIngen sticky/overlappende elementer som kan skjule fokus.
2.5.1 PekerbevegelserAIngen drag-and-drop eller sveipebevegelser.
2.5.2 Avbryt pekerA
2.5.4 BevegelsesaktiveringAIngen bevegelsesbasert interaksjon.
2.5.6 Samtidige inndatamekanismerA
2.5.7 DrabevegelserAIngen drag-and-drop.
3.1.1 Språk på sidenASidekrav — gjelder ikke enkeltkomponenter.
3.1.2 Språk på deler av innholdAAAlt innhold er på gruppens språk; komponenten setter ikke lang på deler.
3.2.1 Ved fokusA
3.2.2 Ved inndataA
3.2.3 Konsistent navigasjonAASidekrav — gjelder ikke enkeltkomponenter.
3.2.4 Konsistent identifikasjonAASystemkrav — gjelder konsistens på tvers av sider, ikke enkeltkomponenter.
3.2.6 Konsistent hjelpASidekrav — gjelder plassering av hjelpefunksjon på tvers av sider.
3.3.4 Forhindring av feil (juridisk, økonomisk, data)AAFlytkrav — gjelder bekreftelse/reversering av transaksjoner, ikke enkeltfelter.
3.3.7 Redundant oppføringAFlytkrav — gjelder at brukeren ikke skal gjenta informasjon i en prosess.
3.3.8 Tilgjengelig autentisering (minimum)AAIkke en autentiseringskomponent.

Props / API

PhoneNumberFieldProps

PropTypePåkrevdStandardBeskrivelse
labelstringJaSynlig felles label over begge feltene (legend)
countryLabelstringJaaria-label på landvelgeren (i18n)
numberLabelstringJaaria-label på nummerfeltet (i18n)
noHitsTextstringJaTekst i landlista ved 0 treff (i18n)
descriptionstringNeiFelles hjelpetekst under label
errorMessagestringNeiFeilmelding for nummer-feltet. Setter aria-invalid på nummer-inputen når den har innhold
countryErrorMessagestringNeiFeilmelding for landkode-feltet. Uavhengig av errorMessage
placeholderstringNeiFrarådes — placeholder er et a11y-antimønster. Bruk description for hjelpetekst/format-hint i stedet
toggleLabelstringNeiaria-label på landvelgerens chevron-knapp (i18n)
resultsTextstringNeiMal for annonsering av antall treff i landlista, {n} = antall (i18n)
countryFieldFieldRegistrationNeiRHF-registrering for landkode: register('landkode'). { name, onChange, onBlur, ref } — spres på landvelgeren
defaultCountryCodestringNeiForhåndsvalgt landkode (uten +) når countryField ikke eier verdien
numberFieldFieldRegistrationNeiRHF-registrering for nummer: register('tlf'). { name, onChange, onBlur, ref } — spres på nummerfeltet
defaultValuestringNeiUkontrollert start-nummer (rå verdi) når numberField ikke eier verdien
countriesCountryOption[]Neiinnebygd listeOverstyr landlista
locale'nb' | 'nn' | 'en'Nei'nb'Språk for den innebygde standardlista
numberFormatstring | FieldFormatterNei'phone'Format for nummeret (norsk 8-sifret som standard)
numberFormatPatternstringNeiPattern-streng (0 = siffer). Alternativ til numberFormat
numberFormatLivebooleanNeiOverstyr formatterens live-modus
disabledbooleanNeiDeaktiverer begge feltene
readOnlybooleanNeiSkrivebeskytter begge feltene
requiredbooleanNeiMarkerer både landvelger og nummerfelt som påkrevd
classNamestringNeiCSS-klasse på <ix-phone-number-field>
idstringNeiid på gruppen
refRef<IxPhoneNumberField>NeiRef videresendes til <ix-phone-number-field>

FieldRegistration

Struktur-typen countryField/numberField tar. Matcher det React Hook Form register() returnerer, men er en ren struktur-type. Pakka har ingen RHF-avhengighet, så egne handlers eller en <Controller>-kobling fungerer også.

FeltTypeBeskrivelse
namestringFeltnavn ved form-innsending
onChange(event) => unknownFår et event der verdien ligger i event.target.value
onBlur(event) => unknownTouched-state / mode: 'onBlur'
refRefVideresendes til delfeltets host (landvelger / nummer-proxy)

CountryOption

Samme form som ComboboxOption. Utelates countries fyller web-komponenten inn sin innebygde standardliste (lokalisert med locale).

FeltTypeBeskrivelse
valuestringLandkoden uten + (verdien landvelgeren sender)
labelstringKallekoden, f.eks. +47 — vist som valgt verdi (primærtekst)
descriptionstringLandnavnet (sekundær tekst i lista)

Tilpasning med CSS

ElementSelektor
Rot.ix-phone-number-field (eller ix-phone-number-field)
Felt-wrapper[data-field="items"]
Landvelger-kolonne[data-field="country"]
Nummer-kolonne[data-field="number"]

Relatert