UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

776 lines (618 loc) 154 kB
--- title: 'v11' description: 'April 21, 2026' version: 11.8.3 generatedAt: 2026-07-29T16:51:35.601Z checksum: 090b7d977ba4be5e2c4c04d199a30a4048416c59f443a56985df2f80629d9c40 --- # v11 This is the migration guide for @dnb/eufemia v11. It covers all breaking changes, removals, and required code updates. > **Start here →** Follow the [Step-by-step migration procedure](#step-by-step-migration-procedure) for a structured, phase-by-phase migration workflow covering all 8 phases. The reference sections below provide details for each step. **How to use this guide:** Start with the [Step-by-step migration procedure](#step-by-step-migration-procedure) for the ordered workflow. Reference the [per-component sections](#components) to find individual property renames for a specific component. Check [Silent failures TypeScript won't catch](#silent-failures-typescript-wont-catch) after applying changes. > **Using AI to migrate?** Set up the [Eufemia MCP server](/uilib/usage/first-steps/tools/#ai-assistance-and-mcp-server) to give your AI agent access to the full v11 API documentation alongside this migration guide. **Most changes fall into these categories:** 1. **snake_case → camelCase renames** — The majority of changes are mechanical property, event, and translation key renames. These can be [automated](#automated-migration-snake_case-to-camelcase). 2. **React 19 alignment** — `innerRef` → `ref`, `Context.Provider` → `Context`, and related updates. 3. **Behavioral changes and removals** — API redesigns, removed features, and changed defaults. These require manual review. <Accordion title="Table of contents"> - [Summary of changes](#summary-of-changes) - [v10 support timeline](#v10-support-timeline) - [Install](#install) - [Migration](#migration) - [Automated migration: snake_case to camelCase](#automated-migration-snake_case-to-camelcase) - [Migration effort levels](#migration-effort-levels) - [Semantic renames (not just casing)](#semantic-renames-not-just-casing) - [Import path changes](#import-path-changes) - [Common migration mistakes](#common-migration-mistakes) - [Cross-component prop patterns](#cross-component-prop-patterns) - [Step-by-step migration procedure](#step-by-step-migration-procedure) - [Find-and-replace safety guide](#find-and-replace-safety-guide) - [Verifying your migration](#verifying-your-migration) - [Silent failures TypeScript won't catch](#silent-failures-typescript-wont-catch) - [Complete migration example](#complete-migration-example) - [innerRef → ref](#innerref--ref) - [Context.Provider → Context](#contextprovider--context) - [Theme.Provider → Theme.Context](#themeprovider--themecontext) - [Theme propMapping removed](#theme-propmapping-removed) - [Theme darkMode → colorScheme](#theme-darkmode--colorscheme) - [Components](#components) - [labelDirection default changed to vertical](#labeldirection-default-changed-to-vertical) - [Section](#section) - [HelpButton](#helpbutton) - [Autocomplete](#autocomplete) - [Dropdown](#dropdown) - [DrawerList](#drawerlist) - [Anchor](#anchor) - [Input](#input) - [InputMasked](#inputmasked) - [FormLabel](#formlabel) - [Radio](#radio) - [Textarea](#textarea) - [Accordion](#accordion) - [Tag](#tag) - [Upload](#upload) - [Stat](#stat) - [P (paragraph)](#p) - [Definition lists](#definition-lists) - [Breadcrumb](#breadcrumb) - [ProgressIndicator](#progressindicator) - [PaymentCard](#paymentcard) - [Divider (Horizontal Rule)](#divider-horizontal-rule) - [Flex.Item](#flexitem) - [Card](#card) - [Checkbox](#checkbox) - [Switch](#switch) - [Logo](#logo) - [Icon](#icon) - [Button](#button) - [Modal, Dialog and Drawer](#modal-dialog-and-drawer) - [Heading](#heading) - [H (heading elements)](#h-heading-elements) - [Table](#table) - [FormStatus](#formstatus) - [Skeleton](#skeleton) - [Tabs](#tabs) - [Pagination](#pagination) - [Slider](#slider) - [Timeline](#timeline) - [DatePicker](#datepicker) - [NumberFormat](#numberformat) - [StepIndicator](#stepindicator) - [GlobalError](#globalerror) - [ToggleButton](#togglebutton) - [Tooltip](#tooltip) - [GlobalStatus](#globalstatus) - [CopyOnClick](#copyonclick) - [Layout](#layout) - [Helpers](#helpers) - [Eufemia Forms](#eufemia-forms) - [SCSS mixin renames](#scss-mixin-renames) - [SCSS: @import → @use](#scss-import--use) - [TypeScript](#typescript) - [Theming](#theming) - [Props Type Exports](#props-type-exports) - [New in v11](#new-in-v11) </Accordion> ## Summary of changes - **React 19 required** — v11 requires React and React DOM v19. - **IE and Edge (EdgeHTML) no longer supported** — All IE- and legacy-Edge-specific CSS rules have been removed from the CSS reset and component styles. Only modern evergreen browsers (Chrome, Firefox, Safari, Chromium-based Edge) are supported. - All **snake_case** (`on_click`) events and properties have been converted to **camelCase** (`onClick`). The reason for previously using snake_case was to support Web Components – but the support was discontinued in [v10](/uilib/about-the-lib/releases/eufemia/v10-info/). - **`labelDirection` default changed to `vertical`** — Labels render above the input by default. If you relied on horizontal labels, set `labelDirection="horizontal"` explicitly. See [labelDirection](#labeldirection-default-changed-to-vertical). - **FormRow and FormSet removed** — Replace with Flex layout components. See [Removal of FormRow and FormSet](#removal-of-formrow-and-formset). - **InputMasked engine replaced** — Switched from text-mask to Maskito. Custom masks using `createNumberMask` or `emailMask` must be updated. See [InputMasked](#inputmasked). - **Logo API redesigned** — The `brand`/`variant` props are replaced with an `svg` prop import pattern. See [Logo](#logo). - **StepIndicator redesigned** — The sidebar mode has been removed. See [StepIndicator](#stepindicator). - **Ajv no longer auto-instantiated** — Ajv is still a dependency, but is no longer automatically instantiated. If you use JSON Schema validation, you must explicitly create and provide an Ajv instance. See [Ajv no longer auto-instantiated](#ajv-no-longer-auto-instantiated). - **Dropdown `actionMenu`/`moreMenu` removed** — The `actionMenu` and `moreMenu` props on Dropdown have been removed. Use the new [Menu](/uilib/components/menu/) component instead. - **NumberFormat split into variants** — The generic `<NumberFormat />` component and `format()` utility have been removed. Use variant sub-components like `<NumberFormat.Number />`, `<NumberFormat.Currency />`, etc. See [NumberFormat](#numberformat). - **`date-fns` upgraded from v2 to v4** — If you import `date-fns` functions directly (e.g. for DatePicker's `locale` prop), update your imports to use named exports. See [DatePicker](#datepicker). - Replaced deprecated `<Context.Provider>` with direct `<Context>` rendering across all internal context providers (React 19). - Several exported TypeScript `interface` declarations have been converted to `type`. This prevents declaration merging but has no impact on standard usage. - All React context value types have been renamed to use a consistent `...ContextValue` suffix (e.g. `AccordionContextProps` → `AccordionContextValue`). See [TypeScript](#typescript) for the full list. - Event handler and render function prop types have been replaced with properly typed signatures (e.g. `(...args: any[]) => any` → `(event: AccordionChangeEvent) => void`). See [Typed event handlers](#typed-event-handlers) for the full list. ## New in v11 These components are new in v11: - **[Menu](/uilib/components/menu/)** — A context menu component that replaces Dropdown's `actionMenu` and `moreMenu` props. Supports `Menu.Button`, `Menu.List`, `Menu.Action`, `Menu.Accordion`, `Menu.Header`, and `Menu.Divider` sub-components. - **[List](/uilib/components/list/)** — A layout component for displaying structured lists with support for icons, titles, content, and accordion behavior. ## v10 support timeline After the v11 release, **v10 will continue to receive critical bug fixes and security patches for 6 months**. During this period: - **Critical bugs** and **security vulnerabilities** will be patched in v10. - **New features** will only be added to v11. - **Non-critical bug fixes** will only target v11. After the 6-month window, v10 will no longer receive updates. We recommend starting your migration early to avoid last-minute pressure. ## Install To upgrade to @dnb/eufemia v11 with NPM, use: ```bash $ npm i @dnb/eufemia@11 # or $ yarn add @dnb/eufemia@11 # or $ pnpm add @dnb/eufemia@11 ``` ## Migration v11 of @dnb/eufemia contains _breaking changes_. > Important: Upgrading to v11 requires React and React DOM v19 ([React 19 Upgrade Guide](https://react.dev/blog/2024/04/25/react-19-upgrade-guide)). ### Automated migration: snake_case to camelCase The largest category of changes in v11 is the rename of **all snake_case properties, events, and translation keys to camelCase**. This affects every component and can be automated. **The pattern:** - Properties: `selected_key` → `selectedKey`, `label_direction` → `labelDirection` - Events: `on_change` → `onChange`, `on_click` → `onClick` - Translations: `Autocomplete.no_options` → `Autocomplete.noOptions` You can use your editor's find-and-replace to handle most of these. Since each snake_case property maps to a specific camelCase name, we recommend using the per-component lists below rather than a generic regex. > **Note:** Some renames are not just snake_case conversions — they also change the name itself (e.g. `triangle_position` → `arrowPosition`, `opened` → `open`, `on_show` → `onOpen`). These are listed individually per component below and require manual attention. The rest of this section covers changes that **cannot** be automated with a simple find-and-replace and need manual review. ### Migration effort levels To help plan your migration, changes are grouped by effort: **Automated** (find-and-replace): - All snake_case → camelCase property, event, and translation key renames - `innerRef` → `ref` - `<Context.Provider>` → `<Context>` **Semi-automated** (value renames — find-and-replace with care): - Status value `'info'` → `'information'` (applies to `state`, `statusState`, `variant`, `confirmType`) - Status value `'warn'` → `'warning'` (applies to `statusState`) - `opened` → `open` on Autocomplete, Dropdown, DrawerList, DatePicker, Tooltip, Field.Date - `on_show` → `onOpen` and `on_hide` → `onClose` on Autocomplete, Dropdown, DrawerList, DatePicker - `prerender` → `keepInDOM` on Tabs, Accordion - `styleType` / `style_type` → `backgroundColor` on Breadcrumb, Dialog.Body, Drawer.Body **Manual review required:** - InputMasked masking engine replacement (text-mask → Maskito) - StepIndicator redesign (sidebar variant removed) - DatePicker behavioral changes (segment elements, format strings, focus events) - Logo API redesign (`brand`/`variant` → `svg` prop) - Ajv no longer auto-instantiated - FormRow and FormSet removal - Card visual changes (outline, border-radius, default innerSpace) - Button `variant="signal"` removal ### Semantic renames (not just casing) These renames change the property or event name itself, not just the casing. They affect multiple components and require targeted find-and-replace: | Old | New | Affected components | | --------------------------------------- | -------------------------------------- | ------------------------------------------------------------------- | | `innerRef` | `ref` | 20+ components (see [innerRef → ref](#innerref--ref)) | | `opened` | `open` | Autocomplete, Dropdown, DrawerList, DatePicker, Tooltip, Field.Date | | `on_show` / `on_hide` | `onOpen` / `onClose` | Autocomplete, Dropdown, DrawerList, DatePicker | | `on_show_focus` / `on_hide_focus` | `onOpenFocus` / `onCloseFocus` | Dropdown | | `triangle_position` | `arrowPosition` | Autocomplete, Dropdown, DrawerList | | `styleType` / `style_type` | `backgroundColor` | Breadcrumb, Dialog.Body, Drawer.Body | | `spacing` | `innerSpace` (object form) | Section, Dialog.Body, Drawer.Body | | `input_class` / `textarea_class` | `inputClassName` / `textareaClassName` | Input, InputMasked, Textarea | | `prerender` | `keepInDOM` | Tabs, Accordion | | `as` | `element` | H (heading element) | | `size` | `span` | Flex.Item, Card | | `align_autocomplete` / `align_dropdown` | `align` | Autocomplete, Dropdown | | `input_icon` | `icon` | Autocomplete | | `clear` | `showClearButton` | Input, InputMasked | | `visible` | `show` | ProgressIndicator | | `show_label` | `showDefaultLabel` | ProgressIndicator | | `active` / `forceOpen` | `open` | Tooltip | | `position` | `placement` | Tooltip | | `accordion` | `mode="accordion"` | Table | | `onClosed` / `onOpened` | `onClose` / `onOpen` | Table | | `isCollapsed` | `collapsed` | Breadcrumb | | `expandBehaviour` | `expandBehavior` | Accordion | | `class` | `className` | ProgressIndicator, Button, Tabs, PaymentCard | | `contentSpacing` / `tabsSpacing` | `contentInnerSpace` / `tabsInnerSpace` | Tabs | | `darkMode` | `colorScheme` | Theme | ### Import path changes All import paths that changed or were removed in v11. Update these before changing component APIs — your app won't compile until these are fixed. | Old import | New import | Notes | | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------- | | `@dnb/eufemia/components/input/InputPassword` | `import { Field } from '@dnb/eufemia/extensions/forms'` then use `<Field.Password>` | Component moved to Eufemia Forms | | `@dnb/eufemia/fragments/drawer-list/DrawerList` (`ItemContent`) | `@dnb/eufemia/fragments/drawer-list/DrawerListItem` (`ItemContent`) | Named export moved | | `@dnb/eufemia/components/form-row/FormRowHelpers` (`includeValidProps`) | `@dnb/eufemia/shared/helpers/filterValidProps` (`pickFormElementProps`) | Function moved and renamed | | `@dnb/eufemia/components/form-row/FormRowHelpers` (`prepareFormRowContext`) | `@dnb/eufemia/shared/helpers/filterValidProps` (`prepareFormElementContext`) | Function moved and renamed | | `@dnb/eufemia/components/input-masked/InputMaskedHooks` | `@dnb/eufemia/components/input-masked/hooks` | Path changed | | `@dnb/eufemia/components/input-masked/addons/createNumberMask` | **Removed** — use built-in `numberMask` prop | Addon deleted | | `@dnb/eufemia/components/input-masked/addons/emailMask` | **Removed** — use `mask` prop directly | Addon deleted | | `@dnb/eufemia/components/input` (`inputPropTypes`) | **Removed** | PropTypes no longer provided | | `@dnb/eufemia/components/button` (`buttonVariantPropType`) | **Removed** | PropTypes no longer provided | | `style/themes/theme-ui/` | `style/themes/ui/` | Path shortened | | `style/themes/theme-sbanken/` | `style/themes/sbanken/` | Path shortened | | `style/themes/theme-eiendom/` | `style/themes/eiendom/` | Path shortened | | `style/themes/theme-carnegie/` | `style/themes/carnegie/` | Path shortened | | `@dnb/eufemia/components/space/types` (`SectionSpacing`) | `@dnb/eufemia/components/space/types` (`InnerSpaceType`) | Type renamed | | `export type { Props }` from any Field/Value/Form module | Use component-prefixed name (e.g. `FieldStringProps`) | See [Props Type Exports](#props-type-exports) | | `@dnb/eufemia/extensions/payment-card/utils/Types` | `@dnb/eufemia/extensions/payment-card/utils/types` | Filename lowercased for consistency | ### Common migration mistakes These changes look simple but are easy to get wrong. Pay special attention to these: #### `spacing` → `innerSpace` requires an object, not a string The `spacing` prop accepted a string like `"large"`. The replacement `innerSpace` requires an **object with a `block` key** to match the same vertical-only padding behavior. Using `innerSpace="large"` (plain string) applies padding on **all four sides**, which will break your layout. **Wrong:** ```tsx <Section innerSpace="large">Content</Section> ``` **Correct:** ```tsx <Section innerSpace={{ block: 'large' }}>Content</Section> ``` This applies to Section, Dialog.Body, and Drawer.Body. #### `on_show` / `on_hide` → `onOpen` / `onClose` is NOT just a casing change The event names changed semantically. A naive snake_case→camelCase conversion would produce `onShow` / `onHide`, which are **wrong**. | Old | Wrong (naive conversion) | Correct | | --------------- | ------------------------ | -------------- | | `on_show` | ~~`onShow`~~ | `onOpen` | | `on_hide` | ~~`onHide`~~ | `onClose` | | `on_show_focus` | ~~`onShowFocus`~~ | `onOpenFocus` | | `on_hide_focus` | ~~`onHideFocus`~~ | `onCloseFocus` | Affected components: Autocomplete, Dropdown, DrawerList, DatePicker. The `_focus` variants only apply to Dropdown. Note: GlobalStatus still uses `onShow` / `onHide` — those are correct for that component and did not change semantically. #### Component-specific props — don't apply globally These renames only apply to specific components. Do not find-and-replace them across the entire codebase: | Rename | Only applies to | Do NOT apply to | | -------------------------------- | --------------------------- | -------------------------------------------- | | `clear` → `showClearButton` | Input, InputMasked | — | | `isCollapsed` → `collapsed` | Breadcrumb | — | | `input_icon` → `icon` | Autocomplete | Other components that already have `icon` | | `visible` → `show` | ProgressIndicator | Other components with `visible` prop | | `position` → `placement` | Tooltip | Other components with `position` prop | | `children` → `label` | Checkbox, ProgressIndicator | — | | `as` → `element` | H (heading element) | — | | `accordion` → `mode="accordion"` | Table | Accordion component itself | | `size` → `span` | Flex.Item, Card | Other components where `size` is still valid | #### `FormRow` / `FormSet` references in context providers When replacing `FormRow`, be careful not to just rename the JSX tag. The context provider pattern also changed: | Old | New | | ------------------------------- | -------------- | | `FormRow=` (in Provider config) | `formElement=` | | `FormRow:` (in context objects) | `formElement:` | ### Cross-component prop patterns These snake_case props appear on many components and follow the same rename pattern everywhere. Apply these as global find-and-replace within Eufemia component JSX: | Old prop | New prop | Components that use it | | --------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `status_state` | `statusState` | Autocomplete, Checkbox, DatePicker, Dropdown, Input, InputMasked, Radio, Radio.Group, Slider, StepIndicator, Switch, Textarea, ToggleButton, ToggleButton.Group | | `status_props` | `statusProps` | Autocomplete, Checkbox, DatePicker, Dropdown, Input, InputMasked, Radio, Radio.Group, Switch, Textarea, ToggleButton, ToggleButton.Group | | `status_no_animation` | `statusNoAnimation` | Autocomplete, Checkbox, DatePicker, Dropdown, Input, InputMasked, Radio, Radio.Group, Switch, Textarea, ToggleButton, ToggleButton.Group | | `label_direction` | `labelDirection` | Autocomplete, DatePicker, Dropdown, FormLabel, Input, InputMasked, ProgressIndicator, Radio.Group, Slider, Textarea, ToggleButton, ToggleButton.Group | | `label_sr_only` | `labelSrOnly` | Autocomplete, Checkbox, DatePicker, Dropdown, Input, InputMasked, Radio.Group, Switch, Textarea, ToggleButton.Group | | `label_position` | `labelPosition` | Checkbox, Radio, Switch | | `icon_size` | `iconSize` | Autocomplete, Button, GlobalStatus, ProgressIndicator, ToggleButton | | `icon_position` | `iconPosition` | Autocomplete, Button, Dropdown, ToggleButton | | `no_animation` | `noAnimation` | Autocomplete, DatePicker, Dropdown, DrawerList, FormStatus, GlobalStatus, Modal/Dialog/Drawer, Skeleton, StepIndicator | | `on_change` | `onChange` | Nearly all interactive components | | `on_focus` | `onFocus` | Autocomplete, Input, Textarea | | `on_blur` | `onBlur` | Autocomplete, Input, Textarea | | `on_click` | `onClick` | Button, StepIndicator, Tabs, Table.ClickableHead | | `inner_ref` | `ref` | All components that accepted `innerRef` (see [innerRef → ref](#innerref--ref) for the full list) | **Status value renames** — apply to all components that accept `statusState` or `state`: | Old value | New value | | --------- | --------------- | | `'warn'` | `'warning'` | | `'info'` | `'information'` | **CSS class renames** — apply wherever these CSS classes are referenced: | Old CSS class | New CSS class | | ---------------------------------------- | ------------------------------------------ | | `dnb-autocomplete--opened` | `dnb-autocomplete--open` | | `dnb-dropdown--opened` | `dnb-dropdown--open` | | `dnb-drawer-list--opened` | `dnb-drawer-list--open` | | `dnb-date-picker--opened` | `dnb-date-picker--open` | | `dnb-progress-indicator--visible` | `dnb-progress-indicator--show` | | `dnb-anchor--contrast` | `dnb-anchor--surface-dark` | | `dnb-number-format--selectall` | `dnb-number-format--select-all` | | `dnb-autocomplete__suffixValue` | `dnb-autocomplete__suffix-value` | | `dnb-height-animation__compensateForGap` | `dnb-height-animation__compensate-for-gap` | ### Step-by-step migration procedure Follow these steps **in order**. Steps in Phase 1 are safe to apply as global find-and-replace across your entire codebase. Steps in later phases require scoping or manual review. #### Phase 1: Global find-and-replace (safe across entire codebase) These renames only exist as Eufemia prop/event names and won't collide with other libraries: 1. Replace all **snake_case props and events** with their camelCase equivalents. Use the per-component lists in the [Components](#components) section below. The most common ones: `on_change` → `onChange`, `on_click` → `onClick`, `status_state` → `statusState`, `label_direction` → `labelDirection`, `label_sr_only` → `labelSrOnly`, `no_animation` → `noAnimation`, `icon_size` → `iconSize`, `icon_position` → `iconPosition`. 2. Replace `innerRef` with `ref` on all Eufemia components. 3. Replace `<Context.Provider>` with `<Context>` when using Eufemia contexts directly. 4. Replace the status value `'info'` with `'information'` (applies to `state`, `statusState`, `variant`, `confirmType`). 5. Replace the status value `'warn'` with `'warning'` (applies to `statusState`). 6. Replace `input_class` (or `inputClass`) with `inputClassName` on Input and InputMasked. 7. Replace `textarea_class` (or `textareaClass`) with `textareaClassName` on Textarea. #### Phase 2: Targeted find-and-replace (scope to specific components) These renames use generic names that exist in non-Eufemia code. Scope your find-and-replace to JSX using the affected component: 8. Replace `opened` with `open` — **only on** Autocomplete, Dropdown, DrawerList, DatePicker, Tooltip, Field.Date. 9. Replace `on_show` with `onOpen` and `on_hide` with `onClose` — **only on** Autocomplete, Dropdown, DrawerList, DatePicker. _(Not just a casing change — the name changed semantically. GlobalStatus still uses `onShow`/`onHide`.)_ 10. Replace `triangle_position` with `arrowPosition` — **only on** Autocomplete, Dropdown, DrawerList. 11. Replace `clear` with `showClearButton` — **only on** Input, InputMasked. 12. Replace `isCollapsed` with `collapsed` — **only on** Breadcrumb. 13. Replace `visible` with `show` — **only on** ProgressIndicator. 14. Replace `position` with `placement` — **only on** Tooltip. 15. Replace `children` with `label` — **only on** Checkbox, ProgressIndicator. 16. Replace `active` or `forceOpen` with `open` — **only on** Tooltip. 17. Replace `as` with `element` — **only on** H (heading element). 18. Replace `size` with `span` — **only on** Flex.Item, Card. 19. Replace `input_icon` with `icon` — **only on** Autocomplete. 20. Replace `accordion` with `mode="accordion"` — **only on** Table. 21. Replace `prerender` with `keepInDOM` — **only on** Tabs, Accordion. 22. Replace `styleType` (or `style_type`) with `backgroundColor` — **only on** Breadcrumb, Dialog.Body, Drawer.Body. 23. Replace `contentSpacing` with `contentInnerSpace` and `tabsSpacing` with `tabsInnerSpace` — **only on** Tabs. #### Phase 3: Structural and visual changes (require code modification or review) 24. **Visual review:** The `labelDirection` default has changed to `vertical`. If your layouts relied on horizontal labels, add `labelDirection="horizontal"` explicitly. See [labelDirection default changed to vertical](#labeldirection-default-changed-to-vertical). 25. **Visual review:** Card outline, border-radius, and default `innerSpace` have changed. Review your Card layouts. See [Card](#card). 26. Replace `spacing` with `innerSpace={{ block: 'value' }}` on Section, Dialog.Body, Drawer.Body. Do NOT use `innerSpace="large"` — it must be an object. See [Section](#section). 27. Replace `Theme.Provider` with `Theme.Context` and `darkBackground` with `surface="dark"`. See [Theme.Provider → Theme.Context](#themeprovider--themecontext). 28. Replace `<FormRow>` with `<Flex.Horizontal align="baseline">` and `<FormRow vertical>` with `<Flex.Vertical>`. Replace `FormRow=` with `formElement=` in Provider config. See [Removal of FormRow and FormSet](#removal-of-formrow-and-formset). 29. Replace `openState="opened"` with `open={true}` and `openState="closed"` with `open={false}` on Modal/Dialog/Drawer. 30. Update `dateFormat` and `returnFormat` strings: `YYYY` → `yyyy`, `DD` → `dd` on DatePicker. 31. Replace `Stat.Amount` with `Stat.Number`, `Stat.Info variant="default"` with `variant="plain"`. 32. Replace Logo `brand`/`variant` props with `svg` prop import pattern. See [Logo](#logo). #### Phase 4: Import path and module changes 33. Update all changed import paths. See [Import path changes](#import-path-changes). 34. If using Ajv with JSON Schema validation, add `ajvInstance={makeAjvInstance()}` to `Form.Handler`. See [Ajv no longer auto-instantiated](#ajv-no-longer-auto-instantiated). 35. Replace `InputPassword` import with `Field.Password` from Eufemia Forms. See [InputPassword moved to Field.Password](#inputpassword-moved-to-fieldpassword). 36. Replace `StepsLayout` with `Wizard.Container`, `StepsLayout.Step` with `Wizard.Step`, etc. #### Phase 5: SCSS changes 37. If you import Eufemia SCSS source files with `@import`, replace with `@use` and namespace your calls. See [SCSS: @import → @use](#scss-import--use). 38. Rename all SCSS mixin references to camelCase. See [SCSS mixin renames](#scss-mixin-renames). 39. Remove `extendFocusRing` and `componentReset` SCSS mixin calls — they have been deleted. #### Phase 6: TypeScript type updates 40. Update any imported context value types (`AccordionContextProps` → `AccordionContextValue`, etc.). See [TypeScript](#typescript). 41. Update any Props type imports (`Props` → component-prefixed name). See [Props Type Exports](#props-type-exports). 42. Update event handler types to match new typed signatures. See [Typed event handlers](#typed-event-handlers). #### Phase 7: Eufemia Forms behavioral changes 43. Replace `validator` with `onChangeValidator` on all Field components. 44. Replace `continuousValidation` with `validateContinuously` on all Field components. 45. Update `errorMessages` object keys: `required` → `Field.errorRequired`, `pattern` → `Field.errorPattern`, etc. See [Error handling](#error-handling). 46. Replace `Form.useError` with `Form.useValidation`, `Form.useLocale` with `Form.useTranslation`. 47. Replace `Form.Visibility` props: `withValue` → `hasValue`, `pathValue`/`whenValue` → `visibleWhen`. 48. Replace `Form.FieldProps` with `Field.Provider`. 49. Replace `<Card stack>` with `<Form.Card>` and `<Card>` (inside forms) with `<Form.Card>`. 50. Replace `Iterate.ArrayPushButton` with `Iterate.PushButton` and `Iterate.ArrayRemoveElementButton` with `Iterate.RemoveButton`. 51. Replace `requireCommit` with `preventUncommittedChanges` on `Iterate.PushContainer`. 52. Replace `active` with `include` and `activeWhen` with `includeWhen` on `Wizard.Step`. 53. Replace Form.Iterate label variable `{itemNr}` with `{itemNo}`. 54. Review all remaining changes in the [Eufemia Forms](#eufemia-forms) section. #### Phase 8: Verify 55. Run `npx tsc --noEmit` to catch remaining type errors. 56. Run your tests. Update any test selectors that query DatePicker/Expiry `input` elements (now `role="spinbutton"` sections). 57. Search for remaining snake_case patterns using the grep command in [Verifying your migration](#verifying-your-migration). ### Find-and-replace safety guide **Safe for global find-and-replace** — these prop names are Eufemia-specific and won't collide with other code: `on_change`, `on_click`, `on_focus`, `on_blur`, `on_submit`, `on_key_down`, `on_type`, `on_select`, `on_clear`, `on_open`, `on_close`, `on_cancel`, `on_reset`, `on_complete`, `on_resize`, `on_end`, `on_load`, `on_startup`, `on_adjust`, `on_days_render`, `on_submit_focus`, `on_submit_blur`, `status_state`, `status_props`, `status_no_animation`, `label_direction`, `label_sr_only`, `label_position`, `icon_size`, `icon_position`, `no_animation`, `inner_ref`, `selected_key`, `default_value`, `prevent_selection`, `prevent_close`, `keep_open`, `independent_width`, `fixed_position`, `enable_body_lock`, `skip_portal`, `cache_hash`, `no_scroll_animation`, `min_height`, `max_height`, `input_element`, `submit_element`, `submit_button_title`, `submit_button_icon`, `submit_button_variant`, `clear_button_title`, `keep_placeholder`, `input_attributes`, `inner_element`. > **Note:** `on_state_update` is **not** in this list because it has been removed, not renamed. If you used `on_state_update`, replace it with `onChange` instead. **Must be scoped to specific components** — these names exist outside Eufemia or overlap across components with different meanings: | Rename | Scope to | Risk if applied globally | | -------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------------- | | `opened` → `open` | Autocomplete, Dropdown, DrawerList, DatePicker, Tooltip, Field.Date | Collides with HTML `open` attribute on `<details>` | | `clear` → `showClearButton` | Input, InputMasked | Collides with generic `clear` functions | | `visible` → `show` | ProgressIndicator | Collides with generic `visible` props | | `position` → `placement` | Tooltip | Collides with CSS `position` prop/style | | `children` → `label` | Checkbox, ProgressIndicator | `children` is a React universal prop | | `as` → `element` | H (heading element) | `as` is used by styled-components and other libs | | `size` → `span` | Flex.Item, Card | `size` is used by many non-Eufemia components | | `active` → `open` | Tooltip | `active` is a common generic prop | | `accordion` → `mode="accordion"` | Table | Prop-to-prop+value change, not a simple rename | | `input_icon` → `icon` | Autocomplete | Other components already have different `icon` props | | `spacing` → `innerSpace` | Section, Dialog.Body, Drawer.Body | Requires object form `{ block: '...' }`, not string | | `on_show` → `onOpen` | Autocomplete, Dropdown, DrawerList, DatePicker | Semantic change; GlobalStatus keeps `onShow` | | `on_hide` → `onClose` | Autocomplete, Dropdown, DrawerList, DatePicker | Semantic change; GlobalStatus keeps `onHide` | ### Verifying your migration After applying changes, use these commands to validate: **TypeScript check** — catches missed renames, wrong prop types, and removed APIs: ```bash npx tsc --noEmit ``` **Search for remaining snake_case** — catches props you missed: ```bash grep -rn 'on_\|status_\|label_\|icon_\|_class\b\|inner_ref\|_state\|_position\|_button\|_text\|_sr_' \ --include='*.tsx' --include='*.ts' src/ ``` > **Note:** This grep only catches snake_case patterns. Semantic renames like `opened` → `open`, `prerender` → `keepInDOM`, `clear` → `showClearButton`, and `expandBehaviour` → `expandBehavior` require manual review using the [Semantic renames](#semantic-renames-not-just-casing) table. **Common TypeScript errors and what they mean:** | Error | Cause | Fix | | ----------------------------------------------------------------- | ------------------------------------ | --------------------------------------------------------- | | `Property 'on_change' does not exist` | Missed snake_case → camelCase rename | Replace with `onChange` | | `Property 'innerRef' does not exist` | Missed innerRef → ref | Replace with `ref` | | `Type '"info"' is not assignable` | Missed status value rename | Replace `'info'` with `'information'` | | `Type '"warn"' is not assignable` | Missed status value rename | Replace `'warn'` with `'warning'` | | `Module not found: '@dnb/eufemia/components/input/InputPassword'` | Import path moved | Use `Field.Password` from `@dnb/eufemia/extensions/forms` | | `Property 'spacing' does not exist` | Removed prop | Replace with `innerSpace={{ block: 'value' }}` | | `Property 'brand' does not exist` on Logo | Logo API redesigned | Import SVG component and use `svg` prop | | `Type '"signal"' is not assignable` on Button | Variant removed | Use `variant="primary"` or `variant="secondary"` | | `Cannot find name 'FormRow'` | Component removed | Replace with `Flex.Horizontal` or `Flex.Vertical` | | `Property 'opened' does not exist` | Prop renamed | Replace with `open` | ### Silent failures TypeScript won't catch TypeScript catches most v10 → v11 errors, but these three categories **compile without errors and fail silently at runtime**. You must search for them manually after migration. #### 1. Data object property renames Dropdown, Autocomplete, DrawerList, and Field.Selection accept `data` arrays with objects. The `DrawerListDataArrayObject` type allows arbitrary keys (`[key: string]: any`), so TypeScript **will not flag** old snake_case property names. The component simply won't find the values it expects. **Compiles but broken:** ```tsx <Dropdown data={[ { selected_key: 'no', content: 'Norway' }, // silent failure { selected_key: 'se', content: 'Sweden' }, // silent failure ]} /> ``` **Correct:** ```tsx <Dropdown data={[ { selectedKey: 'no', content: 'Norway' }, { selectedKey: 'se', content: 'Sweden' }, ]} /> ``` Search for old data property names: ```bash grep -rn 'selected_key\|selected_value\|suffix_value\|search_content\|class_name' \ --include='*.tsx' --include='*.ts' src/ ``` #### 2. Event callback return object renames Several components renamed properties on the objects passed to event callbacks. If you destructure the old property names, the values will be `undefined` at runtime with no TypeScript error (because callback parameter types are often inferred loosely). **DatePicker `onChange` return object:** | Old property | New property | | --------------------- | ------------------ | | `days_between` | `daysBetween` | | `is_valid` | `isValid` | | `is_valid_start_date` | `isValidStartDate` | | `is_valid_end_date` | `isValidEndDate` | **Field.Date `onType` return object:** | Old property | New property | | ------------ | ------------ | | `start_date` | `startDate` | | `end_date` | `endDate` | | `is_valid` | `isValid` | Search for old callback property access: ```bash grep -rn 'days_between\|is_valid\|is_valid_start_date\|is_valid_end_date\|start_date\|end_date' \ --include='*.tsx' --include='*.ts' src/ ``` #### 3. CSS class selectors in strings and tests CSS class names used in `querySelector`, test assertions, or CSS/SCSS files are plain strings that TypeScript cannot validate. Search for all renamed CSS classes: ```bash grep -rn 'dnb-autocomplete--opened\|dnb-dropdown--opened\|dnb-drawer-list--opened\|dnb-date-picker--opened\|dnb-progress-indicator--visible\|dnb-anchor--contrast\|dnb-number-format--selectall\|dnb-section--spacing' \ --include='*.tsx' --include='*.ts' --include='*.scss' --include='*.css' src/ ``` Also check DatePicker/Expiry test selectors — the visible date segments changed from native `input` elements to `role="spinbutton"` sections: ```tsx // Before (v10) — queried native input elements document.querySelector('.dnb-date-picker input') // After (v11) — use role-based selectors document.querySelector('[role="spinbutton"]') // or document.querySelector('.dnb-segmented-field__section') ``` #### 4. Theme `darkMode` prop silently ignored The `darkMode` prop on `Theme` was replaced with `colorScheme`. Passing `darkMode` compiles without error but is silently ignored. The CSS class also changed from `eufemia-theme__dark-mode` to `eufemia-theme__color-scheme--dark`. Search for old usage: ```bash grep -rn 'darkMode\|eufemia-theme__dark-mode' \ --include='*.tsx' --include='*.ts' --include='*.scss' --include='*.css' src/ ``` #### 5. Provider `locales` prop silently ignored The `locales` prop on `Provider` and `Context` was removed in favor of `translations`. Passing `locales` compiles without error but is silently ignored, meaning your custom translations will not be applied. Search for old usage: ```bash grep -rn 'locales=' --include='*.tsx' --include='*.ts' src/ ``` ### Complete migration example This example shows a realistic v10 component migrated to v11, combining multiple change categories: **Before (v10):** ```tsx import { Input, Dropdown, DatePicker, Section, Button, FormRow, } from '@dnb/eufemia' import { Provider } from '@dnb/eufemia/shared' function MyForm({ formRef }) { return ( <Provider FormRow={{ label_direction: 'vertical' }}> <Section spacing="large" style_type="white"> <FormRow> <Input label="Name" on_change={({ value }) => console.log(value)} status="Error message" status_state="error" innerRef={formRef} /> <Dropdown label="Country" selected_key="no" on_change={({ data }) => console.log(data)} opened={false} on_show={() => console.log('opened')} on_hide={() => console.log('closed')} triangle_position="left" data={[ { selected_key: 'no', content: 'Norway' }, { selected_key: 'se', content: 'Sweden' }, ]} /> <DatePicker label="Start date" date_format="YYYY/MM/DD" return_format="YYYY-MM-DD" on_change={({ date }) => console.log(date)} on_show={() => console.log('shown')} on_hide={() => console.log('hidden')} /> </FormRow> <Button variant="signal" on_click={() => console.log('submit')}> Submit </Button> </Section> </Provider> ) } ``` **After (v11):** ```tsx import { Input, Dropdown, Flex, DatePicker, Section, Button, } from '@dnb/eufemia' import { Provider } from '@dnb/eufemia/shared' function MyForm({ formRef }) { return ( <Provider formElement={{ labelDirection: 'vertical' }}> <Section innerSpace={{ block: 'large' }} backgroundColor="white"> <Flex.Horizontal align="baseline"> <Input label="Name" onChange={({ value }) => console.log(value)} status="Error message" statusState="error" ref={formRef} /> <Dropdown label="Country" selectedKey="no" onChange={({ data }) => console.log(data)} open={false} onOpen={() => console.log('opened')} onClose={() => console.log('closed')} arrowPosition="left" data={[ { selectedKey: 'no', content: 'Norway' }, { selectedKey: 'se', content: 'Sweden' }, ]} /> <DatePicker label="Start date" dateFormat="yyyy/MM/dd" returnFormat="yyyy-MM-dd" onChange={({ date }) => console.log(date)} onOpen={() => console.log('shown')} onClose={() => console.log('hidden')} /> </Flex.Horizontal> <Button variant="primary" onClick={() => console.log('submit')}> Submit </Button> </Section> </Provider> ) } ``` **What changed (13 categories in one component):** 1. `FormRow` → `Flex.Horizontal align="baseline"` (removed component) 2. `FormRow={{ label_direction: 'vertical' }}` → `formElement={{ labelDirection: 'vertical' }}` (Provider config) 3. `spacing="large"` → `innerSpace={{ block: 'large' }}` (structural change — object required) 4. `style_type="white"` → `backgroundColor="white"` (semantic rename) 5. `on_change` / `on_click` → `onChange` / `onClick` (snake_case → camelCase) 6. `status_state` → `statusState` (snake_case → camelCase) 7. `innerRef` → `ref` (React 19) 8. `selected_key` → `selectedKey` (snake_case → camelCase, in both props and data objects) 9. `opened` → `open` (semantic rename) 10. `on_show` / `on_hide` → `onOpen` / `onClose` (semantic rename — NOT `onShow`/`onHide`) 11. `triangle_position` → `arrowPosition` (semantic rename) 12. `date_format="YYYY/MM/DD"` → `dateFormat="yyyy/MM/dd"` (casing + format string change) 13. `variant="signal"` → `variant="primary"` (removed variant) ### innerRef → ref React 19 passes `ref` as a regular prop, making `forwardRef` and custom `innerRef` patterns unnecessary. All Eufemia components that previously accepted an `innerRef` prop now accept `ref` directly. **Before:** ```tsx <Input innerRef={myRef} /> <Button innerRef={myRef} /> <Element innerRef={myRef} /> ``` **After:** ```tsx <Input ref={myRef} /> <Button ref={myRef} /> <Element ref={myRef} /> ``` Affected c