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/reactwhich 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/react2library. For example,QtmButtonis nowButton. To assist with migration, aliasing can be used likeimport { Button as QtmButton } from '@qtm/react2. - Removal of Web Component Dependency: The
@qtm/react2package 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
iconprop. - Button's
leftIconandrightIconprops. - MenuItemList's MenuItemType
iconprop. - SplitButton's SplitButtonType and SplitButtonOption
iconprops. - Tab's
iconprop. - Tag's
iconprop. - TextInput's
leftIconandrightIconprops.
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"withmy-propertyormy-property={true} - Replace
my-property="false"withmy-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'siconprop) now supports both aReactElementand thestringtype, allowing more flexible icon definitions.
Checkbox
- Several Checkbox props are now accessible directly via the
inputPropsprop, which exposes props of the inner<input type="checkbox">HTML element:checkedis nowinputProps.checkedorinputProps.defaultCheckedbased on whether the component is controlled or uncontrolled.inputIdis nowinputProps.id.nameis nowinputProps.name.requiredis nowinputProps.required.
- The Checkbox component's
valueChangedevent has been replaced by theonChangecallback (also accessible frominputProps):
- 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.
Dropdown
- The Dropdown component's
visibleChangeevent has changed; previously, thevisiblevalue was accessed viaevent.detail.visible, but it is now directly available asevent. - The Dropdown component's
clickOutsideevent has changed; it now uses a simpler event signature without any parameters. - The
DropdownTriggercomponentdisabledprop has been removed as what's important is the disabled state of the dropdown trigger child itself. - The
DropdownTriggercomponent doesn't have anymore atriggerEventevent, as it was used as a private implementation detail.
Dropdown Select
DropdownSelectOptiontype has been renamed toDropdownSelectItemto avoid naming conflict with the DropdownSelectOption component.- The Dropdown Select component is now searchable thanks to its new
isSearchableprop (default tofalse). - 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'sdisabledprop). - The Dropdown Select component has a new
visibleprop. - The Dropdown Select component's
valueChangedevent 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
clickOptionevent.
Form Label
- React replaces the
forattribute withhtmlForto avoid conflicts and ensure compatibility with JavaScript.
Icon
IconTypehas been renamed toIconProps.
Menu
MenuItemItemTypehas been renamed toMenuItemType.MenuItemListcomponent'senableAutoActiveprop is now set by default totrue. To maintain the previous behavior, review all instances ofMenuItemListin your codebase. If you wish to disable the new auto-active feature, explicitly setenableAutoActivetofalse. Alternatively, to take advantage of the new feature, ensure each menu item (or sub-menu item) has a uniqueidand remove any manually setactiveprops, allowing the auto-active logic to handle them automatically.MenuItemListcomponent'sactiveIdChanged,clickItem, andcollapsedIdsChangedevent 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)}}
MenuItemcomponent'sitem(that was hidden from the docs) has been removed.MenuItemcomponent'sclickedMenuItemhas been replaced with the native<div>'sonClickhandler.MenuItemLabelcomponent'sclickEventhas been replaced with the native<div>'sonClickhandler.SubmenuItemcomponent'sclickedSubmenuItemhas been replaced with the native<div>'sonClickhandler.
Modal
- The Modal component's
closeModalevent has changed its signature that now has an empty parameter. ModalHeader'sModalHeaderTypeis now'large' | 'medium' | 'small'.- The Modal component's
closedButtonevent has been renamed to use theonCloseButton, whose signature has changed and now has an empty parameter.
Multiselect
- The Multiselect component is now searchable thanks to its new
isSearchableprop (default tofalse). - The Multiselect component now has a minimal keyboard navigation that is not yet fully accessible.
- The Multiselect component now supports disabled options (new
MultiSelectOption'sdisabledprop). - The
MultiselectOptionIdtype has been removed to use a simplestring. - The Multiselect component has a new
visibleprop. - The Multiselect component
renderValueprop has changed its parameter's type from astring[](selected options) to aMultiselectOption[]. - The Multiselect component's
valueChangedevent 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
inputPropsprop, which exposes props of the inner<input type="radio">HTML element:checkedis nowinputProps.checked.defaultCheckedis nowinputProps.defaultChecked.inputIdis nowinputProps.id.nameis nowinputProps.name.requiredis nowinputProps.required.valueis nowinputProps.value.
- The Radio Button component's
valueChangedevent has been replaced by theonChangecallback (also accessible frominputProps):
- onValueChanged={(event) => {console.log(event.detail.value)}}
+ onChange={(event) => {console.log(event.target.value)}}
Radio Group
- The RadioGroup component's
valueChangedevent has been replaced by theonChangecallback:
- onValueChanged={(event) => {console.log(event.detail.value)}}
+ onChange={(event) => {console.log(event.target.value)}}
Slider
- The default behavior of the
Slidercomponent 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
valueChangedevent parameter has changed. To get the value:
- onValueChanged={(event) => {console.log(event.detail)}}
+ onValueChanged={(value) => {console.log(value)}}
Split Button
- The
SplitButtoncomponent'siconprop now supports both aReactElementand thestringtype for more flexible icon definition. - The Split Button component's options icon (
SplitButtonOptioncomponent'siconprop) now supports both aReactElementand thestringtype for more flexible icon definition. - The Split Button component's
actionButtonevent has changed its signature that now has an empty parameter. - The Split Button component's
valueChangedevent 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
enableAutoActiveprop (default totrue):- When set to
true, the active tab is automatically updated by manipulating theactiveIdprop of the Tabs component, along with anonActiveIdChangedevent to handle active tab changes. To support this, each Tab component must have a uniqueid. - When set to
false, the active state is controlled via anactiveprop. Be careful, before Tabs generated automaticids. This has changed as you need to set id yourself.
- When set to
- 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
clickTabevent that can be used to replace the Tab components'clickedTabEventthat has been removed. - The Tab component has a new
activeprop. - The Tab component's
iconprop now supports both aReactElementand thestringtype for more flexible icon definition.
Tag
- The Tag component's
iconprop now supports both aReactElementand thestringtype for more flexible icon definition. - The Tag component's
clickedTagButtonEventandclickedTagEventevent have changed their signature that now have an empty parameter. - The
TagButtoncomponent'sclickedTagButtonevent has been replaced by theonClickhandler, whose the event parameter content might differ.
Text Area
- The Text Area component has been renamed from
TextAreatoTextarea. The derivative types and props too:TextAreaSizeis nowTextareaSize.TextAreaSeverityis nowTextareaSeverity.
- Text Area
propshas been replaced by thetextareaPropsprop, which exposes props of the inner<textarea>HTML element:inputIdis nowtextareaProps.id.nameis nowtextareaProps.name.placeholderis nowtextareaProps.placeholder.requiredis nowtextareaProps.required.valueis nowtextareaProps.value.
- The Text Area component's
valueChangedevent has been replaced by theonChangecallback (also accessible fromtextareaProps):
- onValueChanged={(event) => {console.log(event.detail.value)}}
+ onChange={(event) => {console.log(event.target.value)}}
- The Text Area component's
blurandfocusevents still exist, but their parameters have changed as they come from the native inner<textarea>.
Text Input
- Text Input
propshas been replaced by theinputPropsprop, which exposes props of the inner<input>HTML element:autocompleteis nowinputProps.autocomplete.autofocusis nowinputProps.autofocus.inputIdis nowinputProps.id.nameis nowinputProps.name.placeholderis nowinputProps.placeholder.readonlyis nowinputProps.readonly.requiredis nowinputProps.required.typeis nowinputProps.type.valueis nowinputProps.value.TextInputTypehas been removed as thetypeprop is propagated automatically, the type can be inferred from the HTML input elementtypeattribute itself.
- The Text Input component's
leftIconandrightIconprops now support both aReactElementand thestringtype for more flexible icon definition. - The Text Input component's
valueChangedevent has been replaced by theonChangecallback:
- onValueChanged={(event) => {console.log(event.detail.value)}}
+ onChange={(event) => {console.log(event.target.value)}}
- The Text Input component's
blurandfocusevents 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
inputPropsprop, which exposes props of the inner<input type="checkbox">HTML element:checkedis nowinputProps.checked.defaultCheckedis nowinputProps.defaultChecked.inputIdis nowinputProps.id.nameis nowinputProps.name.
- The Toggle Switch component's
valueChangedevent has been replaced by theonChangecallback (also accessible frominputProps):
- onValueChanged={(event) => {console.log(event.detail.checked)}}
+ onChange={(event) => {console.log(event.target.checked)}}
Tooltip
- The Tooltip
titleprop has been renamed totooltipTitle.
Typography
TagTypehas a stricter type fromstringto'h1' | 'h2' | 'p' | 'span'.