Upgrading to v1

Chakra UI v1.0 is focused on improving the ideas and concepts from v0.8 to make it even easier to create, theme and extend components.

While there are quite a number of new features we've added, we focused on making Chakra UI a stable base to build your own design systems on top of. In the end, we want make you feel more confident using Chakra UI in production.


Highlights#

Theming API: Chakra UI now provides a new theming API which makes it easy to style components and their modifiers (sizes, variants, and color scheme) from your theme.

Color mode improvement: We've fixed the bugs related to Color mode and made it possible to persist color mode, set initial color mode, and lock specific components to a certain color mode.

Better TypeScript support: This means all components have very good TypeScript support and most low-level components like Box, Flex will support the as prop and types will be extracted properly.

Theme-aware sx prop: Just like theme-ui, we've added support for the sx prop to help you add theme-aware styles directly on any Chakra component. This is useful if you're not a fan of style props, and prefer passing all styles in one object.

Deprecated PseudoBox: We've removed PseudoBox and merged all its props with Box so you can use pseudo style props, like _hover, _active in any Chakra components.

Dropped Support of IE11: We've dropped support of IE11 reason


Upgrade steps#

Here's a list of steps to migrate your project to v1. Don't worry if your styles aren't exactly the same, this is to be expected and following these steps will fix it.

1. Update your dependencies#

  • Install the framer-motion package. We use this to manage animations and transitions within components.

  • Remove the emotion-theming package. As at emotion v11, emotion-theming as been removed and all it's functionality as been migrated to @emotion/react.

  • Rename the @emotion/core package to @emotion/react. @emotion/core was recently changed to @emotion/react following the v11 release by the emotionjs team.

  • Rename the @chakra-ui/core package to @chakra-ui/react.

  • Update the @emotion/styled package to v11.

"dependencies": {
- "@chakra-ui/core": "^0.8.0",
+ "@chakra-ui/react": "^1.0.0",
"framer-motion": ">=3.0.0",
- "@emotion/core": "^10.0.10",
+ "@emotion/react": "^11.0.0",
"@emotion/styled": "^11.0.0",
- "emotion-theming": "10.0.10"
}

Please note that when using Chakra UI in a TypeScript project, a minimum TypeScript version of 3.8.0 is required.

Notes on Icons#

Chakra moved all icons to a separate package @chakra-ui/icons. We recommend using react-icons in your projects considering it has a robust set of icons. However, you can still install this package.

2. Update the ThemeProvider#

Swap out ThemeProvider with ChakraProvider to make setup cleaner. ChakraProvider adds the following providers for you automatically:

  • ThemeProvider: Provides the theming context for all components.
  • ColorModeProvider: Provides color mode (light or dark) context to all components.
  • GlobalStyle: Provides the global styles defined in theme.styles.global to your application.

Optionally via prop:

  • CSSReset: To omit the recommended CSSReset, pass resetCSS={false}.
  • PortalManager: Manages portals and nested portals without using z-index in your application. Pass the portalZIndex prop.
- <ThemeProvider>
+ <ChakraProvider>
- <CSSReset />
<App />
+ </ChakraProvider>
- </ThemeProvider>

3. Rename variantColor to colorScheme#

Fire up your "Find and Replace" tool in VSCode or IntelliJ. Find variantColor and replace with colorScheme.

Reason: We renamed this prop to make it easier to understand that this prop represents a visual color scheme, not a css color attribute.

4. Update layout size prop#

Change size prop to width or w and height, or h. If you'd like to use only one prop to manage this, you can rename it to boxSize.

- <Box size="40px" />
+ <Box w="40px" h="40px" />
# or
+ <Box boxSize="40px" />

We strongly recommend using the width and height props

Reason: We think the size prop should only be used for component size modifiers. The size prop has caused a lot of confusion in the past because, in some components (e.g. Button), it means the visual size and in others (e.g Box), it means width and height.

5. Replace elements#

PseudoBox#

PseudoBox is now deprecated and its props can now be directly applied to Box. Replace all PseudoBox components with Box.

- <PseudoBox
+ <Box
>
- <PseudoBox
+ <Box
_hover={{ fontWeight: 'semibold' }}
_groupHover={{ color: 'tomato' }}
>
- </PseudoBox>
+ </Box>
- </PseudoBox>
+ </Box>

Callout#

Callout is now deprecated and you can use an Alert instead.

- <Callout
+ <Alert
mt={4}
w="90%"
bg="black"
variant="left-accent"
>
- </Callout>
+ </Alert>

6. Update theme breakpoints#

You may skip this if you didn't customize your breakpoints.

To provide easier extensibility and typesafety, breakpoints should now be created through createBreakpoints by passing an object:

+ import { extendTheme } from "@chakra-ui/react"
+ import { createBreakpoints } from "@chakra-ui/theme-tools"
+ const breakpoints = createBreakpoints({
+ sm: "30em",
+ md: "48em",
+ lg: "62em",
+ xl: "80em",
+ })
const overrides = {
- breakpoints: ["30em", "48em", "62em", "80em"]
+ breakpoints,
}
+ const customTheme = extendTheme(overrides)

Please note that unless you plan overriding all components, sm to xl are required.

You may of course add for example xxl or other breakpoints in between - createBreakpoints will sort in ascending order. It is adviseable to not mix css units.

Reason: Previously, breakpoints on a theme had to be an array with your breakpoints in ascending order which made it hard to reference which value was correlating to md etc. Also, you had to manually manipulate the array by defining properties on it, which was often overlooked and not typesafe.

7. ColorModeScript (optional)#

You can skip this if you are not already using the color mode feature.

To keep color mode settings in sync across pages, add the ColorModeScript.

For exhaustive examples, please visit Features > Color Mode # Add ColorModeScript.


Component Updates#

We've updated the API of some components to fix bugs, improve usability, types and accessibility.

Accordion#

  • Update all imports of AccordionHeader to AccordionButton. This is to remove the notion that it is a header when it is actually a button.
- import { AccordionHeader } from "@chakra-ui/react"
+ import { AccordionButton } from "@chakra-ui/react"

WAI-ARIA guidelines require that accordion buttons be wrapped in the appropriate heading tag h2-h6 based on the page heading flow.

We think the name AccordionHeader might mislead users to think we handle this out of the box when we don't. Here's how to handle this:

<Accordion>
<AccordionItem>
<h3>
<AccordionButton>This is the button</AccordionButton>
</h3>
<AccordionPanel>This is the content</AccordionPanel>
</AccordionItem>
</Accordion>
  • You can no longer use AccordionItem in isolation, it must be used within Accordion.

AspectRatioBox#

  • Change all imports of AspectRatioBox to AspectRatio.
- import { AspectRatioBox } from "@chakra-ui/react"
+ import { AspectRatio } from "@chakra-ui/react"

Removed support for the addSeparator prop.

Button#

  • We've unified the usage of all icon props to only accept a React element. Update all icon names used in leftIcon or rightIcon to the equivalent icon React element.

Replacement logic: If leftIcon is email, then replace it with <EmailIcon/> from Chakra.

import { PhoneIcon } from "@chakra-ui/icons"
- <Button leftIcon="phone">Call</Button>
+ <Button leftIcon={<PhoneIcon />}>Call</Button>

This reduces the effort needed to use custom icons, eliminates TypeScript errors, and reduces unused icons bloating your app.

  • Renamed variantColor to colorScheme

  • Removed negative side margins on leftIcon and rightIcon elements. We believe the user should handle these side margins. #1024

Checkbox#

  • Change variantColor to colorScheme
- <Checkbox variantColor="blue">Option</Checkbox>
+ <Checkbox colorScheme="blue">Option</Checkbox>
  • Deprecated the isFullWidth prop. Checkbox now takes up the width of its parent by default.

  • To allow for better checkbox group layout, the CheckboxGroup component no longer supports every style prop.

    You can now only pass size, variant, and colorScheme in addition to CheckboxGroup-specific props (value, defaultValue, and onChange).

// before
<CheckboxGroup isInline spacing="40px" defaultValue={["one", "two"]}>
<Checkbox value="one">One</Checkbox>
<Checkbox value="two">Two</Checkbox>
<Checkbox value="three">Three</Checkbox>
</CheckboxGroup>
// after
<CheckboxGroup defaultValue={["one", "two"]}>
<Stack spacing="40px">
<Checkbox value="one">One</Checkbox>
<Checkbox value="two">Two</Checkbox>
<Checkbox value="three">Three</Checkbox>
</Stack>
</CheckboxGroup>

We believe a checkbox group's layout should be managed by your design requirements. The checkboxes can be grouped using Stack, placed in a grid using SimpleGrid or made to wrap automatically using Wrap.

ColorMode#

  • Color mode now persists correctly when you refresh the page. All you need to do is add ColorModeScript script as the first child of body.

    Here's how to add it for Next.js:

// pages/_document.js
import { ColorModeScript } from "@chakra-ui/react"
export default class Document extends NextDocument {
static getInitialProps(ctx) {
return NextDocument.getInitialProps(ctx)
}
render() {
return (
<Html>
<Head />
<body>
{/* 👇 Here's the script */}
<ColorModeScript />
<Main />
<NextScript />
</body>
</Html>
)
}
}

Here's how to add it for Gatsby:

Changes#

  • The Gatsby plugin has been renamed from gatsby-plugin-chakra-ui to @chakra-ui/gatsby-plugin. Please make sure to have updated this when installing Chakra UI in your next Gatsby project.
// gatsby-ssr.js
export const onRenderBody = ({ setPreBodyComponents }) => {
setPreBodyComponents([<ColorModeScript key="chakra-ui-no-flash" />])
}

You can also install the @chakra-ui/gatsby-plugin package which automatically configures ColorModeScript along with ChakraProvider.

Editable#

The onRequestEdit prop has been renamed to onEdit. This applies to both the prop passed to Editable as well as the prop in its render props.

Icons#

  • Basic interface icons provided by Chakra have moved to the @chakra-ui/icons package. Replace all <Icon name="..." /> elements imported from @chakra-ui/react with equivalent React elements imported from @chakra-ui/icons.

    Replacement logic: If <Icon name="search" /> is used, then replace it with <SearchIcon /> from Chakra icons package.

- import { Icon } from "@chakra-ui/react"
- <Icon name="search" />
+ import { SearchIcon } from "@chakra-ui/icons"
+ <SearchIcon />

Existing icons will appear as a question mark until refactored.

  • We changed the way custom icons are created. Instead of adding custom icons to theme create your own icons using the createIcon utility:
import { createIcon } from "@chakra-ui/react"
export const UpDownIcon = createIcon({
displayName: "UpDownIcon",
viewBox: "-1 -1 9 11",
d:
"M 3.5 0L 3.98809 -0.569442L 3.5 -0.987808L 3.01191 -0.569442L 3.5 0ZM 3.5 9L 3.01191 9.56944L 3.5 9.98781L 3.98809 9.56944L 3.5 9ZM 0.488094 3.56944L 3.98809 0.569442L 3.01191 -0.569442L -0.488094 2.43056L 0.488094 3.56944ZM 3.01191 0.569442L 6.51191 3.56944L 7.48809 2.43056L 3.98809 -0.569442L 3.01191 0.569442ZM -0.488094 6.56944L 3.01191 9.56944L 3.98809 8.43056L 0.488094 5.43056L -0.488094 6.56944ZM 3.98809 9.56944L 7.48809 6.56944L 6.51191 5.43056L 3.01191 8.43056L 3.98809 9.56944Z",
})

As a convenience you can also import createIcon from the icons package along with other icons:

import { createIcon, MoonIcon, SunIcon } from "@chakra-ui/icons"

Icon Button#

  • We've unified the usage of all icon props to only accept a React element. Update all icon names used in icon to the equivalent icon React element.

Replacement logic: If icon is email, then replace it with <EmailIcon/> from Chakra.

import { PhoneIcon } from "@chakra-ui/react"
- <IconButton icon="phone">Call</IconButton>
+ <IconButton icon={<PhoneIcon />}>Call</IconButton>

This reduces the effort needed to use custom icons, eliminates TypeScript errors, and reduces unused icons bloating your app.

  • Renamed variantColor to colorScheme.

Skeleton#

Renamed colorStart and colorEnd props to startColor and endColor respectively.

Image#

Resolved SSR issue with Next.js. If you still run into issues, we recommend using the Img component which is a regular img tag with support for Chakra props.

Input#

When using InputAddon, you no longer need to pass border radius properties to the Input. InputGroup will intelligently detect the addon and apply the necessary border to the input.

Due to accessibility reasons, we've deprecated the isDisabled prop for Link.

List#

Renamed stylePos to stylePosition

ListIcon#

We deprecated the icon prop. To change the icon rendered, kindly use the as prop instead.

Stack#

  • To reduce the API surface area, we've deprecated the isReversed props in favor of the direction prop.
- <Stack isReversed>
+ <Stack direction="row-reverse">
<Box />
<Box />
</Stack>
  • Added support for responsive direction and spacing props.
<Stack spacing={["16px", "32px"]} direction={["column", "row"]}>
<Box />
<Box />
</Stack>
  • All popper related props that used to be passed to MenuList component, should now be passed to Menu.
  • The placement prop has moved from MenuList to Menu.
  • Removed addAriaLabels and formatIds props in favor of passing a top-level id prop to the modal.

  • Removed preserveScrollBarGap prop. We preserve scroll bar gap by default to prevent any layout shift.

  • Only pass size values defined in the components theme. Hard-coded values will be ignored. Update the styles in theme.components.Modal to reflect your custom values.

  • You can now disable focus trap by passing trapFocus={false}.

  • Modal comes with preset transitions to make it easy for you. You can remove any existing Scale, ScaleFade or SlideFade components.

// before
<SlideIn in={isOpen}>
{(styles) => (
<Modal onClose={onClose} isOpen>
<ModalOverlay opacity={styles.opacity} />
<ModalContent pb={5} {...styles}>
<ModalHeader>Login now</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Lorem count={2} />
</ModalBody>
</ModalContent>
</Modal>
)}
</SlideIn>
// after
<Modal motionPreset="slideInBottom" onClose={onClose} isOpen={isOpen}>
<ModalOverlay />
<ModalContent pb={5}>
<ModalHeader>Login now</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Lorem count={2} />
</ModalBody>
</ModalContent>
</Modal>

Progress#

Changed color prop to colorScheme.

- <Progress color="blue"/>
+ <Progress colorScheme="blue"/>

CircularProgress#

  • trackColor prop now takes a specific theme color or a valid css color.
  • Changed the thickness prop to point to an actual thickness value in px (e.g. thickness={4})
- <CircularProgress value={59} size="100px" thickness={0.1} />
+ <CircularProgress value={59} size="100px" thickness={10} />

Radio#

  • Changed variantColor prop to colorScheme.
- <Radio variantColor="blue">Option</Radio>
+ <Radio colorScheme="blue">Option</Radio>
  • Deprecated the isFullWidth prop. The Radio takes up the width of its parent by default.

  • Deprecated the RadioButton component. Use the useRadio hook to create custom radio buttons. Learn more about creating custom radio buttons.

  • The useRadio hook is exported with state and focus management logic for use in creating tailor-made radio component for your application

RadioGroup#

  • Deprecated the isFullWidth prop. The RadioGroup takes up the width of the parent by default.

  • Deprecated the RadioButtonGroup component. Use the useRadioGroup hook to control a group of custom radio buttons. Learn more about creating custom radio buttons.

  • To allow for better Radio group layout, the RadioGroup component no longer supports every style prop. You can only pass size, variant, and colorScheme in addition to RadioGroup props (value, defaultValue, and onChange).

// before
<RadioGroup isInline defaultValue="one">
<Radio value="one">One</Radio>
<Radio value="two">Two</Radio>
<Radio value="three">Three</Radio>
</RadioGroup>
// after
<RadioGroup defaultValue="one">
<Stack direction="row">
<Radio value="one">One</Radio>
<Radio value="two">Two</Radio>
<Radio value="three">Three</Radio>
</Stack>
</RadioGroup>
  • The onChange callback now returns the selected value not the event.
const [value, setValue] = React.useState("one")
// before
<RadioGroup value={value} onChange={e => setValue(e.target.value)}>
<Radio value="one">One</Radio>
<Radio value="two">Two</Radio>
<Radio value="three">Three</Radio>
</RadioGroup>
// after
<RadioGroup value={value} onChange={val => setValue(val)}>
<Stack direction="row">
<Radio value="one">One</Radio>
<Radio value="two">Two</Radio>
<Radio value="three">Three</Radio>
</Stack>
</RadioGroup>

Slider#

  • Update JSX structure: Wrap SliderFilledTrack with SliderTrack.
// before
<Slider defaultValue={30}>
<SliderTrack />
<SliderFilledTrack />
<SliderThumb />
</Slider>
// after
<Slider defaultValue={30}>
<SliderTrack>
<SliderFilledTrack />
</SliderTrack>
<SliderThumb />
</Slider>

Switch#

Rename the color prop to colorScheme.

- <Switch color="blue"/>
+ <Switch colorScheme="blue"/>

Tabs#

Change variantColor prop to colorScheme.

Tags#

  • Change variantColor to colorScheme.
- <Tag variantColor="blue"/>
+ <Tag colorScheme="blue"/>
  • Added support for isDisabled prop on the TagCloseButton component.
<Tag variant="solid" size="sm" colorScheme="cyan">
<TagLabel>Tab Label</TagLabel>
<TagCloseButton isDisabled />
</Tag>
  • Default size was changed from lg to md.

Toast#

  • Removed react-spring dependency in favor of framer-motion.
  • Added support for duplicate toast prevention using toast.isActive method.
  • Added support to programmatically close one or all toasts using toast.close or toast.closeAll methods.
  • Added support to programmatically update a toast using toast.update method.
  • Added support for onCloseComplete prop, which is a callback function that is invoked when the toast closes.

Wrap (for rc versions)#

  • Children of Wrap must now be wrapped in WrapItem. This makes it easy to customize the WrapItem using the sx prop.
// before
<Wrap spacing="30px">
<Center w="180px" h="80px" bg="red.200">Box 1</Center>
<Center w="180px" h="80px" bg="green.200">Box 2</Center>
<Center w="180px" h="80px" bg="tomato">Box 3</Center>
</Wrap>
// after
<Wrap spacing="30px">
<WrapItem>
<Center w="180px" h="80px" bg="red.200">Box 1</Center>
</WrapItem>
<WrapItem>
<Center w="180px" h="80px" bg="green.200">Box 2</Center>
</WrapItem>
<WrapItem>
<Center w="180px" h="80px" bg="tomato">Box 3</Center>
</WrapItem>
</Wrap>

Transition Components#

All transition components like Collapse, Fade, SlideFade, etc. use the in prop to trigger its transition/animation, instead of isOpen. Change the isOpen prop to in

CSS Reset#

  • Removed the config prop, in favor of adding global styles to theme.styles.global.
  • If you want to remove focus for non-keyboard interactions, install the focus-visible package.
yarn add focus-visible
# or
npm install focus-visible
# at the root of your application
import "focus-visible/dist/focus-visible"

Hooks#

  • useDisclosure now accepts object instead of boolean as initial values.
- const { isOpen, onToggle } = useDisclosure(true);
+ const { isOpen, onToggle } = useDisclosure({defaultIsOpen: true});

That's it! Welcome to Chakra UI v1 🥳.

If you still experience issues after migrating, feel free to create an issue or join our Discord chat here: https://discord.gg/dQHfcWF