Migration guide
Neutral selected states
When the platform-dst-tokens-finesse feature flag is enabled, this component uses the new neutral treatment for selected states.
Motion in Early Access
Motion updates for multi-value Select tags are in Early Access and available behind the platform-dst-motion-uplift-labels feature flag.
Note: Select is migrated to Compiled in v22.0. Follow this migration guide to migrate Select in pre-22.0 versions.
Overview
Atlaskit Select has been migrated from Emotion to Compiled CSS-in-JS to improve performance and enable React 18 Streaming SSR compatibility. This guide will help you migrate your existing Select customizations to the new approach.
Migration approach
The migration introduces an enhanced components API that replaces the styles prop with the
xcss prop for better performance and type safety.
Before and after comparison
Old approach (Emotion with styles prop)
import Select from '@atlaskit/select';
import { token } from '@atlaskit/tokens';
const customStyles = {
control: (base, state) => ({
...base,
backgroundColor: token('elevation.surface'),
}),
};
const MyComponent = () => <Select options={options} styles={customStyles} />;New approach (Compiled with components API)
/** @jsx jsx */
import { cssMap, cx } from '@atlaskit/css';
import Select, { components } from '@atlaskit/select';
import { token } from '@atlaskit/tokens';
const controlStyles = cssMap({
root: {
backgroundColor: token('elevation.surface'),
},
});
const MyComponent = () => (
<Select
options={options}
components={{
Control: (props) => <components.Control {...props} xcss={controlStyles.root} />,
}}
/>
);Component mapping reference
When migrating from styles prop to components API, use this mapping:
styles prop key | components API key |
|---|---|
| clearIndicator | ClearIndicator |
| container | SelectContainer |
| control | Control |
| dropdownIndicator | DropdownIndicator |
| group | Group |
| groupHeading | GroupHeading |
| indicatorsContainer | IndicatorsContainer |
| input | Input |
| loadingIndicator | LoadingIndicator |
| loadingMessage | LoadingMessage |
| menu | Menu |
| menuList | MenuList |
| menuPortal | MenuPortal |
| multiValue | MultiValueContainer |
| multiValueLabel | MultiValueLabel |
| multiValueRemove | MultiValueRemove |
| noOptionsMessage | NoOptionsMessage |
| option | Option |
| placeholder | Placeholder |
| singleValue | SingleValue |
| valueContainer | ValueContainer |
Step-by-step migration process
1. Update imports
// Add these imports
/** @jsx jsx */
import { cssMap, cx } from '@atlaskit/css';
import Select, { components } from '@atlaskit/select';2. Convert styles to cssMap
// Old styles object
const customStyles = {
control: (base, state) => ({
...base,
minHeight: '40px',
borderRadius: token('radius.large'),
}),
};
// New cssMap approach
const controlStyles = cssMap({
root: {
minHeight: '40px',
borderRadius: token('radius.large'),
},
});3. Replace styles prop with components API
// Old approach
<Select styles={customStyles} />
// New approach
<Select
components={{
Control: (props) => (
<components.Control {...props} xcss={controlStyles.root} />
),
}}
/>Advanced migration patterns
State-based styling
const controlStyles = cssMap({
root: {
minHeight: '32px',
borderRadius: token('radius.small'),
},
focused: {
borderColor: token('color.border.focused'),
},
disabled: {
cursor: 'not-allowed',
},
});
// Usage with conditional styling
<components.Control
{...props}
xcss={cx(
controlStyles.root,
props.isFocused && controlStyles.focused,
props.isDisabled && controlStyles.disabled,
)}
/>;Multi-value styling
const multiValueStyles = cssMap({
container: {
backgroundColor: token('color.background.warning'),
},
label: {
color: token('color.text.warning'),
fontWeight: 'bold',
},
remove: {
color: token('color.text.warning'),
'&:hover': {
backgroundColor: token('color.background.warning.subtle'),
},
},
});
// Usage
<Select
components={{
MultiValueContainer: (props) => (
<components.MultiValueContainer {...props} xcss={multiValueStyles.container} />
),
MultiValueLabel: (props) => (
<components.MultiValueLabel {...props} xcss={multiValueStyles.label} />
),
MultiValueRemove: (props) => (
<components.MultiValueRemove {...props} xcss={multiValueStyles.remove} />
),
}}
/>;Backward compatibility
What still works
Most existing styles prop definitions will continue to work, but with limitations:
// This will still work (basic inline styles)
<Select
styles={{
control: (base) => ({
...base,
backgroundColor: token('elevation.surface'),
minHeight: '40px',
}),
}}
/>What no longer works
The following CSS selectors are not supported in the styles prop:
- Pseudo-classes/elements:
:hover,:focus,:active,:disabled,:before,:after - Attribute selectors:
[type="text"],[disabled] - Combinators:
>(child),+(adjacent sibling),~(general sibling) - Universal selector:
* - ID selector:
#myId - Class selector:
.myClass - At-rules:
@media,@supports - Parent selector:
& - Namespace separator:
| - Attribute operators:
^=,$=,=
If your styles use any of these selectors, you must migrate to the components API.
Performance best practices
- Use Design Tokens: Always use
@atlaskit/tokensfor consistent theming. - Minimize Style Objects: Keep
cssMapobjects focused and reusable. - Avoid using styles props: Migrate away from
stylesprop completely. - Leverage State Props: Use
componentprops for conditional styling instead of complex selectors.