packages/codemod/docs/BREADCRUMB_MIGRATION.md
This guide explains how to migrate from Chakra UI v2 Breadcrumb components to the v3 compound component API.
In Chakra UI v3, the Breadcrumb component has been redesigned to use a compound component pattern with explicit separators. This provides better control over structure, styling, and accessibility.
npx @chakra-ui/codemod@latest breadcrumb <path>
This will automatically transform all Breadcrumb components in your codebase.
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from "@chakra-ui/react"
;<Breadcrumb>
<BreadcrumbItem>
<BreadcrumbLink href="#">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem isCurrentPage>
<BreadcrumbLink href="#">Current</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>
import { Breadcrumb } from "@chakra-ui/react"
;<Breadcrumb.Root>
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.CurrentLink>Current</Breadcrumb.CurrentLink>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb.Root>
Key Changes:
Breadcrumb → Breadcrumb.RootBreadcrumb.ListBreadcrumbItem → Breadcrumb.ItemBreadcrumbLink → Breadcrumb.Link or Breadcrumb.CurrentLink<Breadcrumb.Separator /> between itemsimport {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbSeparator,
} from "@chakra-ui/react"
import { Breadcrumb } from "@chakra-ui/react"
All subcomponents are accessed via Breadcrumb.* (compound component pattern).
Before (v2):
<Breadcrumb spacing="8px"></Breadcrumb>
After (v3):
<Breadcrumb.Root>
<Breadcrumb.List gap="8px"></Breadcrumb.List>
</Breadcrumb.Root>
Changes:
spacing prop moved to Breadcrumb.List and renamed to gapThe separator prop has been removed in favor of explicit
<Breadcrumb.Separator /> components.
Before (v2) - String Separator:
<Breadcrumb separator="-">
<BreadcrumbItem>
<BreadcrumbLink href="#">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbLink href="#">About</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>
After (v3):
<Breadcrumb.Root>
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator>-</Breadcrumb.Separator>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">About</Breadcrumb.Link>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb.Root>
Before (v2) - Icon Separator:
import { ChevronRightIcon } from "@chakra-ui/icons"
;<Breadcrumb separator={<ChevronRightIcon color="gray.500" />}>
<BreadcrumbItem>
<BreadcrumbLink href="#">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbLink href="#">About</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>
After (v3):
import { ChevronRightIcon } from "@chakra-ui/icons"
;<Breadcrumb.Root>
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator>
<ChevronRightIcon color="gray.500" />
</Breadcrumb.Separator>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">About</Breadcrumb.Link>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb.Root>
Changes:
separator prop → explicit <Breadcrumb.Separator> components between itemsseparator prop was presentBefore (v2):
<Breadcrumb listProps={{ className: "custom-list", id: "breadcrumb" }}>
</Breadcrumb>
After (v3):
<Breadcrumb.Root>
<Breadcrumb.List className="custom-list" id="breadcrumb">
</Breadcrumb.List>
</Breadcrumb.Root>
Changes:
listProps → spread directly on Breadcrumb.ListBefore (v2):
<BreadcrumbItem isCurrentPage>
<BreadcrumbLink href="#">Current</BreadcrumbLink>
</BreadcrumbItem>
After (v3):
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Current</Breadcrumb.Link>
</Breadcrumb.Item>
⚠️ Note: The isCurrentPage prop is removed from BreadcrumbItem. To mark
a page as current, use isCurrentPage on BreadcrumbLink (see below) or use
Breadcrumb.CurrentLink directly.
Before (v2):
<BreadcrumbItem isLastChild>
<BreadcrumbLink href="#">Last</BreadcrumbLink>
</BreadcrumbItem>
After (v3):
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Last</Breadcrumb.Link>
</Breadcrumb.Item>
Changes:
isLastChild prop is removed (no longer needed with explicit separators)Before (v2):
<BreadcrumbItem spacing="2">
<BreadcrumbLink href="#">Home</BreadcrumbLink>
</BreadcrumbItem>
After (v3):
<Breadcrumb.Item gap="2">
<Breadcrumb.Link href="#">Home</Breadcrumb.Link>
</Breadcrumb.Item>
Changes:
spacing → gapBefore (v2):
<BreadcrumbItem>
<BreadcrumbLink href="#" isCurrentPage>
Current
</BreadcrumbLink>
</BreadcrumbItem>
After (v3):
<Breadcrumb.Item>
<Breadcrumb.CurrentLink href="#">Current</Breadcrumb.CurrentLink>
</Breadcrumb.Item>
Changes:
BreadcrumbLink with isCurrentPage → Breadcrumb.CurrentLinkisCurrentPage prop is removedBefore (v2):
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from "@chakra-ui/react"
export default function App() {
return (
<Breadcrumb>
<BreadcrumbItem>
<BreadcrumbLink href="#">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbLink href="#">Docs</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem isCurrentPage>
<BreadcrumbLink href="#">Breadcrumb</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>
)
}
After (v3):
import { Breadcrumb } from "@chakra-ui/react"
export default function App() {
return (
<Breadcrumb.Root>
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Docs</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.CurrentLink>Breadcrumb</Breadcrumb.CurrentLink>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb.Root>
)
}
Before (v2):
import { ChevronRightIcon } from "@chakra-ui/icons"
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from "@chakra-ui/react"
export default function App() {
return (
<Breadcrumb spacing="8px" separator={<ChevronRightIcon color="gray.500" />}>
<BreadcrumbItem>
<BreadcrumbLink href="#">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbLink href="#">About</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem isCurrentPage>
<BreadcrumbLink href="#">Contact</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>
)
}
After (v3):
import { ChevronRightIcon } from "@chakra-ui/icons"
import { Breadcrumb } from "@chakra-ui/react"
export default function App() {
return (
<Breadcrumb.Root>
<Breadcrumb.List gap="8px">
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator>
<ChevronRightIcon color="gray.500" />
</Breadcrumb.Separator>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">About</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator>
<ChevronRightIcon color="gray.500" />
</Breadcrumb.Separator>
<Breadcrumb.Item>
<Breadcrumb.CurrentLink>Contact</Breadcrumb.CurrentLink>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb.Root>
)
}
Before (v2):
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from "@chakra-ui/react"
export default function App() {
return (
<Breadcrumb fontWeight="medium" fontSize="sm">
<BreadcrumbItem>
<BreadcrumbLink href="#">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbLink href="#">About</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem isCurrentPage>
<BreadcrumbLink href="#">Current</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>
)
}
After (v3):
import { Breadcrumb } from "@chakra-ui/react"
export default function App() {
return (
<Breadcrumb.Root fontWeight="medium" fontSize="sm">
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Link href="#">About</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.CurrentLink>Current</Breadcrumb.CurrentLink>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb.Root>
)
}
After running the codemod, review your code for:
Breadcrumb.CurrentLink is used
for current pagesgap prop on Breadcrumb.List provides the desired
spacingaria-current="page" is set on current links
(automatic with CurrentLink)If you have isCurrentPage on BreadcrumbItem (not on BreadcrumbLink), the
codemod will remove the prop but won't automatically convert the link to
CurrentLink. You may need to manually change these:
// This pattern may need manual adjustment
<BreadcrumbItem isCurrentPage>
<BreadcrumbLink href='#'>Current</BreadcrumbLink>
</BreadcrumbItem>
// Should become:
<Breadcrumb.Item>
<Breadcrumb.CurrentLink href='#'>Current</Breadcrumb.CurrentLink>
</Breadcrumb.Item>
Workaround: Use isCurrentPage on BreadcrumbLink in v2 code before
running the codemod.
After migration, test:
If you encounter issues during migration: