v13#
Note: There is no
v12release. The versionv12was accidentally published to NPM and has since been removed. Because a published version number cannot be safely reused,v12has been skipped entirely, and these breaking changes are released asv13instead.
Migration#
v13 of @dnb/eufemia contains breaking changes. As a migration process, you can simply search and replace:
Install#
To upgrade to @dnb/eufemia v13 with NPM, use:
$ npm i @dnb/eufemia@13# or$ yarn add @dnb/eufemia@13
CSS custom properties#
Typography:#
- Replace
--sb-font-size-*with--font-size-* - Replace
--sb-font-size-medium--pluswith--font-size-medium - Replace
--sb-line-height-*with--line-height-*
The font size and line height values now come from Figma brand tokens. Existing CSS variable names remain available. Carnegie's xx-large heading changes from 48px/56px to 56px/68px at the default root size. Responsive xx-large headings now use the matching line-height step: x-large on mobile and xx-large from tablet upward. Check layouts that constrain large headings, especially fixed heights and truncation.
The generated JavaScript properties exports keep their existing value format: concrete rem values for the size scale and aliases for lead.
The deprecated Sbanken-prefixed properties are still emitted. Their values differ from the generic scale, so check the rendered result when replacing them.
Tailwind#
- Replace
--text-sb-*with--text-* - Replace
--text-sb-medium--pluswith--text-medium - Replace
--leading-sb-*with--leading-*
Component changes#
Theme#
The deprecated name property and data-name attribute have been removed. Use brand and data-brand instead.
-<Theme name="carnegie">+<Theme brand="carnegie">
Replace useTheme().name with useTheme().brand. For persisted theme state, replace getTheme().name and setTheme({ name }) with getTheme().brand and setTheme({ brand }).
VisibilityByTheme also matches on the theme object, so replace name there too:
-<VisibilityByTheme visible={[{ name: 'sbanken' }]}>+<VisibilityByTheme visible={[{ brand: 'sbanken' }]}>
With name removed, TypeScript reports it as an unknown property here. Plain JavaScript gets no such warning — the filter simply stops matching, and the content silently disappears.
The deprecated size property, ThemeSizes type, data-size attribute, and eufemia-theme__size--* CSS classes have also been removed. Use density, ThemeDensities, data-density, and eufemia-theme__density--* instead.
-<Theme size="basis">+<Theme density="basis">
The deprecated VisibilityByTheme.Name component has been removed. Use VisibilityByTheme.Brand instead.
-<VisibilityByTheme.Name />+<VisibilityByTheme.Brand />
SidebarMenu#
Replace breakpoint with drawerAt on SidebarMenu.ResponsiveProvider. The deprecated breakpoint alias is removed in v13.
SidebarMenu.Header now uses text for its label and children for the nested menu items. Move the previous label children to text. The deprecated, no-effect headingLevel compatibility property is removed in v13 because Header is a visual menu label rather than a semantic page heading.
-<SidebarMenu.Header headingLevel={3}>Accounts</SidebarMenu.Header>+<SidebarMenu.Header text="Accounts">+ <SidebarMenu.Item id="overview" text="Overview" />+</SidebarMenu.Header>
Flex#
Flex now uses native CSS gap and renders React children unchanged. The following legacy migration APIs are deprecated:
Flex.withChildren_supportsSpacingPropswrapChildrenInSpacelayoutEngine="legacy"
Custom components#
The _supportsSpacingProps marker is no longer needed. A custom component becomes a flex item through its rendered root, so nothing needs to opt it in to the layout. When the component should accept spacing properties, apply them to its root with useSpacing so an author can still adjust the spacing per instance.
Before (v11):
import { clsx } from 'clsx'import { useSpacing } from '@dnb/eufemia/components/space/SpacingUtils'function MyComponent({ className, ...props }) {const params = useSpacing(props, {...props,className: clsx('my-component', className),})return <div {...params} />}// Opted the component in to receive spacing from Flex.Container.MyComponent._supportsSpacingProps = true
After (v13):
import { clsx } from 'clsx'import { useSpacing } from '@dnb/eufemia/components/space/SpacingUtils'function MyComponent({ className, ...props }) {const params = useSpacing(props, {...props,className: clsx('my-component', className),})return <div {...params} />}
For a component that already applied spacing to its root, deleting the marker is the only change. The rendered <div> is now a flex item automatically, and useSpacing keeps the component's own top, right, bottom, and left props working — in CSS mode those values participate in pairwise spacing and may replace the adjacent container gap. If a component did not previously apply spacing to its root, adopt useSpacing as shown so authors can keep adjusting spacing per instance. A component that never needs per-instance spacing can simply drop the marker and receive the container gap.
Wrapper components#
Flex.withChildren is deprecated. It never hoisted a wrapper's children into the outer container's flex line. When the HOC marked a wrapper, Flex.Container automatically injected a nested Flex.Container inside the wrapper's root — inheriting the outer container's props — and laid the wrapper's children out there. The rendered DOM was already outer container → wrapper root → inner container. To keep that layout in v13, render the inner Flex.Container yourself.
Before (v11):
import { Flex } from '@dnb/eufemia'// The HOC marked the wrapper, so Flex.Container injected a nested// Flex.Container inside it to lay out the wrapper's children.const Wrapper = Flex.withChildren(({ children }) => <div>{children}</div>)render(<Flex.Container direction="vertical"><Item /><Wrapper><Item /><Item /></Wrapper><Item /></Flex.Container>)
After (v13):
import { Flex } from '@dnb/eufemia'// Render the inner Flex.Container yourself — this is the container// the HOC used to inject automatically.function Wrapper({ children }) {return (<div><Flex.Container direction="vertical">{children}</Flex.Container></div>)}render(<Flex.Container direction="vertical"><Item /><Wrapper><Item /><Item /></Wrapper><Item /></Flex.Container>)
The DOM structure is unchanged from v11 — a wrapper root containing a nested Flex.Container. The only difference is that you now provide that inner container explicitly and set its own props (direction, gap, divider, …) instead of inheriting them from the outer container. If a wrapper renders no DOM of its own — for example a Fragment, a context provider, or another transparent component — its children already become direct flex items of the outer container and need no inner Flex.Container.
When using divider="line" or divider="line-framed", the CSS engine paints the divider without rendering <hr> elements. This removes the corresponding separator roles from the accessibility tree. If a divider conveys semantic separation, render explicit Hr elements instead of relying on the divider property.
The previous child-inspection engine remains temporarily available during migration:
<Flex.Container layoutEngine="legacy">...</Flex.Container>
Do not use the deprecated APIs for new integrations. See the Flex.Container migration guidance for details.
Accordion#
- Replace
idwithconnectedToonAccordion.Contentwhen connecting to a standalone tertiary button.
Autocomplete#
The individual search-related props are deprecated in favor of a single search object:
disableFilter→search.filterdisableReorder→search.reorderdisableHighlighting→search.highlightsearchNumbers→search.numberssearchInWordIndex→search.matchInsideWordsFromsearchMatch→search.match
Note that the disable* props invert, so a disabled feature becomes false:
-<Autocomplete- disableFilter- disableReorder- disableHighlighting- searchNumbers- searchInWordIndex={4}- searchMatch="starts-with"-/>+<Autocomplete+ search={{+ filter: false,+ reorder: false,+ highlight: false,+ numbers: true,+ matchInsideWordsFrom: 4,+ match: 'starts-with',+ }}+/>
Modal, Dialog and Drawer#
- Replace
closeButtonAttributeswithcloseButtonProps.
-<Drawer closeButtonAttributes={{ text: 'Custom text' }} />+<Drawer closeButtonProps={{ text: 'Custom text' }} />
- Replace
triggerAttributeswithtriggerProps.
-<Dialog triggerAttributes={{ text: 'Open', variant: 'primary' }} />+<Dialog triggerProps={{ text: 'Open', variant: 'primary' }} />
- The
ModalTriggerAttributestype has been removed. UseButtonPropsfrom@dnb/eufemiainstead.
InfoCard#
Replace InfoCard with Card.Info and compose its content as children. Card.Info supplies the card surface, shadow, and padding. See Card.Info for layout, sizing, interaction, and dismissal guidance.
Before:
<InfoCardtitle="Savings tip"text="Save a little every month."acceptButtonText="Start saving"onAccept={onAccept}/>
After:
<Card.Info><Flex.Stack gap="x-small"><P size="small" weight="medium">Savings tip</P><P size="small">Save a little every month.</P></Flex.Stack><Button variant="secondary" onClick={onAccept}>Start saving</Button></Card.Info>
- Replace
textwith paragraph children. Use heading children or Card'stitleproperty for the title. - Replace
icon,src,alt, andimgPropswith IconPrimary, Img, or other graphic children. Include appropriate alternative text. - Replace accept and close button props, including the
*ButtonAttributesaliases, with explicit Button children. For a top-corner close control, renderCard.Info.CloseButtonas a direct Card.Info child and pass the dismissal handler asonClick. - Replace
centeredwith your content layout, for exampleFlex.Stack align="center"and centered text. Wrap loading content inProvider skeleton. - Remove
stretchand control width through the containing layout. Other Card properties, including spacing anddropShadow, can be passed directly to Card.Info.
Img#
- Replace
imgClasswithimageClassName. - The
elementprop is deprecated. Keep the defaultfigurewrapper and usefigurePropsto pass native properties to it.
-<Img src="image.png" alt="Description" imgClass="image-class" />+<Img src="image.png" alt="Description" imageClassName="image-class" />
Popover#
- Replace
triggerAttributeswithtriggerProps.
-<Popover triggerAttributes={{ 'aria-haspopup': 'menu' }} />+<Popover triggerProps={{ 'aria-haspopup': 'menu' }} />
- The
PopoverTriggerAttributestype has been removed. UsetriggerPropsinstead.
Typography#
- Replace
<Typography.Provider>with<Typography.Context>.
-<Typography.Provider/>+<Typography.Context/>
ScrollView#
- The deprecated
ScrollViewexport from@dnb/eufemia/fragmentshas been removed. Import it from the main package instead.
-import { ScrollView } from '@dnb/eufemia/fragments'+import { ScrollView } from '@dnb/eufemia'
Field.Name.Company#
- The
onBlurValidatorproperty now only accepts aCompanyNameValidator, and itsvalidatorsno longer includenameValidator. UsecompanyValidatorinstead.
-import type { NameValidator } from '@dnb/eufemia/extensions/forms/Field/Name'+import type { CompanyNameValidator } from '@dnb/eufemia/extensions/forms/Field/Name'-const myValidator: NameValidator = (value, { validators }) => {- return [validators.nameValidator]+const myValidator: CompanyNameValidator = (value, { validators }) => {+ return [validators.companyValidator]}