Skip to main content
HomeUpgrade Quantum
warning
This is a beta release of the Quantum web libraries
Please be careful when using them in production, as they may contain bugs, unstable breaking changes, and incomplete features.

Upgrade Quantum

This guide will help you migration from Quantum v1 to Quantum v2.

Need to see the v1 docs? Visit this older version of the docs site (unmaintained v1.4.0 snapshot).

Overview

This migration focuses on transitioning from Stencil-based React components to native React components and removing the "Qtm" prefix from component names in the @qtm/react2 library.

  • @qtm/react2: A new library offering native React components. This is distinct from the original @qtm/react which relied on Stencil. The move away from Stencil was prompted by numerous issues with DOM manipulation, particularly concerning dynamic changes.
  • Component Renaming: The "Qtm" prefix has been removed from component names in the @qtm/react2 library. For example, QtmButton is now Button. To assist with migration, aliasing can be used like import { Button as QtmButton } from '@qtm/react2.
  • Removal of Web Component Dependency: The @qtm/react2 package no longer depends on web components.

Migration Steps

Step 1: Update Dependencies

Update your project's dependencies to the latest versions of Quantum Design System packages. Modify your package.json to reflect the new package names and versions.

Before:

"dependencies": {
"@qtm/react": "^1.4.0",
"@qtm/web-components": "^1.4.0",
"@qtm/tailwind-preset": "^1.4.0",
"@qtm/tokens": "^1.4.0",
// other dependencies
}

After:

"dependencies": {
"@qtm/react2": "beta",
"@qtm/tailwind-preset": "beta",
"@qtm/tokens": "beta",
// other dependencies
}

Run the following command to update your dependencies:

npm install

Step 2: Refactor Component Imports

Refactor your component imports to use the new @qtm/react2 package for native React components and update the component names.

Before:

import { QtmButton } from '@qtm/react';

After:

import { Button as QtmButton } from '@qtm/react2';

Alternatively, you can directly use the new component names without aliasing:

import { Button } from '@qtm/react2';

function App() {
return <Button>Submit</Button>;
}

export default App;

Step 3: Refactor Types Imports

Refactor your type imports to use the new @qtm/react2 package. This ensures that your TypeScript project benefits from improved type safety and autocompletion.

Before:

import type { AlertSeverity } from '@qtm/web-components'
// or
import type { AlertSeverity } from '@qtm/web-components/dist/types/components/alert/alert-type'

After:

import type { AlertSeverity } from '@qtm/react2'

Step 4: Update CSS

Ensure your CSS references are updated to include the necessary styles from the new @qtm/react2 package.

Before:

@import '@qtm/web-components/dist/web-components/web-components.css';

After:

@import '@qtm/react2/dist/style.css';

Step 5: Adjust for API Changes

Review the component API changes and adjust your code accordingly. This might include updating props, event handlers, and other component-specific configurations.

Custom icon support

Custom icon support has been slightly changed as icon props now accept React elements instead of an object:

- <QtmButton leftIcon={{ icon: 'applied_settings', lib: 'business' }} label="Button"></QtmButton>
+ <Button leftIcon={<Icon icon="applied_settings" lib="business" />} label="Button"></Button>

This allows for more flexible and dynamic icon rendering, allowing you to use any React component as an icon. We recommend the use of the Icon component implementing a similar IconProps type.

List of impacted elements:

  • Alert's ActionButton icon prop.
  • Button's leftIcon and rightIcon props.
  • MenuItemList's MenuItemType icon prop.
  • SplitButton's SplitButtonType and SplitButtonOption icon props.
  • Tab's icon prop.
  • Tag's icon prop.
  • TextInput's leftIcon and rightIcon props.

Step 6: Review Boolean Usage

In the previous version, React components wrapped with Stencil accepted boolean string values like "true" and "false". The new native React implementation requires actual boolean values.

Follow these guidelines to update your boolean properties:

  • Replace my-property="true" with my-property or my-property={true}
  • Replace my-property="false" with my-property={false}
  • Leave my-property={true} unchanged
  • Leave my-property={false} unchanged

Be attentive to cases where strings come from variables or dynamic expressions, as these may need additional steps for proper boolean conversion.

Step 7: Test Your Application

Thoroughly test your application to ensure all components are rendering correctly and there are no regressions. Pay special attention to styles, functionality, and performance.


Extra Focus on Components

Alert

  • The Alert component's action button icon (ActionButton's icon prop) now supports both a ReactElement and the string type, allowing more flexible icon definitions.

Checkbox

  • Several Checkbox props are now accessible directly via the inputProps prop, which exposes props of the inner <input type="checkbox"> HTML element:
    • checked is now inputProps.checked or inputProps.defaultChecked based on whether the component is controlled or uncontrolled.
    • inputId is now inputProps.id.
    • name is now inputProps.name.
    • required is now inputProps.required.
  • The Checkbox component's valueChanged event has been replaced by the onChange callback (also accessible from inputProps):
- onValueChanged={(event) => {console.log(event.detail.checked)}}
+ onChange={(event) => {console.log(event.target.checked)}}

Datatable

  • A new Datatable component is available to render basic data tables, with a variant for when there's no data available.

Doughnut

  • The Doughnut component wasn't officially released in v1, but please be aware that the Doughnut component present in the package has been removed.
  • The Dropdown component's visibleChange event has changed; previously, the visible value was accessed via event.detail.visible, but it is now directly available as event.
  • The Dropdown component's clickOutside event has changed; it now uses a simpler event signature without any parameters.
  • The DropdownTrigger component disabled prop has been removed as what's important is the disabled state of the dropdown trigger child itself.
  • The DropdownTrigger component doesn't have anymore a triggerEvent event, as it was used as a private implementation detail.
  • DropdownSelectOption type has been renamed to DropdownSelectItem to avoid naming conflict with the DropdownSelectOption component.
  • The Dropdown Select component is now searchable thanks to its new isSearchable prop (default to false).
  • The Dropdown Select component now has a minimal keyboard navigation that is not yet fully accessible.
  • The Dropdown Select component now supports disabled options (new DropdownSelectItem's disabled prop).
  • The Dropdown Select component has a new visible prop.
  • The Dropdown Select component's valueChanged event parameter has changed. To get the value:
- onValueChanged={(event) => {console.log(event.detail.valueChanged)}}
+ onValueChanged={(value) => {console.log(value)}}
  • The DropdownSelectOption component doesn't have anymore a clickOption event.

Form Label

  • React replaces the for attribute with htmlFor to avoid conflicts and ensure compatibility with JavaScript.

Icon

  • IconType has been renamed to IconProps.
  • MenuItemItemType has been renamed to MenuItemType.
  • MenuItemList component's enableAutoActive prop is now set by default to true. To maintain the previous behavior, review all instances of MenuItemList in your codebase. If you wish to disable the new auto-active feature, explicitly set enableAutoActive to false. Alternatively, to take advantage of the new feature, ensure each menu item (or sub-menu item) has a unique id and remove any manually set active props, allowing the auto-active logic to handle them automatically.
  • MenuItemList component's activeIdChanged, clickItem, and collapsedIdsChanged event parameters have changed. To get the values:
- onActiveIdChanged={(event) => {console.log(event.detail)}}
- onClickItem={(event) => {console.log(event.detail)}}
- onCollapsedIdsChanged={(event) => {console.log(event.detail)}}
+ onActiveIdChanged={(event) => {console.log(event)}}
+ onClickItem={(event) => {console.log(event)}}
+ onCollapsedIdsChanged={(event) => {console.log(event)}}
  • MenuItem component's item (that was hidden from the docs) has been removed.
  • MenuItem component's clickedMenuItem has been replaced with the native <div>'s onClick handler.
  • MenuItemLabel component's clickEvent has been replaced with the native <div>'s onClick handler.
  • SubmenuItem component's clickedSubmenuItem has been replaced with the native <div>'s onClick handler.
  • The Modal component's closeModal event has changed its signature that now has an empty parameter.
  • ModalHeader's ModalHeaderType is now 'large' | 'medium' | 'small'.
  • The Modal component's closedButton event has been renamed to use the onCloseButton, whose signature has changed and now has an empty parameter.

Multiselect

  • The Multiselect component is now searchable thanks to its new isSearchable prop (default to false).
  • The Multiselect component now has a minimal keyboard navigation that is not yet fully accessible.
  • The Multiselect component now supports disabled options (new MultiSelectOption's disabled prop).
  • The MultiselectOptionId type has been removed to use a simple string.
  • The Multiselect component has a new visible prop.
  • The Multiselect component renderValue prop has changed its parameter's type from a string[] (selected options) to a MultiselectOption[].
  • The Multiselect component's valueChanged event parameter has changed. To get the value:
- onValueChanged={(event) => {console.log(event.detail.selectedOptions)}}
+ onValueChanged={(value) => {console.log(value)}}

Radio Button

  • Several Radio Button props are now accessible directly via the inputProps prop, which exposes props of the inner <input type="radio"> HTML element:
    • checked is now inputProps.checked.
    • defaultChecked is now inputProps.defaultChecked.
    • inputId is now inputProps.id.
    • name is now inputProps.name.
    • required is now inputProps.required.
    • value is now inputProps.value.
  • The Radio Button component's valueChanged event has been replaced by the onChange callback (also accessible from inputProps):
- onValueChanged={(event) => {console.log(event.detail.value)}}
+ onChange={(event) => {console.log(event.target.value)}}

Radio Group

  • The RadioGroup component's valueChanged event has been replaced by the onChange callback:
- onValueChanged={(event) => {console.log(event.detail.value)}}
+ onChange={(event) => {console.log(event.target.value)}}

Slider

  • The default behavior of the Slider component has changed. If you do not explicitly set a value, it will now default to the min value instead of 0.
  • The Slider component's valueChanged event parameter has changed. To get the value:
- onValueChanged={(event) => {console.log(event.detail)}}
+ onValueChanged={(value) => {console.log(value)}}

Split Button

  • The SplitButton component's icon prop now supports both a ReactElement and the string type for more flexible icon definition.
  • The Split Button component's options icon (SplitButtonOption component's icon prop) now supports both a ReactElement and the string type for more flexible icon definition.
  • The Split Button component's actionButton event has changed its signature that now has an empty parameter.
  • The Split Button component's valueChanged event parameter has changed. To get the value:
- onValueChanged={(event) => {console.log(event.detail)}}
+ onValueChanged={(value) => {console.log(value)}}

Tabs

  • The Tabs component now support two modes supported by the enableAutoActive prop (default to true):
    • When set to true, the active tab is automatically updated by manipulating the activeId prop of the Tabs component, along with an onActiveIdChanged event to handle active tab changes. To support this, each Tab component must have a unique id.
    • When set to false, the active state is controlled via an active prop. Be careful, before Tabs generated automatic ids. This has changed as you need to set id yourself.
  • To migrate, you can use the default behavior of enableAutoActive:
- <Tabs>
- <Tab active label="Item 1"></Tab>
- <Tab label="Item 2"></Tab>
+ <Tabs activeId="tab-item-1">
+ <Tab id="tab-item-1" label="Item 1"></Tab>
+ <Tab id="tab-item-2" label="Item 2"></Tab>
</Tabs>
  • The Tabs component has an extra clickTab event that can be used to replace the Tab components' clickedTabEvent that has been removed.
  • The Tab component has a new active prop.
  • The Tab component's icon prop now supports both a ReactElement and the string type for more flexible icon definition.

Tag

  • The Tag component's icon prop now supports both a ReactElement and the string type for more flexible icon definition.
  • The Tag component's clickedTagButtonEvent and clickedTagEvent event have changed their signature that now have an empty parameter.
  • The TagButton component's clickedTagButton event has been replaced by the onClick handler, whose the event parameter content might differ.

Text Area

  • The Text Area component has been renamed from TextArea to Textarea. The derivative types and props too:
    • TextAreaSize is now TextareaSize.
    • TextAreaSeverity is now TextareaSeverity.
  • Text Area props has been replaced by the textareaProps prop, which exposes props of the inner <textarea> HTML element:
    • inputId is now textareaProps.id.
    • name is now textareaProps.name.
    • placeholder is now textareaProps.placeholder.
    • required is now textareaProps.required.
    • value is now textareaProps.value.
  • The Text Area component's valueChanged event has been replaced by the onChange callback (also accessible from textareaProps):
- onValueChanged={(event) => {console.log(event.detail.value)}}
+ onChange={(event) => {console.log(event.target.value)}}
  • The Text Area component's blur and focus events still exist, but their parameters have changed as they come from the native inner <textarea>.

Text Input

  • Text Input props has been replaced by the inputProps prop, which exposes props of the inner <input> HTML element:
    • autocomplete is now inputProps.autocomplete.
    • autofocus is now inputProps.autofocus.
    • inputId is now inputProps.id.
    • name is now inputProps.name.
    • placeholder is now inputProps.placeholder.
    • readonly is now inputProps.readonly.
    • required is now inputProps.required.
    • type is now inputProps.type.
    • value is now inputProps.value.
    • TextInputType has been removed as the type prop is propagated automatically, the type can be inferred from the HTML input element type attribute itself.
  • The Text Input component's leftIcon and rightIcon props now support both a ReactElement and the string type for more flexible icon definition.
  • The Text Input component's valueChanged event has been replaced by the onChange callback:
- onValueChanged={(event) => {console.log(event.detail.value)}}
+ onChange={(event) => {console.log(event.target.value)}}
  • The Text Input component's blur and focus events still exist, but their parameters have changed as they come from the native inner <input>.

Toggle Switch

  • Several Toggle Switch props are now accessible directly via the inputProps prop, which exposes props of the inner <input type="checkbox"> HTML element:
    • checked is now inputProps.checked.
    • defaultChecked is now inputProps.defaultChecked.
    • inputId is now inputProps.id.
    • name is now inputProps.name.
  • The Toggle Switch component's valueChanged event has been replaced by the onChange callback (also accessible from inputProps):
- onValueChanged={(event) => {console.log(event.detail.checked)}}
+ onChange={(event) => {console.log(event.target.checked)}}

Tooltip

  • The Tooltip title prop has been renamed to tooltipTitle.

Typography

  • TagType has a stricter type from string to 'h1' | 'h2' | 'p' | 'span'.

Spotted a bug, have a question, or want to suggest a new feature?

Submit an issue on GitLab