Migrering
Veiledning for konsumenter som oppgraderer @entur/*-pakker for React 18+
Alle @entur/*-pakker krever nå React 18.0.0 eller høyere som peer dependency. Dette er en breaking change.
Automatisk migrering med Claude Code
Designsystemet tilbyr en migreringsguide skrevet for AI-kodeagenter. Lim inn meldingen under i Claude Code – ingen installasjon eller oppsett kreves. Den fungerer også i andre agenter som kan hente URL-er, som GitHub Copilot og Cursor.
Oppgrader @entur/*-pakkene i dette prosjektet til siste major-versjon.
Les og følg denne migreringsguiden:
https://raw.githubusercontent.com/entur/design-system/main/skills/migrate-react-18/SKILL.md
Relative lenker i guiden (f.eks. references/breaking-changes.md) ligger under
https://raw.githubusercontent.com/entur/design-system/main/skills/migrate-react-18/Breaking changes
Peer dependencies
Alle pakker krever nå:
- react: >=18.0.0 (tidligere >=16.8.0)
- react-dom: >=18.0.0 (tidligere >=16.8.0)
ESM exports
Alle @entur/*-pakker har nå et strengt exports-felt i package.json. Dette gir bundlere korrekt ESM/CJS-oppløsning, men begrenser hvilke importstier som fungerer.
Hva har endret seg
- Hver pakke har nå "exports" med eksplisitte types-, import-, require- og default-betingelser.
- Deep imports til dist/ som ikke er eksplisitt listet, vil feile.
- CSS kan importeres via en ren ./styles-subpath.
Hva konsumenter må gjøre
Fjern custom alias/resolve-konfigurasjon – exports-feltet håndterer dette nativt.
Fiks dype dist/-imports:
// ❌ Før (vil feile)
import { Button } from '@entur/button/dist/Button';
// ✅ Etter
import { Button } from '@entur/button';CSS-imports – både gammel og ny sti fungerer:
// ✅ Ny (anbefalt)
import '@entur/button/styles';
// ✅ Fungerer fortsatt
import '@entur/button/dist/styles.css';@entur/tokens stil-imports:
// ✅ Ny (anbefalt)
@use '@entur/tokens/styles/base.scss' as *;
@use '@entur/tokens/styles/semantic.scss' as *;
// ✅ Fungerer fortsatt
@use '@entur/tokens/dist/base.scss' as *;
@use '@entur/tokens/dist/semantic.scss' as *;@entur/utils SCSS-imports:
// ✅ Ny (anbefalt)
@use '@entur/utils/styles/breakpoints' as breakpoint;
@use '@entur/utils/styles/color-utils' as util;
// ✅ Fungerer fortsatt
@use '@entur/utils/dist/breakpoints.scss' as breakpoint;
@use '@entur/utils/dist/color-utils.scss' as util;@entur/modal
Intern implementasjon er migrert fra @reach/dialog (utdatert) til det native HTML-elementet <dialog>. Dette fjerner alle tredjepartsavhengigheter for modal.
Hva har endret seg internt
- @reach/dialog → Nativt <dialog>-element med showModal() / close()
- Fokusfelle håndteres nå nativt av nettleseren (innebygd i <dialog>)
- Fokusrestaurering ved lukking håndteres nativt
- Bakgrunnsstyling bruker ::backdrop pseudo-element i stedet for en egen overlay-div
- Scroll-lås bruker html:has(dialog[open]) CSS i stedet for JavaScript
Breaking changes
- onDismiss er nå påkrevd på Modal. Native <dialog> tillater alltid lukking via Escape – onDismiss sikrer at parent-state holdes synkronisert.
- Ny showCloseButton-prop (default: true) – styrer om lukkeknappen vises øverst til høyre.
Hva konsumenter må gjøre
- Legg til onDismiss hvis det mangler – det er nå en påkrevd prop.
- CSS som målretter <div>-overlay – oppdater til å målrette <dialog> eller bruk klassen .eds-modal__overlay.
- Fjern referanser til data-reach-dialog-*-attributter.
Hva er bevart
- Modal med open, onDismiss, size, title, closeLabel, closeOnClickOutside, initialFocusRef, align
- ModalOverlay, ModalContent og Drawer – alle props bevart
- Fokusfelle, fokusrestaurering, Escape-lukking og klikk-utenfor fungerer som før
- Alle CSS-klassenavn (eds-modal__*, eds-drawer__*) er uendret
@entur/tab
Intern implementasjon er migrert fra @reach/tabs (utdatert) til en nativ ARIA-implementasjon uten tredjepartsavhengigheter.
Hva har endret seg internt
- @reach/tabs → Nativ ARIA-implementasjon (null avhengigheter)
- Tab-tilstand styres nå via React Context (TabsContext)
- ARIA-attributter (role, aria-selected, aria-controls, aria-labelledby) settes direkte
- Tastaturnavigasjon (ArrowLeft, ArrowRight, Home, End) er implementert nativt i TabList
Hva er bevart
- Tabs med index, defaultIndex, onChange, as (kontrollert og ukontrollert)
- TabList, Tab, TabPanel og TabPanels – alle props bevart
- Tastaturnavigasjon, ARIA-roller og alle CSS-klassenavn (eds-tabs, eds-tab, eds-tab-list osv.)
Hva konsumenter må gjøre
- Fjern data-reach-*-selektorer – erstatt med .eds-tab, .eds-tab-list, .eds-tab-panel, eller rolle-selektorer ([role="tab"] osv.).
- Fjern ikke-standard props – typer er nå strengere. Alle standard HTML-attributter fungerer fortsatt.
- Ikke hardkod genererte ID-er i tester – bruk aria-controls/aria-labelledby for å finne tilknyttede elementer.
Nye funksjoner
- keepMounted-prop på TabPanels – beholder alle paneler i DOM med hidden-attributtet.
- SSR-kompatibel – useId() produserer stabile ID-er mellom server og klient.
- aria-label og aria-labelledby er nå eksplisitt typet på TabList.
@entur/expand
Intern implementasjon er migrert fra react-collapse (ikke vedlikeholdt siden 2021) til en CSS grid-animasjon uten avhengigheter.
Breaking changes – innhold forblir i DOM når det er lukket
Tidligere ble lukket innhold fjernet fra DOM. Nå forblir lukket innhold i DOM, men skjules med aria-hidden="true" og inert. For å gjenopprette gammel oppførsel:
// Gammel oppførsel: innhold fjernes fra DOM når det lukkes
<ExpandablePanel unmountOnClose={true} title="...">
{children}
</ExpandablePanel>Dette påvirker også SideNavigationGroup i @entur/menu.
Nye props
- ExpandablePanel: open, onToggle (kontrollert modus), unmountOnClose
- ExpandableText: unmountOnClose
- AccordionItem: unmountOnClose
- Accordion: openId, onToggle, defaultOpenId (kontrollert modus)
- BaseExpand: unmountOnClose
Alle expand-komponenter støtter nå ref-forwarding via React.forwardRef.
Hva konsumenter må gjøre
- De fleste konsumenter trenger ingen endringer – ny standardoppførsel er bedre for tilgjengelighet og ytelse
- Hvis du er avhengig av at lukket innhold fjernes fra DOM, legg til unmountOnClose={true}
- For kontrollert accordion-oppførsel kan du nå bruke openId og onToggle på Accordion
@entur/layout
LayoutWrapper fjernet
LayoutWrapper er fjernet. Bruk Grid fra @entur/layout/beta direkte:
// ❌ Før
import { LayoutWrapper } from '@entur/layout';
<LayoutWrapper>{children}</LayoutWrapper>
// ✅ Etter
import { Grid } from '@entur/layout/beta';
<Grid
templateColumns={{
base: 'repeat(4, 1fr)',
m: 'repeat(8, 1fr)',
lg: 'repeat(12, 1fr)',
}}
columnGap={{ base: 's-m', m: 'm-l' }}
>
{children}
</Grid>Responsive breakpoint-nøkler endret
Beta Grid bruker nye responsive breakpoint-nøkler:
- sm → base
- md → m
- lg → lg (uendret)
- xl → xl (uendret)
// ❌ Før
<Grid.Item colSpan={{ sm: '1 / -1', md: '1 / -1', lg: '3 / -3' }}>
// ✅ Etter
<Grid.Item colSpan={{ base: '1 / -1', m: '1 / -1', lg: '3 / -3' }}>@entur/utils
useRandomId er avviklet
useRandomId fra @entur/utils er nå avviklet (deprecated). React 18 tilbyr useId() nativt. Erstatt slik:
// ❌ Før
import { useRandomId } from '@entur/utils';
const id = useRandomId('eds-my-component');
// ✅ Etter
import { useId } from 'react';
const id = `eds-my-component${useId()}`;useRandomId fungerer fortsatt (den bruker useId() internt), men vil bli fjernet i en fremtidig major-versjon.
Tredjepartsavhengigheter
Fjernede avhengigheter
- @reach/dialog → Erstattet av nativt <dialog>-element
- @reach/tabs → Erstattet av nativ ARIA-implementasjon
- react-collapse → Erstattet av CSS grid-animasjon