Chakra UI v1.0 🎉
A simple guide to upgrade your existing Chakra UI projects to v1.0.
Chakra UI v1.0 is focused on improving the ideas and concepts from 0.x to make
even easier to create, theme, and extend components.
While there's quite a number of new exciting features we've added, we focused on
making Chakra UI a stable base to build your own design systems on, so that you
can 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 or locally using a chakra
factory function.
Color mode improvement: We've fixed the bugs related to Color mode and it's
now easy 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, etc. will
support the as
prop and types will be extracted properly.
Theme-aware css prop: Just like theme-ui
, we've added a __css
prop you
can use to add theme-aware styles.
Upgrade steps
Here's a list of steps to take in order to migrate your project safely. Don't
worry if your styles aren't exactly the same—this is to be expected.
1. Update your dependencies
Chakra no longer requires @emotion/styled
, @emotion/core
and
@emotion/theming
. If you're not using these libraries in your code, you can
safely remove them and update Chakra UI to v1.
We use only
@emotion/core
internally.
"dependencies": {
"@chakra-ui/core": "1.0.0-beta",
- "@emotion/styled": "10.X",
- "@emotion/theming": "10.x",
- "@emotion/core": "10.x"
}
Note on bundle size: Chakra UI now exports all components as separate
packages to make it easier to consume individual packages. For example, if you
use only Button
, you can now install @chakra-ui/button
along side its peer
dependency @chakra-ui/system
, and you're good to go!
2. Clone Chakra's default theme (Work in Progress)
Chakra no longer comes with the default theme pre-installed, so you'll need to
add it manually. Luckily for you, we've added a CLI tool for generating the
theme.
We believe that having the theme cloned to your project will help you learn
about the theme tokens (colors, fonts, component styles) and make it less
stressful for you to customize theme.
- Run
npx chakra init --theme
to clone the theme to your project. This
creates achakra
folder with the default theme inside.
npx chakra-cli init --theme
- Update the
ThemeProvider
in your app's root by passing thetheme
prop.
import { ThemeProvider, CSSReset } from "@chakra-ui/core"
import theme from "./chakra"
function AppRoot() {
return (
<ThemeProvider theme={theme}>
<CSSReset />
<App />
</ThemeProvider>
)
}
3. 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 - PortalManager: Manages portals and nested portals without using
z-index
in your application. - GlobalStyle: Provides the global styles defined in
theme.styles.global
to your application.
- <ThemeProvider theme={theme}>
+ <ChakraProvider theme={theme}>
<CSSReset />
<App />
+ </ChakraProvider>
- </ThemeProvider>
4. Rename variantColor to colorScheme
Fire up your "Find and Replace" tool in VSCode or IntelliJ. Find variantColor
and replace with colorScheme
.
Reason: We named this prop to make it easier to understand that this prop
represents a visual color scheme, not a css color attribute.
5. 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. Thesize
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. Update these prop names
These style props still work but we recommend renaming them to the new prop.
We now show a console warning when you use any of these deprecated props.
Deprecated Prop | New Prop |
---|---|
rounded | borderRadius |
roundedLeft | borderLeftRadius |
roundedRight | borderRightRadius |
roundedTop | borderTopRadius |
roundedTopLeft | borderTopLeftRadius |
roundedTopRight | borderTopRightRadius |
roundedBottomLeft | borderBottomLeftRadius |
roundedBottomRight | borderBottomRightRadius |
roundedBottom | borderBottomRadius |
bgImg | bgImage |
bgPos | bgPosition |
shadow | boxShadow |
listStyleImg | listStyleImage |
listStylePos | listStylePosition |
Component Updates
We've updated the API of some components to fix bugs and improve usability,
types and accessibility.
- All components now take the pseudo style props (
_hover
,_active
, etc.) - Improved TypeScript support for the
as
prop
Accordion
Can install as a stand-alone package: @chakra-ui/accordion
Changes
- Update all imports of
AccordionHeader
toAccordionButton
. This is to
remove the notion that it's a header when it's actually abutton
.
- import { AccordionHeader } from "@chakra-ui/core"
+ import { AccordionButton } from "@chakra-ui/core"
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
. We think most users don't do this by default but it's worth
noting.
Features
Keyboard Navigation: Accordion
now supports keyboard navigation between
accordion buttons. Pressing the up
and down
arrow keys will move focus
between accordion buttons.
AspectRatioBox
- Change all imports of
AspectRatioBox
toAspectRatio
- import { AspectRatioBox } from "@chakra-ui/core"
+ import { AspectRatio } from "@chakra-ui/core"
Avatar
Features
- You can now use a custom fallback avatar icon by passing the
icon
prop:
<Avatar src="john.png" name="John Doe" icon={<UserIcon />} />
-
You can now change the
borderRadius
of the avatar -
Theming Support: All design decisions for the Avatar are located in
chakra/components/Avatar
in your cloned theme, which means you can customize
the styles to suit your brand needs. -
Added
getInitials
prop to allow users to manage how initials are generated
from name. By default we merge the first characters of each word in thename
prop.
Breadcrumb
- Removed support for the
addSeparator
prop
Button
Changes
-
We've unified the usage of all icon props to only accept a React element.
Update all icon names used inleftIcon
orrightIcon
to the equivalent icon
React element.Replacement logic: If
leftIcon
isemail
, then replace it with
<EmailIcon/>
from Chakra.
import { PhoneIcon } from "@chakra-ui/core"
- <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
tocolorScheme
Features
- Added support for custom spinners using the
spinner
prop
import { BeatLoader } from "react-spinners"
function Example() {
return (
<Button isLoading colorScheme="blue" spinner={<BeatLoader color="white" />}>
Click me
</Button>
)
}
Checkbox
Changes
- Change
variantColor
tocolorScheme
- <Checkbox variantColor="blue">Option</Checkbox>
+ <Checkbox colorScheme="blue">Option</Checkbox>
-
Deprecated the
isFullWidth
prop.Checkbox
now takes up the width of the
parent by default. -
To allow for better checkbox group layout, the
CheckboxGroup
component no
longer supports every style prop. You can now only passsize
,variant
, and
colorScheme
in addition toCheckboxGroup
-specific props (value
,
defaultValue
, andonChange
).
// 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 usingStack
, placed in a grid
usingSimpleGrid
or made to wrap automatically usingWrap
.
Features
- Added the
iconColor
andiconSize
props to customize the default check icon
<Checkbox iconColor="blue" iconSize="1rem">
Option
</Checkbox>
- Added the
spacing
prop to customize the spacing between the checkbox and
label text
<Checkbox spacing="1rem">Option</Checkbox>
-
The
useCheckbox
hook is exported with state and focus management logic for
use in creating tailor-made checkbox component for your application -
The
useCheckboxGroup
hook is exported with state management logic for use in
creating tailor-made checkbox group component for your application
ColorMode
-
You can now set the initial color mode you want your application to start
with. Settheme.config.initialColorMode
tolight
ordark
const theme = { config: { initialColorMode: "dark", }, }
-
You can now update the color mode based on your user's device preference. Set
theme.config.useSystemColorMode
totrue
orfalse
const theme = { config: { useSystemColorMode: true, }, }
Bug Fix
-
Color mode now persists correctly when you refresh the page. All you need to
do is addInitialColorMode
script as the first child ofbody
.Here's how to add it for Next.js:
// pages/_app.js
import { InitialColorMode } from "@chakra-ui/core"
export default class Document extends NextDocument {
static async getInitialProps(ctx) {
const initialProps = await NextDocument.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<Html>
<Head />
<body>
{/* 👇 Here's the script */}
<InitializeColorMode />
<Main />
<NextScript />
</body>
</Html>
)
}
}
Here's how to add it for Gatsby:
// gatsby-ssr.js
export const onRenderBody = ({ setPreBodyComponents }) => {
setPreBodyComponents([<InitializeColorMode key="chakra-ui-no-flash" />])
}
You can also install the
gatsby-plugin-chakra-ui
package which automatically configures InitializeColorMode
along with
ChakraProvider
.
FormControl
-
We've improved the accessibility of the
FormControl
component. Here are the
changes:id
passed to the form control will be passed to the form input directlyFormLabel
will havehtmlFor
that points to theid
of the form inputFormErrorMessage
addsaria-describedby
andaria-invalid
pointing to
the form inputFormHelperText
adds/extendsaria-describedby
pointing to the form inputisDisabled
,isRequired
,isReadOnly
props passed toFormControl
will
cascade across all related components
-
FormLabel
is now aware of thedisabled
,focused
anderror
state of the
form input. This helps you style the label accordingly using the_disabled
,
_focus
, and_invalid
style props. -
If you render
FormErrorMessage
andisInvalid
isfalse
orundefined
,
FormErrorMessage
won't be visible. The only way to make it visible is by
passingisInvalid
and setting it totrue
.
Image
Bug Fixes
- Resolved the common SSR issue with Next.js
Features
-
Added support for the
fit
prop to specify how to fit an image within its
dimension. It uses theobject-fit
property -
Added support for the
align
prop to specify how to align the image within
its dimension. It uses theobject-position
property -
Added support for custom
fallback
component
Input
-
When using
InputAddon
, you no longer need to pass border radius properties
to theInput
.InputGroup
will intelligently detect the addon and apply the
necessary border to the input. -
Input now uses
paddingY
instead ofheight
for its block height.
Link
- Due to accessibility reasons, we've deprecated the
isDisabled
prop for
Link
.
Stack
- To reduce the API surface area, we've deprecated the
isInline
and
isReversed
props in favor of thedirection
prop
- <Stack isInline>
+ <Stack direction="row">
<Box />
<Box />
</Stack>
-
We've deprecated the
shouldWrapChildren
prop because we now use css to
manage the stack rather thanReact.cloneElement
-
Added support for responsive
direction
andspacing
props
<Stack direction={["column", "row"]}>
<Box />
<Box />
</Stack>
- Added support for
divider
prop between stacked element. Dividers also work
with responsive direction and spacing.
<Stack divider={<StackDivider />}>
<Box />
<Box />
</Stack>
- You can also use the
HStack
andVStack
components to conveniently stack
elements in the horizontal or vertical directions respectively.
Menu
Features
- Added support for nested menus or submenus
const PreferencesMenu = forwardRef((props, ref) => {
return (
<Menu>
<MenuButton ref={ref} {...props}>
Preferences
</MenuButton>
<MenuList>
<MenuItem>Settings</MenuItem>
<MenuItem isDisabled>Extensions</MenuItem>
<MenuSeparator />
<MenuItem>Keyboard shortcuts</MenuItem>
</MenuList>
</Menu>
)
})
function Example() {
return (
<Menu>
<MenuButton>Code</MenuButton>
<MenuList>
<MenuItem>About Visual Studio Code</MenuItem>
<MenuItem>Check for Updates...</MenuItem>
<MenuSeparator />
<MenuItem as={PreferencesMenu} />
</MenuList>
</Menu>
)
}
- Added support for menu icons and commands (or hotkeys)
<Menu>
<MenuButton size="sm" colorScheme="teal">
Open menu
</MenuButton>
<MenuList>
<MenuItem command="⌘T">New Tab</MenuItem>
<MenuItem command="⌘N">New Window</MenuItem>
<MenuItem command="⌘⇧N">Open Closed Tab</MenuItem>
<MenuItem command="⌘O">Open File...</MenuItem>
</MenuList>
</Menu>
-
Support for menu transitions and animations
It's important to use the
css
orsx
prop for the transitions to work
properly. For some reason, it doesn't work with thestyle
native prop
<Menu>
<MenuButton size="sm" colorScheme="teal">
Open menu
</MenuButton>
<MenuTransition>
{(styles) => (
<MenuList css={styles}>
<MenuItem command="⌘T">New Tab</MenuItem>
<MenuItem command="⌘N">New Window</MenuItem>
<MenuItem command="⌘⇧N">Open Closed Tab</MenuItem>
<MenuItem command="⌘O">Open File...</MenuItem>
</MenuList>
)}
</MenuTransition>
</Menu>
- Added support for Portals. Wrap the
MenuList
in thePortal
component and
you're good to go!
<Menu>
<MenuButton size="sm" colorScheme="teal">
Open menu
</MenuButton>
<Portal>
<MenuList>
<MenuItem>Menu 1</MenuItem>
<MenuItem>New Window</MenuItem>
<MenuItem>Open Closed Tab</MenuItem>
<MenuItem>Open File</MenuItem>
</MenuList>
</Portal>
</Menu>
- Moved to Popper V2 🥳
Fixes
- Fixed issue with
as
prop forMenuItem
- Fixed issue with
Link
not navigating to the specifiedhref
value - Fixed issue where menu popper gets cut off when component is far right
- Fixed issue where
Menu
throws if noMenuItem
exist - Fixed issue where
closeOnSelect
doesn't work on navigation when using
MenuItem
as link
Modal
Changes
-
Removed
addAriaLabels
andformatIds
props in favor of passing a top-level
id
prop to the modal, and we'll handle the rest. -
Removed
preserveScrollBarGap
prop. We preserve scroll bar gap by default to
prevent any layout shift. -
Wrap
ModalContent
with theModalOverlay
component.
// before
<Modal>
- <ModalOverlay />
<ModalContent>
<ModalHeader>Modal header</ModalHeader>
<ModalCloseButton />
<ModalBody>Modal body</ModalBody>
<ModalFooter>Modal footer</ModalFooter>
</ModalContent>
</Modal>
// after
<Modal>
+ <ModalOverlay>
<ModalContent>
<ModalHeader>Modal header</ModalHeader>
<ModalCloseButton />
<ModalBody>Modal body</ModalBody>
<ModalFooter>Modal footer</ModalFooter>
</ModalContent>
+ </ModalOverlay>
</Modal>
-
Only pass
size
values defined in the components theme. Hard-coded values
will be ignored. Update the styles intheme.components.Modal
to reflect your
custom values -
You can now disable focus trap by passing
trapFocus={false}
New Props
trapFocus
: to disable focus trapautoFocus
: to disable autofocus on the first interactive elementonOverlayClick
: callback fired when the overlay is clickedonEsc
: callback fired whenesc
is pressed
NumberInput
-
Added example where consumers can format and parse number input values (
#438) -
Fixed issue where error is thrown if the input value is greater than the
max
prop when focus is blurred (
#584) -
Fixed issue where deleting sole digit sets value to 0 (which may be invalid) (
#533) -
Fixed issue where input returns
NaN
value after multiple dots (
#364) -
Fixed issue where passing
id
toNumberInput
and adding alabel
with
htmlFor
that points to thatid
doesn't focus the input (
#515)
Progress
- Change
color
prop tocolorScheme
.
- <Progress color="blue"/>
+ <Progress colorScheme="blue"/>
- Added Support for
isIndeterminate
prop in theProgress
component
CircularProgress
trackColor
prop now takes a specific theme color or a validcss
color.- Change the
thickness
prop to point to an actual thickness value inpx
(e.g.thickness={4}
)
Radio
- Change
variantColor
prop tocolorScheme
.
- <Radio variantColor="blue">Option</Radio>
+ <Radio colorScheme="blue">Option</Radio>
-
Deprecated the
isFullWidth
prop. TheRadio
takes up the width of the
parent by default. -
Deprecated
RadioButton
component. Use theuseRadio
hook to create 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. TheRadioGroup
takes up the width of the
parent by default. -
To allow for better Radio group layout, the
RadioGroup
component no longer
supports every style prop. You can only passsize
,variant
, and
colorScheme
in addition toRadioGroup
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>
Slider
- Update JSX structure: Wrap
SliderFilledTrack
withSliderTrack
.
// before
<Slider defaultValue={30}>
- <SliderTrack />
- <SliderFilledTrack />
<SliderThumb />
</Slider>
// after
<Slider defaultValue={30}>
+ <SliderTrack>
+ <SliderFilledTrack />
+ </SliderTrack>
<SliderThumb />
</Slider>
-
Added support for the
isReversed
prop, which allows users to reverse the
direction and functionality of the slider. This is mostly useful forrtl
purposes. -
Added support for the
onChangeEnd
prop. Dragging the slider can trigger lots
of updates and user might only be interested in the final result after sliding
is complete. -
Added
isReadOnly
prop to support cases where slider needs to be in read-only
state. -
Export the
useSlider
hook to help users manage and build custom slider UIs.
Popover
-
returnFocusOnClose
has been changed toreturnFocus
for conciseness. -
autoFocus
prop to allow users to control whether the popover should
automatically receive focus when it opens.
Stat
- We improved the semantic HTML structure of the Stat components to use
dl
,
dd
, anddt
tags.
Switch
- Rename the
color
prop tocolorScheme
- <Switch color="blue"/>
+ <Switch colorScheme="blue"/>
Tabs
- Change
variantColor
prop tocolorScheme
Tags
- Change
variantColor
tocolorScheme
- <Tag variantColor="blue"/>
+ <Tag colorScheme="blue"/>
- Added support for
isDisabled
prop on theTagCloseButton
component
<Tag variant="solid" size="sm" colorScheme="cyan">
<TagLabel>Tab Label</TagLabel>
<TagCloseButton isDisabled />
</Tag>
Toast
- Removed
react-spring
dependency in favor ofreact-transition-group
- Added support for duplicate toast prevention using
toast.isActive
method - Added support to programmatically close one or all toasts using
toast.close
ortoast.closeAll
methods - Added support to programmatically update a toast using
toast.update
method. - Added support for
onCloseComplete
prop, a callback function to run side
effects after the toast component has closed.
Tooltip
- Added support for
hideOnClick
prop - Added support for
hideOnMouseDown
prop
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