packages/codemod/docs/ACCORDION_MIGRATION.md
This guide shows how to migrate Chakra UI Accordion components from v2 to v3.
The codemod automatically handles:
<Accordion> → <Accordion.Root><AccordionItem> → <Accordion.Item> with auto-generated value prop<AccordionButton> → <Accordion.ItemTrigger><AccordionIcon> → <Accordion.ItemIndicator><AccordionPanel> → <Accordion.ItemContent> + <Accordion.ItemBody>allowMultiple → multiple, allowToggle → collapsibledefaultIndex → defaultValue, index → valueonChange → onValueChangeimport {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Box,
} from "@chakra-ui/react"
function App() {
return (
<Accordion allowToggle>
<AccordionItem>
<h2>
<AccordionButton>
<Box as="span" flex="1" textAlign="left">
Section 1 title
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<h2>
<AccordionButton>
<Box as="span" flex="1" textAlign="left">
Section 2 title
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</AccordionPanel>
</AccordionItem>
</Accordion>
)
}
import { Accordion, Box } from "@chakra-ui/react"
function App() {
return (
<Accordion.Root collapsible>
<Accordion.Item value="item-0">
<h2>
<Accordion.ItemTrigger>
<Box as="span" flex="1" textAlign="left">
Section 1 title
</Box>
<Accordion.ItemIndicator />
</Accordion.ItemTrigger>
</h2>
<Accordion.ItemContent>
<Accordion.ItemBody pb={4}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</Accordion.ItemBody>
</Accordion.ItemContent>
</Accordion.Item>
<Accordion.Item value="item-1">
<h2>
<Accordion.ItemTrigger>
<Box as="span" flex="1" textAlign="left">
Section 2 title
</Box>
<Accordion.ItemIndicator />
</Accordion.ItemTrigger>
</h2>
<Accordion.ItemContent>
<Accordion.ItemBody pb={4}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</Accordion.ItemBody>
</Accordion.ItemContent>
</Accordion.Item>
</Accordion.Root>
)
}
import {
Accordion,
AccordionButton,
AccordionItem,
AccordionPanel,
AddIcon,
Box,
MinusIcon,
} from "@chakra-ui/react"
function App() {
return (
<Accordion allowMultiple>
<AccordionItem>
<h2>
<AccordionButton>
<Box as="span" flex="1" textAlign="left">
Section 1 title
</Box>
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</AccordionPanel>
</AccordionItem>
<AccordionItem>
{({ isExpanded }) => (
<>
<h2>
<AccordionButton>
<Box as="span" flex="1" textAlign="left">
Section 2 title
</Box>
{isExpanded ? (
<MinusIcon fontSize="12px" />
) : (
<AddIcon fontSize="12px" />
)}
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</AccordionPanel>
</>
)}
</AccordionItem>
</Accordion>
)
}
useAccordionItemContext Hookimport { Accordion, Box, useAccordionItemContext } from "@chakra-ui/react"
import { LuMinus, LuPlus } from "react-icons/lu"
function App() {
return (
<Accordion.Root multiple>
<Accordion.Item value="item-0">
<Accordion.ItemTrigger>
<Box flex="1" textAlign="left">
Section 1 title
</Box>
<Accordion.ItemIndicator />
</Accordion.ItemTrigger>
<Accordion.ItemContent>
<Accordion.ItemBody>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</Accordion.ItemBody>
</Accordion.ItemContent>
</Accordion.Item>
<Accordion.Item value="item-1">
<CustomItemContent />
</Accordion.Item>
</Accordion.Root>
)
}
function CustomItemContent() {
const { open } = useAccordionItemContext()
return (
<>
<Accordion.ItemTrigger>
<Box flex="1" textAlign="left">
Section 2 title
</Box>
{open ? <LuMinus size={12} /> : <LuPlus size={12} />}
</Accordion.ItemTrigger>
<Accordion.ItemContent>
<Accordion.ItemBody>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</Accordion.ItemBody>
</Accordion.ItemContent>
</>
)
}
Accordion.ItemContext Componentimport { Accordion, Box } from "@chakra-ui/react"
import { LuMinus, LuPlus } from "react-icons/lu"
function App() {
return (
<Accordion.Root multiple>
<Accordion.Item value="item-0">
<Accordion.ItemTrigger>
<Box flex="1" textAlign="left">
Section 1 title
</Box>
<Accordion.ItemIndicator />
</Accordion.ItemTrigger>
<Accordion.ItemContent>
<Accordion.ItemBody>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</Accordion.ItemBody>
</Accordion.ItemContent>
</Accordion.Item>
<Accordion.Item value="item-1">
<Accordion.ItemContext>
{({ open }) => (
<>
<Accordion.ItemTrigger>
<Box flex="1" textAlign="left">
Section 2 title
</Box>
{open ? <LuMinus size={12} /> : <LuPlus size={12} />}
</Accordion.ItemTrigger>
<Accordion.ItemContent>
<Accordion.ItemBody>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</Accordion.ItemBody>
</Accordion.ItemContent>
</>
)}
</Accordion.ItemContext>
</Accordion.Item>
</Accordion.Root>
)
}
Accordion → Accordion.RootAccordionItem → Accordion.ItemAccordionButton → Accordion.ItemTriggerAccordionIcon → Accordion.ItemIndicatorAccordionPanel → Accordion.ItemContent + Accordion.ItemBodyAccordion.Item now requires a value prop (string)
"about", "features", etc.item-0, item-1, etc.| v2 | v3 |
|---|---|
allowMultiple | multiple |
allowToggle | collapsible |
defaultIndex={0} | defaultValue={["0"]} (array of strings) |
index={1} | value={["1"]} (array of strings) |
onChange={(index) => ...} | onValueChange={({ value }) => ...} |
{({ isExpanded }) => ...} render prop on AccordionItemuseAccordionItemContext() hook or Accordion.ItemContext componentisExpanded → opennpx @chakra-ui/codemod@latest --transform accordion src/**/*.tsx
value props - Replace item-0, item-1 with
meaningful IDsuseAccordionItemContext() hook or
Accordion.ItemContext componentAccordionButton,
AccordionIcon, etc.)