iTwinUI react v3 migration guide - iTwin/iTwinUI GitHub Wiki

Semi-Automated Migration Tool 🤖

To help with the migration (for breaking changes), we also provide a migration tool that scans your project repo for old code and runs automated codemods.

Download options:


This page documents all breaking changes in @itwin/itwinui-react@^3.0.0. Make sure to install the latest 3.x version and resolve any version conflicts.

Also see @itwin/[email protected] migration guide.

General

  • #1389: iTwinUI is now ESM-first and correctly supports both ESM and CJS environments.
  • #1412: All styles have been wrapped inside a cascade layer named itwinui. See the styling documentation for more.
  • #1583: Bumped minimum required react version to 17. If you're still on react 16, please update to react 17 (which has no breaking changes).
  • #1298: Most components are now polymorphic (support as prop), spread their rest props, and forward their refs.
  • #1346: The build now targets es2020 instead of es2018. As a result, you might need to update some of your build tools (e.g. babel).

Dependencies

  • #1302: The dependencies on @itwin/itwinui-css and @itwin/itwinui-variables have been removed. This means @itwin/itwinui-react will bring its own stylesheet.
  • #1331, #1506: The dependency on tippy.js has been removed in favor of floating ui. While the basic usage is unchanged, all advanced props from tippy are no longer available. Components affected: Tooltip, Select, ComboBox, DropdownMenu, DropdownButton, SplitButton.
  • #1514: The dependency on @types/react-table has been removed. See: Table section.

Breaking changes

ThemeProvider

  • #1265: Removed the deprecated useTheme hook. <ThemeProvider> is now always required to be wrapped around every tree within which iTwinUI components are used.

    + <ThemeProvider>
       <App />
    + </ThemeProvider>
  • #1478: ThemeProvider now defaults the theme value to "inherit" (previously "light"), while still using "light" as fallback if there is no parent theme found. Also the inherit behavior has been made more resilient for cases where react context fails.

Styles

  • #1322: All CSS imports within components have been removed.

    • For packages: No change required! Styles will be handled manually by applications or automatically by fallback logic within iTwinUI.
    • For applications: @itwin/itwinui-react/styles.css should now be manually imported at the entrypoint.
      + import '@itwin/itwinui-react/styles.css';
      If your application is still using v2, it may not be possible without npm aliases. In such a case, iTwinUI will fall back to using a dynamic import to automatically import missing CSS. However, for best experience and more robustness, we recommend that applications migrate to v3 and continue to manually import styles.css.
  • #1302: All elements have had their class names changed to prevent conflict with older versions. These classes are considered a private implementation detail, so if you were relying on them in your code, it is strongly recommended to instead use your own classes or data attributes. Most iTwinUI components support passing a custom className prop.

    - .iui-button {
    + .my-button {
      /* ... */
    } 
     <Button
      onClick={() => {}}
    + className='my-button'
     >

    If you find a component where it is not possible to add a custom class, then please open an issue.

Exports

  • #1298: Props types will no longer be exported for any component. Use React.ComponentProps or React.ComponentPropsWithoutRef instead. In most cases, it is also useful to manually omit the as prop because it relies on generics.

      import {
        Avatar,
    -   type AvatarProps,
      } from '@itwin/itwinui-react';
    + type AvatarProps = Omit<React.ComponentPropsWithoutRef<typeof Avatar>, 'as'>;
  • #1433: Updated package exports to prevent importing internal utilities.

Button

  • #1461: The behavior of disabled buttons has been changed to make them focusable and use aria-disabled instead of disabled attribute. While this is technically a breaking change, it shouldn't affect most uses. If you run into any issues, you can restore the old behavior using the new htmlDisabled prop.
  • #1435: SplitButton: className is now passed to the button instead of the component wrapper. Use wrapperProps if the old behavior is desired.

Checkbox

  • #1406: Removed setFocus prop. Checkbox can be focused by using autoFocus or ref.
  • #1371: className and style will now always be applied on the checkbox input element (instead of conditionally being applied on the wrapper in some cases). If checkbox is used without label, then no changes should be needed. If label is used, then pass className and style to wrapperProps.
      <Checkbox
        label='Checkbox label'
    -   className={wrapperClassname}
    -   style={wrapperStyle}
    +   wrapperProps={{ className: wrapperClassName, style: wrapperStyle }}
      />
    

ColorPicker

  • #1406: Removed setFocus prop. ColorPicker can be automatically focused by using it within Popover.

ComboBox

  • #1406: Removed setFocus prop. ComboBox can be focused by using inputProps.autoFocus or inputProps.ref.

Dialog / Modal

  • #1269: All dialog variants have flex applied by default. This means the content should be wrapped with Dialog.Content or ModalContent for optimal layout.
     <Modal>
    -  my content
    +  <ModalContent>my content</ModalContent>
     </Modal>
  • #1300: modalRootId and ownerDocument props have been removed from Modal, in favor of the new portal prop (also available in Dialog). This new prop can accept any HTMLElement, with no opinion on how it gets created.
    - <Modal modalRootId='my-custom-root'>
    + <Modal portal={{ to: myCustomRootElement }}>

DropdownMenu

  • #1565: Removed Menu component in favor of DropdownMenu.

ErrorPage / NonIdealState

  • #1400: The deprecated ErrorPage component will now dynamically import illustrations (previously it was statically importing the entire illustrations package, bloating the bundle). No required API changes.

Input

  • #1406: Removed setFocus prop. Input can be focused by using autoFocus or ref.

LabeledInput

  • #1544: iconDisplayStyle has been removed. svgIcon is now always displayed inline and doesn't support buttons.
    • For icons below input, use <StatusMessage>. For inline buttons, use <InputWithDecorations>.
  • #1406: Removed setFocus prop. LabeledInput can be focused by using autoFocus or ref.
  • #1355: Removed inputStyle and inputClassName props; style and className props are being passed down to input. Added wrapperProps, labelProps, messageProps, messageIconProps, inputWrapperProps to pass props to sub elements.

LabeledTextarea

  • #1355: iconDisplayStyle has been removed. svgIcon is now always displayed inline and doesn't support buttons.
  • #1406: Removed setFocus prop. LabeledTextarea can be focused by using autoFocus or ref.
  • #1355: Removed textareaStyle and textareaClassName props; style and className props are being passed down to textarea. Added wrapperProps, labelProps, messageProps, messageIconProps to pass props to sub elements.

LabeledSelect

  • #1355: Removed selectStyle and selectClassName props; style and className props are being passed down to textarea. Added wrapperProps, labelProps, messageProps, messageIconProps to pass props to sub elements.

Radio

  • #1406: Removed setFocus prop. Radio can be focused by using autoFocus or ref.
  • #1409: RadioTile's className and style props will now always be applied on the <input> element instead of conditionally being applied on the wrapper when label is passed. Added wrapperProps, iconProps, labelProps, subLabelProps to individually customize each part of the component.
      <Radio
        label = 'Radio label'
    -   className={wrapperClassname}
    -   style={wrapperStyle}
    +   wrapperProps={{ className: wrapperClassName, style: wrapperStyle }}
      />

RadioTile

  • #1406: Removed setFocus prop. RadioTile can be focused by using autoFocus or ref.

Select

  • #1406: Removed setFocus prop. Select can be focused by using triggerProps.ref.

SideNavigation

  • #1458: Top-level props (className, style, etc) now passed to the main inner div instead of to the wrapper. Use wrapperProps to restore old behavior.

Slider

  • #1406: Removed setFocus prop. Slider can be focused by using thumbProps.ref.

Textarea

  • #1406: Removed setFocus prop. Textarea can be focused by using autoFocus or ref.

Tile

  • #1527: Tile's leftIcon and rightIcon props no longer set size for the buttons so it must be done manually.
      <Tile
       // ...
    -  leftIcon={<IconButton styleType='borderless'>...</IconButton>}
    +  leftIcon={<IconButton styleType='borderless' size='small'>...</IconButton>}
    -  rightIcon={<IconButton styleType='borderless'>...</IconButton>}
    +  rightIcon={<IconButton styleType='borderless' size='small'>...</IconButton>}
      />

Toaster

  • #1351: toaster import has been removed and replaced with useToaster which returns a toaster object with the same public methods as before.
    - import { toaster } from '@itwin/itwinui-react';
    + import { useToaster } from '@itwin/itwinui-react';
    
      export default () => {
    +   const toaster = useToaster();
    
        return <button onClick={() => toaster.positive('hello')}>show</button>
      };

ToggleSwitch

  • #1406: Removed setFocus prop. ToggleSwitch can be focused by using autoFocus or ref.

Tooltip

  • #1331: Migrated Tooltip from tippy.js to floating-ui. While the basic component usage is unchanged, all advanced props that were inherited from tippy.js have been removed. New props available: autoUpdateOptions, middleware and portal.

    Note: Since floating-ui uses ResizeObserver, you might need to add a mock in your tests.

Typography

  • #1296: Removed previously-deprecated typography components (Body, Headline, Leading, Small, Subheading, Title) which have been replaced by Text.

Table

  • #1514: Removed dependency on @types/react-table and instead exposed a package endpoint /react-table for all react-table types. Our types are specifically tailored to the users of our Table and thus offer better type support.
    import { Table } from '@itwin/itwinui-react';
    - import { Column, TableState } from 'react-table';
    + import { Column, TableState } from '@itwin/itwinui-react/react-table';
  • #1570: We made changes to help raise type errors that might have been previously hidden. Thus, you might have to use satisfies when passing props to <Table> to make sure all your types are correct.
    - const data = [...]
    + const data = [...] satisfies MyRowDataType[]

Tabs

  • #1388: Removed previously-deprecated HorizontalTabs and VerticalTabs. Instead use Tabs with orientation prop.
  • #1548: Tabs are now always scrollable. The overflowOptions prop is now a no-op.

UserIcon / UserIconGroup

  • #1383: Removed previously-deprecated UserIcon and UserIconGroup components (replaced with Avatar and AvatarGroup respectively). Also removed userIcon prop from Header (now part of actions prop).

Wizard

  • #1384: Removed previously-deprecated Wizard component. Use Stepper for interactive wizards, or use WorkflowDiagram for displaying non-interactive flowcharts.

ButtonGroup

  • #1278: Adjusted calculations in ButtonGroup's overflowButton callback, so that it respects overflowPlacement and considers the presence of the overflowButton itself.

ProgressRadial / ProgressLinear

  • #1356: ProgressRadial has been refactored to be a single <div> instead of using a nested svg. Also it is recommended to explicitly set size when using in other components. For instance, <ProgressRadial /> in Table's DefaultCell.endIcon prop (example diff), or if you were previously relying on some iTwinUI component to automatically set the progress indicator to small size, you must now use <ProgressRadial size='small'>.

ExpandableBlock

  • #1354: The value of the isExpanded prop will now be used as the source of truth for all renders (i.e. "controlled" mode), rather than only for the initial render. If you were previously relying on this prop to specify the initial state, you must now maintain your own state (alongside the onToggle prop).

New features

  • #1477: Added a new portalContainer prop to ThemeProvider. When specified, all floating elements (tooltips, toats, dialogs) under the ThemeProvider will read this prop from context and portal into it.
  • #1506: Added new Popover component for public use.
  • #1328: Added new Overlay component with customizable subcomponents: Overlay.Wrapper, Overlay.HiddenContent, Overlay.Overlay
  • #1073: Added new TransferList component which is used to move one or more items between lists.
  • #1457: Added htmlName prop to the HeaderButton subcomponent which handles the native name attribute in <button>.
  • #1419: Added htmlSize prop to the Input component which handles the native size attribute in <input>.
  • #1247: Added alternative subcomponent API to Alert.
  • #1369: Added alternative subcomponent API to Breadcrumbs.
  • #1354: Added alternative subcomponent API to ExpandableBlock.
  • #1255: Added alternative subcomponent API to Tile.
  • #1548: Added alternative subcomponent API to Tabs.
  • #1355: Added InputGrid and InputWithDecorations components.
  • #1355: Added padded prop to Icon to render icons with padding.
  • #1355: Added StatusMessage component (previously used under LabeledInput, LabeledSelect, etc(.
  • #1355: Added status prop to Input, Textarea and Select.
  • #1403: Accept additional type of JSX.Element[] and JSX.Element for menuItems prop in DropdownMenu.

New deprecations

Breadcrumbs

  • #1557: Directly passing <a>/<Button>/<span> as children is deprecated. Should be replaced with Breadcrumbs.Item subcomponent.

MenuItem

  • #1295: Deprecated icon and badge props in favor of new startIcon and endIcon props. Also affects Select and ComboBox options.

FileUploadTemplate

  • #1330: Deprecated FileUploadTemplate. Should be replaced with FileUploadCard.

Tabs

  • #1548: Deprecated overflowOptions prop in Tabs. It is now a no-op, as tabs will overflow by default.
⚠️ **GitHub.com Fallback** ⚠️