Documentation for migrating to Chakra UI v3. # Migration to v3 :::warning We recommend using the [LLMs.txt](/docs/get-started/llms) files to make the Chakra UI v3 documentation available to large language models. ::: ## Codemod (Recommended) The codemod automates the migration from Chakra UI v2 to v3. It handles component renames, prop changes, import updates, and compound component restructuring. Start here before migrating manually. ```bash npx @chakra-ui/codemod upgrade ``` Use `--dry` to preview changes without modifying files. ## Manual Steps > The minimum node version required is Node.20.x :::steps ### Update Packages Remove the unused packages: `@emotion/styled` and `framer-motion`. These packages are no longer required in Chakra UI. ```bash npm uninstall @emotion/styled framer-motion ``` Install updated versions of the packages: `@chakra-ui/react` and `@emotion/react`. ```bash npm install @chakra-ui/react@latest @emotion/react@latest ``` Next, install component snippets using the CLI snippets. Snippets provide pre-built compositions of Chakra components to save you time and put you in charge. ```bash npx @chakra-ui/cli snippet add ``` ### Refactor Custom Theme Move your custom theme to a dedicated `theme.js` or `theme.ts` file. Use `createSystem` and `defaultConfig` to configure your theme. **Before** ```ts import { extendTheme } from "@chakra-ui/react" export const theme = extendTheme({ fonts: { heading: `'Figtree', sans-serif`, body: `'Figtree', sans-serif`, }, }) ``` **After** ```ts {3} import { createSystem, defaultConfig } from "@chakra-ui/react" export const system = createSystem(defaultConfig, { theme: { tokens: { fonts: { heading: { value: `'Figtree', sans-serif` }, body: { value: `'Figtree', sans-serif` }, }, }, }, }) ``` > All token values need to be wrapped in an object with a **value** key. Learn > more about tokens [here](/docs/theming/tokens). ### Update ChakraProvider Update the ChakraProvider import from `@chakra-ui/react` to the one from the snippets. Next, rename the `theme` prop to `value` to match the new system-based theming approach. **Before** ```tsx import { ChakraProvider } from "@chakra-ui/react" export const App = ({ Component }) => ( ) ``` **After** ```tsx {1,3} import { Provider } from "@/components/ui/provider" import { defaultSystem } from "@chakra-ui/react" export const App = ({ Component }) => ( ) ``` ```tsx {1,3} import { ColorModeProvider } from "@/components/ui/color-mode" import { ChakraProvider, defaultSystem } from "@chakra-ui/react" export function Provider(props) { return ( ) } ``` > If you have a custom theme, replace `defaultSystem` with the custom `system` The Provider component compose the `ChakraProvider` from Chakra and `ThemeProvider` from `next-themes` ::: ## Improvements - **Performance:** Improved reconciliation performance by `4x` and re-render performance by `1.6x` - **Namespaced imports:** Import components using the dot notation for more concise imports ```tsx import { Accordion } from "@chakra-ui/react" const Demo = () => { return ( ) } ``` - **TypeScript:** Improved IntelliSense and type inference for style props and tokens. - **Polymorphism:** Loosened the `as` prop typings in favor of using the `asChild` prop. This pattern was inspired by Radix Primitives and Ark UI. ## Removed Features ### Color Mode - `ColorModeProvider` and `useColorMode` have been removed in favor of `next-themes` - `LightMode`, `DarkMode` and `ColorModeScript` components have been removed. You now have to use `className="light"` or `className="dark"` to force themes. - `useColorModeValue` has been removed in favor of `useTheme` from `next-themes` :::note We provide snippets for color mode via the CLI to help you set up color mode quickly using `next-themes` ::: ### Hooks We removed the hooks package in favor of using dedicated, robust libraries like `react-use` and `usehooks-ts` The only hooks we ship now are `useBreakpointValue`, `useCallbackRef`, `useDisclosure`, `useControllableState` and `useMediaQuery`. ### Style Config We removed the `styleConfig` and `multiStyleConfig` concept in favor of recipes and slot recipes. This pattern was inspired by Panda CSS. ### Next.js package We've removed the `@chakra-ui/next-js` package in favor of using the `asChild` prop for better flexibility. To style the Next.js image component, use the `asChild` prop on the `Box` component. ```jsx ``` To style the Next.js link component, use the `asChild` prop on the `Link` component ```jsx ``` ### Theme Tools We've removed this package in favor using CSS color mix. **Before** We used JS to resolve the colors and then apply the transparency ```jsx defineStyle({ bg: transparentize("blue.200", 0.16)(theme), // -> rgba(0, 0, 255, 0.16) }) ``` **After** We now use CSS color-mix ```jsx defineStyle({ bg: "blue.200/16", // -> color-mix(in srgb, var(--chakra-colors-200), transparent 16%) }) ``` ### forwardRef Due to the simplification of the `as` prop, we no longer provide a custom `forwardRef`. Prefer to use `forwardRef` from React directly. Before: ```tsx {3} import { Button as ChakraButton, forwardRef } from "@chakra-ui/react" const Button = forwardRef(function Button(props, ref) { return }) ``` After: ```tsx {2, 4} import { Button as ChakraButton } from "@chakra-ui/react" import { forwardRef } from "react" const Button = forwardRef( function Button(props, ref) { return }, ) ``` ### Icons Removed `@chakra-ui/icons` package. Use `react-icons` (Lucide icons recommended) or `lucide-react` instead. Install with `npm install react-icons`. - **Icons without props** → use the react-icon directly - **Icons with Chakra style props** → wrap in `Icon` from `@chakra-ui/react` Before: ```tsx import { AddIcon, CheckIcon } from "@chakra-ui/icons" ``` After: ```tsx import { Icon } from "@chakra-ui/react" import { LuCheck, LuPlus } from "react-icons/lu" ``` Common icon mappings: `AddIcon` → `LuPlus`, `CloseIcon` → `LuX`, `CheckIcon` → `LuCheck`, `EditIcon` → `LuPencil`, `DeleteIcon` → `LuTrash2`, `SearchIcon` → `LuSearch`, `ChevronDownIcon` → `LuChevronDown`, `ArrowForwardIcon` → `LuArrowRight`, `HamburgerIcon` → `LuMenu`, `WarningIcon` → `LuAlertTriangle`, `InfoIcon` → `LuInfo`, `ExternalLinkIcon` → `LuExternalLink`, `StarIcon` → `LuStar` ### Storybook Addon We're removed the storybook addon in favor of using `@storybook/addon-themes` and `withThemeByClassName` helper. ```tsx import { ChakraProvider, defaultSystem } from "@chakra-ui/react" import { withThemeByClassName } from "@storybook/addon-themes" import type { Preview, ReactRenderer } from "@storybook/react" const preview: Preview = { decorators: [ withThemeByClassName({ defaultTheme: "light", themes: { light: "", dark: "dark", }, }), (Story) => ( ), ], } export default preview ``` ### Removed Components - **StackItem**: You don't need this anymore. Use `Box` instead. - **FocusLock**: We no longer ship a focus lock component. Install and use `react-focus-lock` directly. - **AlertDialog** - Replace with the `Dialog` component and set `role=alertdialog` - Set `leastDestructiveRef` prop to the `initialFocusEl` to the `Dialog.Root` component ### CircularProgress - Renamed to `ProgressCircle` and now uses compound components - `isIndeterminate` becomes `value={null}` - `thickness` prop becomes `--thickness` CSS variable - `color` prop becomes `stroke` prop on `ProgressCircle.Range` Before: ```tsx ``` After: ```tsx ``` For indeterminate progress: ```tsx ``` ### StackDivider - No longer available as a separate component - Use explicit `Stack.Separator` components between stack items Before: ```tsx } spacing={4}> Item 1 Item 2 Item 3 ``` After: ```tsx Item 1 Item 2 Item 3 ``` ## Prop Changes ### Boolean Props Changed naming convention for boolean properties from `is` to `` - `isOpen` -> `open` - `defaultIsOpen` -> `defaultOpen` - `isDisabled` -> `disabled` - `isInvalid` -> `invalid` - `isRequired` -> `required` ### ColorScheme Prop The `colorScheme` prop has been changed to `colorPalette` **Before** - You could only use `colorScheme` in a component's theme - `colorScheme` clashes with the native `colorScheme` prop in HTML elements ```tsx ``` **After** - You can now use `colorPalette` anywhere ```tsx ``` Usage in any component, you can do something like: ```tsx Some box Some text ``` If you are using custom colors, you must define two things to make `colorPalette` work: - **tokens**: For the 50-950 color palette - **semanticTokens**: For the `solid`, `contrast`, `fg`, `muted`, `subtle`, `emphasized`, and `focusRing` color keys ```tsx title="theme.ts" /brand: {/ /tokens: {/ /semanticTokens: {/ import { createSystem, defaultConfig } from "@chakra-ui/react" export const system = createSystem(defaultConfig, { theme: { tokens: { colors: { brand: { 50: { value: "#e6f2ff" }, 100: { value: "#e6f2ff" }, 200: { value: "#bfdeff" }, 300: { value: "#99caff" }, // ... 950: { value: "#001a33" }, }, }, }, semanticTokens: { colors: { brand: { solid: { value: "{colors.brand.500}" }, contrast: { value: "{colors.brand.100}" }, fg: { value: "{colors.brand.700}" }, muted: { value: "{colors.brand.100}" }, subtle: { value: "{colors.brand.200}" }, emphasized: { value: "{colors.brand.300}" }, focusRing: { value: "{colors.brand.500}" }, }, }, }, }, }) ``` > Read more about it [here](/guides/theming-custom-colors). ### Gradient Props Gradient style prop simplified to `gradient` and `gradientFrom` and `gradientTo` props. This reduces the runtime performance cost of parsing the gradient string, and allows for better type inference. **Before** ```tsx ``` **After** ```tsx ``` ### Color Palette - Default color palette is now `gray` for all components but you can configure this in your theme. - Default theme color palette size has been increased to 11 shades to allow more color variations. **Before** ```tsx const colors = { // ... gray: { 50: "#F7FAFC", 100: "#EDF2F7", 200: "#E2E8F0", 300: "#CBD5E0", 400: "#A0AEC0", 500: "#718096", 600: "#4A5568", 700: "#2D3748", 800: "#1A202C", 900: "#171923", }, } ``` **After** ```tsx const colors = { // ... gray: { 50: { value: "#fafafa" }, 100: { value: "#f4f4f5" }, 200: { value: "#e4e4e7" }, 300: { value: "#d4d4d8" }, 400: { value: "#a1a1aa" }, 500: { value: "#71717a" }, 600: { value: "#52525b" }, 700: { value: "#3f3f46" }, 800: { value: "#27272a" }, 900: { value: "#18181b" }, 950: { value: "#09090b" }, }, } ``` ### Style Props Changed the naming convention for some style props - `noOfLines` -> `lineClamp` - `truncated` -> `truncate` - `_activeLink` -> `_currentPage` - `_activeStep` -> `_currentStep` - `_mediaDark` -> `_osDark` - `_mediaLight` -> `_osLight` **Examples:** ```tsx // Before Long text that will be clamped to 2 lines This text will be truncated with ellipsis // After Long text that will be clamped to 2 lines This text will be truncated with ellipsis ``` We removed the `apply` prop in favor of `textStyle` or `layerStyles` ### Nested Styles We have changed the way you write nested styles in Chakra UI components. **Before** Write nested styles using the `sx` or `__css` prop, and you sometimes don't get auto-completion for nested styles. ```tsx ``` **After** Write nested styles using the `css` prop. All nested selectors **require** the use of the ampersand `&` prefix ```tsx ``` This was done for two reasons: - **Faster style processing:** Before we had to check if a style key is a style prop or a selector which is quite expensive overall. - **Better typings:** This makes it easier to type nested style props are strongly typed ## Component Changes ### ChakraProvider - Removed `theme` prop in favor of passing the `system` prop instead. Import the `defaultSystem` module instead of `theme` - Removed `resetCss` prop in favor of passing `preflight: false` to the `createSystem` function Before ```tsx ``` After ```tsx const system = createSystem(defaultConfig, { preflight: false }) ``` - Removed support for configuring toast options. Pass it to the `createToaster` function in `components/ui/toaster.tsx` file instead. ### Modal Renamed to `Dialog` and uses compound components with an explicit `Dialog.Positioner` and `Portal` wrapper. **Component Renaming:** - `Modal` → `Dialog.Root` - `ModalOverlay` → `Dialog.Backdrop` - `ModalContent` → `Dialog.Content` (wrap in `Dialog.Positioner`) - `ModalHeader` → `Dialog.Header` - `ModalBody` → `Dialog.Body` - `ModalFooter` → `Dialog.Footer` - `ModalCloseButton` → `Dialog.CloseTrigger` **Prop Changes:** - `isOpen` → `open` - `onClose` → `onOpenChange` (receives `{ open }`) - `isCentered` → `placement="center"` - `closeOnOverlayClick` → `closeOnInteractOutside` - `closeOnEsc` → `closeOnEscape` - `blockScrollOnMount` → `preventScroll` - `onOverlayClick` → `onInteractOutside` - `onEsc` → `onEscapeKeyDown` - `onCloseComplete` → `onExitComplete` - `initialFocusRef` → `initialFocusEl={() => ref.current}` - `finalFocusRef` → `finalFocusEl={() => ref.current}` **Size Mapping:** Sizes `2xl` through `6xl` are mapped to `xl` in v3. **Removed Props:** `allowPinchZoom`, `lockFocusAcrossFrames`, `preserveScrollBarGap`, `returnFocusOnClose`, `useInert`, `portalProps` ### Avatar Now uses a declarative composition pattern with separate `Avatar.Image` and `Avatar.Fallback` parts. **Component Renaming:** - `Avatar` → `Avatar.Root` - `AvatarBadge` → removed (use `Float` + `Circle` instead) - `AvatarGroup` → `AvatarGroup` (unchanged, but `max` prop removed) **Props moved to `Avatar.Image`:** - `src`, `srcSet`, `sizes`, `loading`, `referrerPolicy`, `crossOrigin` **Props moved to `Avatar.Fallback`:** - `name` — generates initials automatically - `icon` — render as children instead - `iconLabel` → `aria-label` **Props removed:** - `ignoreFallback` — no longer needed - `showBorder` — use `border` and `borderColor` style props instead - `AvatarGroup` `max` — removed, handle in userland - `AvatarGroup` `spacing` → `spaceX` Before: ```tsx import { Avatar, AvatarBadge, AvatarGroup } from "@chakra-ui/react" const Demo = () => ( <> } /> ) ``` After: ```tsx import { Avatar, AvatarGroup, Circle, Float } from "@chakra-ui/react" const Demo = () => ( <> ) ``` ### Breadcrumb Now uses compound components with explicit separators between items and a required `Breadcrumb.List` wrapper. **Component Renaming:** - `Breadcrumb` → `Breadcrumb.Root` - `BreadcrumbItem` → `Breadcrumb.Item` - `BreadcrumbLink` → `Breadcrumb.Link` - `BreadcrumbLink` with `isCurrentPage` → `Breadcrumb.CurrentLink` - `BreadcrumbSeparator` → `Breadcrumb.Separator` **Prop Changes:** - `separator` prop → removed, use explicit `` between items - `spacing` → `gap` (moved to `Breadcrumb.List`) - `isCurrentPage` on `BreadcrumbItem` → use `Breadcrumb.CurrentLink` instead - `isLastChild` → removed (not needed with explicit separators) - `listProps` → spread directly on `Breadcrumb.List` Before: ```tsx import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from "@chakra-ui/react" const Demo = () => ( Home Current ) ``` After: ```tsx import { Breadcrumb } from "@chakra-ui/react" const Demo = () => ( Home - Current ) ``` ### Portal - Remove `appendToParentPortal` prop in favor of using the `containerRef` - Remove `PortalManager` component ### Progress - Now uses compound components with `Progress.Root`, `Progress.Track`, and `Progress.Range` - `hasStripe` prop renamed to `striped` - `isAnimated` prop renamed to `animated` - `colorScheme` prop renamed to `colorPalette` Before: ```tsx ``` After: ```tsx ``` ### Stack - Changed `spacing` to `gap` - Removed `StackItem` in favor of using the `Box` component directly ### Select Now called `NativeSelect` and exposes all parts now. Before: ```tsx ``` After: ```tsx ``` Changing the icon Before: ```tsx ``` After ```tsx Email This field is required ``` ### Link - Removed `isExternal` prop in favor of explicitly setting the `target` and `rel` props Before ```tsx Click me ``` After ```tsx Click me ``` ### List Now uses compound components with dot notation. `OrderedList` and `UnorderedList` are no longer separate components — use `List.Root` with the `as` prop instead. **Component Renaming:** - `List` → `List.Root` - `OrderedList` → `List.Root as="ol"` - `UnorderedList` → `List.Root as="ul"` - `ListItem` → `List.Item` - `ListIcon` → `List.Indicator` **Prop Changes:** - `spacing` → `gap` - `styleType` → `listStyleType` - `stylePosition` → `listStylePosition` Before: ```tsx import { ListIcon, ListItem, UnorderedList } from "@chakra-ui/react" import { MdCheckCircle } from "react-icons/md" const Demo = () => ( Lorem ipsum dolor sit amet Consectetur adipiscing elit ) ``` After: ```tsx import { List } from "@chakra-ui/react" import { MdCheckCircle } from "react-icons/md" const Demo = () => ( Lorem ipsum dolor sit amet Consectetur adipiscing elit ) ``` For ordered lists: Before: ```tsx import { ListItem, OrderedList } from "@chakra-ui/react" const Demo = () => ( First item Second item ) ``` After: ```tsx import { List } from "@chakra-ui/react" const Demo = () => ( First item Second item ) ``` ### Button **Prop Changes:** - `isActive` → `data-active` attribute - `isDisabled` → `disabled` - `isLoading` → `loading` - `colorScheme` → `colorPalette` - `leftIcon` / `rightIcon` → render icons as children directly - `iconSpacing` → `gap` - `variant="unstyled"` → `unstyled` boolean prop - `variant="link"` → `variant="plain"` Before: ```tsx ``` After: ```tsx ``` **ButtonGroup Changes:** - `isAttached` → `attached` - `isDisabled` → removed (propagate `disabled` to each child instead) ### IconButton - `icon` → render as `children` directly - `isRounded` → `borderRadius="full"` - `isDisabled` → `disabled` Before: ```tsx } isRounded isDisabled aria-label="Search" /> ``` After: ```tsx ``` ### Spinner - Change the `thickness` prop to `borderWidth` - Change the `speed` prop to `animationDuration` Before ```tsx ``` After ```tsx ``` ### Dialog, Drawer Both `Modal` and `Drawer` now use compound components with an explicit `Positioner` and `Portal` wrapper. **Prop Changes (shared by Dialog and Drawer):** - `isOpen` → `open` - `onClose` → `onOpenChange` (receives `{ open }`) - `blockScrollOnMount` → `preventScroll` - `closeOnEsc` → `closeOnEscape` - `closeOnOverlayClick` → `closeOnInteractOutside` - `onOverlayClick` → `onInteractOutside` - `onEsc` → `onEscapeKeyDown` - `onCloseComplete` → `onExitComplete` - `initialFocusRef` → `initialFocusEl={() => ref.current}` - `finalFocusRef` → `finalFocusEl={() => ref.current}` - `isCentered` → `placement="center"` (Dialog only) - Sizes `2xl`–`6xl` → mapped to `xl` **Drawer-specific Changes:** - `placement="left"` → `placement="start"` (RTL-aware) - `placement="right"` → `placement="end"` (RTL-aware) - `isFullHeight` → add `height="100%"` to `Drawer.Content` - `DrawerOverlay` → `Drawer.Backdrop` - `DrawerContent` → `Drawer.Positioner` + `Drawer.Content` **Removed Props:** `allowPinchZoom`, `lockFocusAcrossFrames`, `preserveScrollBarGap`, `returnFocusOnClose`, `useInert`, `portalProps` **Dialog Example:** Before: ```tsx import { Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, } from "@chakra-ui/react" const Demo = () => ( Title Content ) ``` After: ```tsx import { Dialog, Portal } from "@chakra-ui/react" const Demo = () => ( !e.open && onClose()} placement="center" closeOnEscape={false} > Title Content ) ``` **Drawer Example:** Before: ```tsx import { Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerFooter, DrawerHeader, DrawerOverlay, } from "@chakra-ui/react" const Demo = () => ( Title Content ) ``` After: ```tsx import { Drawer, Portal } from "@chakra-ui/react" const Demo = () => ( !e.open && onClose()} > Title Content ) ``` ### Editable Now uses compound components with dot notation. Custom controls use declarative trigger components instead of the `useEditableControls` prop-getter pattern. **Component Renaming:** - `Editable` → `Editable.Root` - `EditablePreview` → `Editable.Preview` - `EditableInput` → `Editable.Input` - `EditableTextarea` → `Editable.Textarea` - `useEditableControls` → `useEditableContext` **Prop Changes:** - `isDisabled` → `disabled` - `onChange` → `onValueChange` (receives `{ value }` object) - `onSubmit` → `onValueCommit` - `onCancel` → `onValueRevert` - `startWithEditView` → `defaultEdit` - `selectAllOnFocus` → `selectOnFocus` - `submitOnBlur={false}` → `submitMode="enter"` - `finalFocusRef` → `finalFocusEl` (function returning element) - `isPreviewFocusable={false}` → add `tabIndex={undefined}` to `Editable.Preview` Before: ```tsx import { Editable, EditableInput, EditablePreview } from "@chakra-ui/react" const Demo = () => ( ) ``` After: ```tsx import { Editable } from "@chakra-ui/react" const Demo = () => ( ) ``` **Custom Controls:** The `useEditableControls` prop-getter pattern is replaced by declarative trigger components. Before: ```tsx function EditableControls() { const { isEditing, getSubmitButtonProps, getCancelButtonProps } = useEditableControls() return isEditing ? ( } {...getSubmitButtonProps()} /> } {...getCancelButtonProps()} /> ) : null } ``` After: ```tsx ``` ### FormControl Replaced by `Field` for standard form controls and `Fieldset` for grouped controls (radio groups, checkbox groups). The `as='fieldset'` pattern is replaced with a dedicated `Fieldset` component. **Component Renaming:** - `FormControl` → `Field.Root` - `FormLabel` → `Field.Label` - `FormHelperText` → `Field.HelperText` - `FormErrorMessage` → `Field.ErrorText` For fieldset usage: - `FormControl as='fieldset'` → `Fieldset.Root` - `FormLabel as='legend'` → `Fieldset.Legend` - `FormHelperText` → `Fieldset.HelperText` - `FormErrorMessage` → `Fieldset.ErrorText` **Prop Changes:** - `isInvalid` → `invalid` - `isRequired` → `required` - `isDisabled` → `disabled` - `isReadOnly` → `readOnly` Before: ```tsx import { FormControl, FormErrorMessage, FormHelperText, FormLabel, } from "@chakra-ui/react" const Demo = () => ( Email We'll never share your email. Email is required. ) ``` After: ```tsx import { Field } from "@chakra-ui/react" const Demo = () => ( Email We'll never share your email. Email is required. ) ``` > `Field.ErrorText` only renders when `invalid` is `true`, so no conditional > logic is needed. **Fieldset Usage:** Before: ```tsx import { FormControl, FormHelperText, FormLabel } from "@chakra-ui/react" const Demo = () => ( Favorite Character Select only if you're a fan. ) ``` After: ```tsx import { Fieldset } from "@chakra-ui/react" const Demo = () => ( Favorite Character Select only if you're a fan. ) ``` ### Collapse Replace with the `Collapsible` component. Before: ```tsx Some content ``` After: ```tsx Some content ``` ### Fade, ScaleFade, Slide, SlideFade All transition components have been replaced by a unified `Presence` component that uses CSS-based animations instead of JavaScript-based transitions. **Component Mapping:** - `Fade` → `Presence` with `animationName={{ _open: "fade-in", _closed: "fade-out" }}` - `ScaleFade` → `Presence` with `animationStyle={{ _open: "scale-fade-in", _closed: "scale-fade-out" }}` - `SlideFade` → `Presence` with `animationName={{ _open: "slide-from-bottom, fade-in", _closed: "slide-to-bottom, fade-out" }}` - `Slide` → `Presence` with direction-specific positioning and animation **Prop Changes:** - `in` → `present` - `initialScale` → removed (scale is fixed in CSS keyframes) - `offsetX` / `offsetY` → removed (offset is fixed in CSS keyframes) - `direction` → replaced by positioning props and direction-specific animation names Before: ```tsx import { Fade, Slide } from "@chakra-ui/react" const Demo = () => ( <> Fading content Sliding content ) ``` After: ```tsx import { Presence } from "@chakra-ui/react" const Demo = () => ( <> Fading content Sliding content ) ``` **Slide Direction Mapping:** | Direction | Positioning | Open Animation | Close Animation | | --------- | -------------------------------------------- | ------------------------ | ---------------------- | | `top` | `position="fixed"` `top="0"` `insetX="0"` | `slide-from-top-full` | `slide-to-top-full` | | `bottom` | `position="fixed"` `bottom="0"` `insetX="0"` | `slide-from-bottom-full` | `slide-to-bottom-full` | | `left` | `position="fixed"` `left="0"` `insetY="0"` | `slide-from-left-full` | `slide-to-left-full` | | `right` | `position="fixed"` `right="0"` `insetY="0"` | `slide-from-right-full` | `slide-to-right-full` | ### Slider / RangeSlider `RangeSlider` has been unified with `Slider` — pass an array value for range mode. Both now require a `Slider.Control` wrapper and `Slider.HiddenInput` inside each thumb. **Component Renaming:** - `Slider` / `RangeSlider` → `Slider.Root` - `SliderTrack` / `RangeSliderTrack` → `Slider.Track` - `SliderFilledTrack` / `RangeSliderFilledTrack` → `Slider.Range` - `SliderThumb` / `RangeSliderThumb` → `Slider.Thumb` **Prop Changes:** - `onChange` → `onValueChange` (receives `{ value }`) - `onChangeEnd` → `onValueChangeEnd` (receives `{ value }`) - `onChangeStart` → removed - `colorScheme` → `colorPalette` - `isReversed` / `reversed` → removed (use `dir="rtl"`) - `focusThumbOnChange` → removed Before: ```tsx import { RangeSlider, RangeSliderFilledTrack, RangeSliderThumb, RangeSliderTrack, } from "@chakra-ui/react" const Demo = () => ( console.log(val)}> ) ``` After: ```tsx import { Slider } from "@chakra-ui/react" const Demo = () => ( console.log(e.value)} > ) ``` ### Table - `TableContainer` is now `Table.ScrollArea` - `Td`(now called `Table.ColumnHeader`) `isNumeric` is now `textAlign="end"` The compound component have been renamed slightly. Before: ```tsx Imperial to metric conversion factors {items.map((item) => ( ))}
Product Category Price
{item.name} {item.category} {item.price}
Product Category Price
``` After: ```tsx Product Category Price {items.map((item) => ( {item.name} {item.category} {item.price} ))} ``` ### Tag `TagLeftIcon` and `TagRightIcon` are now `Tag.StartElement` and `Tag.EndElement` Before: ```tsx Cyan ``` After: ```tsx Cyan ``` - `TagCloseButton` is now `Tag.CloseTrigger` Before: ```tsx Green ``` After: ```tsx Green ``` ### Alert Now uses compound components with dot notation. v3 also introduces `Alert.Content` as a wrapper for title and description. **Component Renaming:** - `Alert` → `Alert.Root` - `AlertIcon` → `Alert.Indicator` - `AlertTitle` → `Alert.Title` - `AlertDescription` → `Alert.Description` **Prop Changes:** - Removed `addRole` prop (role is handled automatically in v3) Before: ```tsx import { Alert, AlertDescription, AlertIcon, AlertTitle, } from "@chakra-ui/react" const Demo = () => ( Your browser is outdated! Your Chakra experience may be degraded. ) ``` After: ```tsx import { Alert } from "@chakra-ui/react" const Demo = () => ( Your browser is outdated! Your Chakra experience may be degraded. ) ``` **Variant Changes:** The `left-accent` and `top-accent` variants have been removed. Replicate them using border style props on `Alert.Root`: - `left-accent` → `variant="subtle"` + `borderStartWidth="3px"` + `borderStartColor="colorPalette.solid"` - `top-accent` → `variant="subtle"` + `borderTopWidth="3px"` + `borderTopColor="colorPalette.solid"` New variants `surface` and `outline` have been added. Before: ```tsx Data uploaded to the server. Fire on! ``` After: ```tsx Data uploaded to the server. Fire on! ``` ### Skeleton - `startColor` and `endColor` props now use CSS variables Before: ```tsx ``` After: ```tsx ``` - `isLoaded` prop is now `loading` Before: ```tsx Chakra ui is cool ``` After: ```tsx Chakra ui is cool ``` ### Stepper Renamed to `Steps` with compound component pattern. The `useSteps` hook is still available but with updated API. **Component Renaming:** - `Stepper` → `Steps.Root` - `Step` → `Steps.Item` - `StepIndicator` → `Steps.Indicator` - `StepStatus` → `Steps.Status` - `StepTitle` → `Steps.Title` - `StepDescription` → `Steps.Description` - `StepSeparator` → `Steps.Separator` **Prop Changes:** - `index` → `step` - Children must be wrapped in `Steps.List` **Hook Changes:** - `useSteps({ index })` → `useSteps({ defaultStep })` - When using `useSteps`, use `Steps.RootProvider` with `value={stepsApi}` instead of `Steps.Root` Before: ```tsx import { Step, StepIcon, StepIndicator, StepNumber, StepSeparator, StepStatus, StepTitle, Stepper, } from "@chakra-ui/react" const Demo = () => ( {steps.map((step, index) => ( } incomplete={} /> {step.title} ))} ) ``` After: ```tsx import { Steps } from "@chakra-ui/react" const Demo = () => ( {steps.map((step, index) => ( } incomplete={} /> {step.title} ))} ) ``` ### Stat Now uses compound components with dot notation. **Component Renaming:** - `Stat` → `Stat.Root` - `StatLabel` → `Stat.Label` - `StatNumber` → `Stat.ValueText` - `StatHelpText` → `Stat.HelpText` - `StatArrow type="increase"` → `Stat.UpIndicator` - `StatArrow type="decrease"` → `Stat.DownIndicator` - `StatGroup` → `Stat.Root` (nest `Stat.Root` children inside) Before: ```tsx import { Stat, StatArrow, StatHelpText, StatLabel, StatNumber, } from "@chakra-ui/react" const Demo = () => ( Revenue $45,670 12.5% ) ``` After: ```tsx import { Stat } from "@chakra-ui/react" const Demo = () => ( Revenue $45,670 12.5% ) ``` ### Menu - Now uses compound components everywhere Before: ```tsx }> Actions Download Create a Copy ``` After: ```tsx Download Create a Copy ``` - Accesing internal state is now done via `Menu.Context` no longer render prop. Before: ```tsx {({ isOpen }) => ( <> }> {isOpen ? "Close" : "Open"} Download alert("Kagebunshin")}>Create a Copy )} ``` After: ```tsx {(menu) => ( )} Download alert("Kagebunshin")}> Create a Copy ``` - `isLazy` prop on `Menu` is split into `lazyMount` and `unmountOnExit` on `Menu.Root` - `MenuOptionGroup` is now split into `Menu.RadioItemGroup` and `Menu.CheckboxItemGroup` to handle the states separately. Before: ```tsx Trigger Ascending Descending Email Phone Country ``` After: ```tsx Ascending Descending Email Phone Country ``` ### Tooltip Now a **snippet** component imported from `@/components/ui/tooltip` instead of `@chakra-ui/react`. **Prop Changes:** - `label` → `content` - `hasArrow` → `showArrow` - `closeOnEsc` → `closeOnEscape` - `closeOnMouseDown` → `closeOnPointerDown` - `onOpen` / `onClose` → `onOpenChange` (receives `{ open }`) - `shouldWrapChildren` → wrap children in `` manually - `placement`, `gutter`, `offset`, `arrowPadding` → grouped into `positioning` object **Removed Props:** `modifiers`, `motionProps`, `portalProps`, `arrowSize`, `arrowShadowColor` Before: ```tsx import { Tooltip } from "@chakra-ui/react" ; ``` After: ```tsx import { Tooltip } from "@/components/ui/tooltip" ; ``` ### Accordion Now uses compound components with dot notation. All sub-components are namespaced under `Accordion`. **Component Renaming:** - `Accordion` → `Accordion.Root` - `AccordionItem` → `Accordion.Item` (now **requires** a `value` prop) - `AccordionButton` → `Accordion.ItemTrigger` - `AccordionIcon` → `Accordion.ItemIndicator` - `AccordionPanel` → `Accordion.ItemContent` + `Accordion.ItemBody` **Prop Changes:** - `allowMultiple` → `multiple` - `allowToggle` → `collapsible` - `defaultIndex` → `defaultValue` (now an array of strings) - `index` → `value` (now an array of strings) - `onChange` → `onValueChange` Before: ```tsx import { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Box, } from "@chakra-ui/react" const Demo = () => (

Section 1 title

Lorem ipsum dolor sit amet.
) ``` After: ```tsx import { Accordion, Box } from "@chakra-ui/react" const Demo = () => (

Section 1 title

Lorem ipsum dolor sit amet.
) ``` **Render Props → Context:** The `AccordionItem` render prop pattern (`{({ isExpanded }) => ...}`) has been replaced. Use the `Accordion.ItemContext` component or the `useAccordionItemContext` hook instead. The `isExpanded` property is now `expanded`. Before: ```tsx {({ isExpanded }) => ( <> Section title {isExpanded ? : } Content )} ``` After: ```tsx {({ expanded }) => ( <> Section title {expanded ? : } Content )} ``` ### Tabs - Component structure has changed and `value` prop is now required on list and panels. Before: ```tsx One Two Three one! two! three! ``` After: ```tsx One Two Three one! two! three! ``` - `defaultIndex`, `index` and `onChange` is now `defaultValue`, `value` and `onValueChange` respectively Before: ```tsx {}} /> ``` After: ```tsx {}} /> ``` - `isLazy` prop on `Tabs` is now `lazyMount` and `unmountOnExit` on `Tabs.Root` Before: ```tsx ``` After: ```tsx ``` ### Show and Hide - `Show` and `Hide` components are removed in favor of `hideFrom` and `hideBelow` Before: ```tsx This text appears only on screens md and smaller. This text hides at the "md" value screen width and smaller. ``` After: ```tsx This text hides at the "md" value screen width and smaller. This text appears only on screens md and larger. ``` ### Checkbox Refactored to use compound components. The single `` is now split into explicit parts for full control over structure and styling. **Prop Changes:** - `isChecked` → `checked` - `isDisabled` → `disabled` - `isInvalid` → `invalid` - `isReadOnly` → `readOnly` - `isIndeterminate` → `checked="indeterminate"` - `onChange` → `onCheckedChange` - `colorScheme` → `colorPalette` - `icon` → render as children of `Checkbox.Control` - `iconColor` → `color` on `Checkbox.Indicator` - `iconSize` → `boxSize` on `Checkbox.Indicator` - `isFocusable` → removed **CheckboxGroup:** - `isDisabled` → `disabled` - `onChange` → `onValueChange` - `isNative` → removed Before: ```tsx import { Checkbox } from "@chakra-ui/react" const Demo = () => ( setChecked(e.target.checked)} colorScheme="blue" > Accept terms ) ``` After: ```tsx import { Checkbox } from "@chakra-ui/react" const Demo = () => ( setChecked(!!e.checked)} colorPalette="blue" > Accept terms ) ``` ### Radio Group Refactored to use compound components. `Radio` is now `RadioGroup.Item` with explicit sub-components: `ItemHiddenInput`, `ItemIndicator`, `ItemText`. **Component Renaming:** - `RadioGroup` → `RadioGroup.Root` - `Radio` → `RadioGroup.Item` (with required sub-components) **RadioGroup Prop Changes:** - `onChange` → `onValueChange` (receives `{ value }` object) - `colorScheme` → `colorPalette` **Radio Prop Changes:** - `isDisabled` → `disabled` - `isInvalid`, `isChecked`, `defaultChecked` → removed (controlled from Root) - `colorScheme` → removed from items (set `colorPalette` on Root instead) - `inputProps` → spread into `RadioGroup.ItemHiddenInput` Before: ```tsx import { Radio, RadioGroup } from "@chakra-ui/react" const Demo = () => ( setValue(val)}> Option 1 Option 2 ) ``` After: ```tsx import { RadioGroup } from "@chakra-ui/react" const Demo = () => ( setValue(e.value)}> Option 1 Option 2 ) ``` ### Button Props - `isActive` → `data-active` attribute - `isDisabled` → `disabled` - `isLoading` → `loading` - `leftIcon` and `rightIcon` → passed as children - `iconSpacing` → removed (use gap in flex layout) - `colorScheme` → `colorPalette` **Example:** ```tsx // Before // After ``` ### Input Props - `isDisabled` → `disabled` - `isInvalid` → `invalid` - `isReadOnly` → `readOnly` - `isRequired` → `required` - `colorScheme` → `colorPalette` - `focusBorderColor` → use CSS variables - `errorBorderColor` → use CSS variables **Example:** ```tsx // Before // After ``` ### Checkbox Props - `isChecked` → `checked` - `isDisabled` → `disabled` - `isInvalid` → `invalid` - `isIndeterminate` → `checked="indeterminate"` - `onChange` → `onCheckedChange` - `colorScheme` → `colorPalette` - `iconColor` → `color` on `Checkbox.Indicator` - `iconSize` → `boxSize` on `Checkbox.Indicator` - `isFocusable` → removed ### Modal to Dialog Props - `isOpen` → `open` - `onClose` → `onOpenChange` (receives `{ open }`) - `isCentered` → `placement="center"` - `closeOnOverlayClick` → `closeOnInteractOutside` - `closeOnEsc` → `closeOnEscape` - `blockScrollOnMount` → `preventScroll` - `onOverlayClick` → `onInteractOutside` - `onEsc` → `onEscapeKeyDown` - `onCloseComplete` → `onExitComplete` - `initialFocusRef` → `initialFocusEl` (function returning element) - `finalFocusRef` → `finalFocusEl` (function returning element) - `scrollBehavior` → unchanged - `motionPreset` → unchanged - `trapFocus` → unchanged - Sizes `2xl`–`6xl` → mapped to `xl` - Removed: `allowPinchZoom`, `lockFocusAcrossFrames`, `preserveScrollBarGap`, `returnFocusOnClose`, `useInert`, `portalProps` ### Stack Props - `spacing` → `gap` - `divider` → `separator` - Other props remain the same **Example:** ```tsx // Before } > Item 1 Item 2 // After } > Item 1 Item 2 ```