packages/codemod/docs/CHECKBOX_MIGRATION.md
This document outlines the migration from Chakra UI v2 Checkbox component to v3.
<Checkbox>Label Text</Checkbox>
<Checkbox.Root>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Label Text</Checkbox.Label>
</Checkbox.Root>
| v2 Prop | v3 Prop | Notes |
|---|---|---|
isChecked | checked | Standard prop name |
isDisabled | disabled | Standard HTML attribute |
isInvalid | invalid | Simplified prop name |
isReadOnly | readOnly | Standard prop name |
isRequired | required | Standard HTML attribute |
isIndeterminate | checked="indeterminate" | Special value for checked prop |
isFocusable | (removed) | Not supported in v3 |
| v2 Prop | v3 Prop/Location | Notes |
|---|---|---|
colorScheme | colorPalette | Renamed for consistency |
onChange | onCheckedChange | Renamed for clarity |
icon | Checkbox.Control children | Custom icon replaces Indicator |
iconColor | color on Indicator/Icon | Applied to icon element |
iconSize | boxSize on Indicator/Icon | Applied to icon element |
inputProps | Spread into Checkbox.HiddenInput | Props for hidden input element |
tabIndex | Checkbox.HiddenInput | Moved to hidden input |
| v2 Prop | v3 Prop | Notes |
|---|---|---|
isDisabled | disabled | Simplified prop name |
isNative | (removed) | Not supported in v3 |
onChange | onValueChange | Receives array of checked values |
v2:
import { Checkbox } from "@chakra-ui/react"
;<Checkbox defaultChecked>Accept terms</Checkbox>
v3:
import { Checkbox } from "@chakra-ui/react"
;<Checkbox.Root defaultChecked>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Accept terms</Checkbox.Label>
</Checkbox.Root>
v2:
import { Checkbox } from '@chakra-ui/react'
<Checkbox isDisabled>Checkbox</Checkbox>
<Checkbox isDisabled defaultChecked>Checkbox</Checkbox>
v3:
import { Checkbox } from '@chakra-ui/react'
<Checkbox.Root disabled>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Checkbox</Checkbox.Label>
</Checkbox.Root>
<Checkbox.Root disabled defaultChecked>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Checkbox</Checkbox.Label>
</Checkbox.Root>
v2:
import { Checkbox } from '@chakra-ui/react'
<Checkbox colorScheme='red' defaultChecked>
Checkbox
</Checkbox>
<Checkbox colorScheme='green' defaultChecked>
Checkbox
</Checkbox>
v3:
import { Checkbox } from '@chakra-ui/react'
<Checkbox.Root colorPalette='red' defaultChecked>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Checkbox</Checkbox.Label>
</Checkbox.Root>
<Checkbox.Root colorPalette='green' defaultChecked>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Checkbox</Checkbox.Label>
</Checkbox.Root>
v2:
import { Checkbox, Stack } from "@chakra-ui/react"
;<Stack spacing={[1, 5]} direction={["column", "row"]}>
<Checkbox size="sm" colorScheme="red">
Small
</Checkbox>
<Checkbox size="md" colorScheme="green" defaultChecked>
Medium
</Checkbox>
<Checkbox size="lg" colorScheme="orange" defaultChecked>
Large
</Checkbox>
</Stack>
v3:
import { Checkbox, Stack } from "@chakra-ui/react"
;<Stack spacing={[1, 5]} direction={["column", "row"]}>
<Checkbox.Root size="sm" colorPalette="red">
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Small</Checkbox.Label>
</Checkbox.Root>
<Checkbox.Root size="md" colorPalette="green" defaultChecked>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Medium</Checkbox.Label>
</Checkbox.Root>
<Checkbox.Root size="lg" colorPalette="orange" defaultChecked>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Large</Checkbox.Label>
</Checkbox.Root>
</Stack>
v2:
import { Checkbox } from "@chakra-ui/react"
;<Checkbox isInvalid>Checkbox</Checkbox>
v3:
import { Checkbox } from "@chakra-ui/react"
;<Checkbox.Root invalid>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Checkbox</Checkbox.Label>
</Checkbox.Root>
v2:
import { Checkbox } from "@chakra-ui/react"
;<Checkbox iconColor="blue.400" iconSize="1rem">
Option
</Checkbox>
v3:
import { Checkbox } from "@chakra-ui/react"
;<Checkbox.Root>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator color="blue.400" boxSize="1rem" />
</Checkbox.Control>
<Checkbox.Label>Option</Checkbox.Label>
</Checkbox.Root>
v2:
import { CheckIcon } from "@chakra-ui/icons"
import { Checkbox } from "@chakra-ui/react"
;<Checkbox icon={<CheckIcon />}>Custom Icon</Checkbox>
v3:
import { CheckIcon } from "@chakra-ui/icons"
import { Checkbox } from "@chakra-ui/react"
;<Checkbox.Root>
<Checkbox.HiddenInput />
<Checkbox.Control>
<CheckIcon />
</Checkbox.Control>
<Checkbox.Label>Custom Icon</Checkbox.Label>
</Checkbox.Root>
v2:
import { Checkbox } from "@chakra-ui/react"
function App() {
const [isIndeterminate, setIsIndeterminate] = useState(true)
return (
<Checkbox isIndeterminate={isIndeterminate} isChecked={allChecked}>
Select All
</Checkbox>
)
}
v3:
import { Checkbox } from "@chakra-ui/react"
function App() {
const [isIndeterminate, setIsIndeterminate] = useState(true)
return (
<Checkbox.Root checked={isIndeterminate ? "indeterminate" : allChecked}>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Select All</Checkbox.Label>
</Checkbox.Root>
)
}
v2:
import { Checkbox } from "@chakra-ui/react"
function App() {
const [checked, setChecked] = useState(false)
return (
<Checkbox
isChecked={checked}
onChange={(e) => setChecked(e.target.checked)}
>
Remember me
</Checkbox>
)
}
v3:
import { Checkbox } from "@chakra-ui/react"
function App() {
const [checked, setChecked] = useState(false)
return (
<Checkbox.Root
checked={checked}
onCheckedChange={(e) => setChecked(!!e.checked)}
>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Remember me</Checkbox.Label>
</Checkbox.Root>
)
}
v2:
import { Checkbox, CheckboxGroup, Stack } from "@chakra-ui/react"
function App() {
const [values, setValues] = useState(["react"])
return (
<CheckboxGroup value={values} onChange={setValues}>
<Stack direction="column">
<Checkbox value="react">React</Checkbox>
<Checkbox value="vue">Vue</Checkbox>
<Checkbox value="svelte">Svelte</Checkbox>
</Stack>
</CheckboxGroup>
)
}
v3:
import { Checkbox, CheckboxGroup, Stack } from "@chakra-ui/react"
function App() {
const [values, setValues] = useState(["react"])
return (
<CheckboxGroup value={values} onValueChange={setValues}>
<Stack direction="column">
<Checkbox.Root value="react">
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>React</Checkbox.Label>
</Checkbox.Root>
<Checkbox.Root value="vue">
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Vue</Checkbox.Label>
</Checkbox.Root>
<Checkbox.Root value="svelte">
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Svelte</Checkbox.Label>
</Checkbox.Root>
</Stack>
</CheckboxGroup>
)
}
v2:
import { Checkbox, CheckboxGroup } from "@chakra-ui/react"
;<CheckboxGroup isDisabled>
<Checkbox>Option 1</Checkbox>
<Checkbox>Option 2</Checkbox>
</CheckboxGroup>
v3:
import { Checkbox, CheckboxGroup } from "@chakra-ui/react"
;<CheckboxGroup disabled>
<Checkbox.Root>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Option 1</Checkbox.Label>
</Checkbox.Root>
<Checkbox.Root>
<Checkbox.HiddenInput />
<Checkbox.Control>
<Checkbox.Indicator />
</Checkbox.Control>
<Checkbox.Label>Option 2</Checkbox.Label>
</Checkbox.Root>
</CheckboxGroup>
To automatically migrate your Checkbox components, run:
npx @chakra-ui/codemod transform checkbox <path>
--dry - Do a dry-run without making changes--print - Print the changed output for comparison# Transform all files in src directory
npx @chakra-ui/codemod transform checkbox ./src
# Dry run to preview changes
npx @chakra-ui/codemod transform checkbox ./src --dry
# Print changes for comparison
npx @chakra-ui/codemod transform checkbox ./src --print
If you prefer to migrate manually:
Restructure Components:
<Checkbox> → <Checkbox.Root><Checkbox.HiddenInput /> as first child<Checkbox.Control> with <Checkbox.Indicator /> or custom icon<Checkbox.Label>Update Props:
isChecked → checkedisDisabled → disabledisInvalid → invalidisReadOnly → readOnlyisRequired → requiredisIndeterminate → checked="indeterminate" (or ternary expression)onChange → onCheckedChangecolorScheme → colorPaletteisFocusableHandle Special Props:
icon prop content into <Checkbox.Control>iconColor as color on Indicator/iconiconSize as boxSize on Indicator/iconinputProps into <Checkbox.HiddenInput>tabIndex to <Checkbox.HiddenInput>Update CheckboxGroup:
isDisabled → disabledonChange → onValueChangeisNativeisChecked → checkedisDisabled → disabledisInvalid → invalidisReadOnly → readOnlyisRequired → requiredonChange → onCheckedChangecolorScheme → colorPaletteicon → Checkbox.Control childreniconColor → color on Indicator/icon elementiconSize → boxSize on Indicator/icon elementinputProps → spread into Checkbox.HiddenInputtabIndex → Checkbox.HiddenInputisFocusable - no longer supportedisIndeterminate → use checked="indeterminate" or ternary expressionisDisabled → disabledisNative → removedonChange → onValueChange (receives array of values)The codemod will:
<Checkbox> to <Checkbox.Root> structurecolorScheme to colorPaletteonChange to onCheckedChangeisIndeterminate transformation to checked ternaryicon prop to Checkbox.ControliconColor and iconSize to Indicator/iconinputProps and tabIndex to Checkbox.HiddenInputThe v3 Checkbox component provides:
onCheckedChange event in v3 receives an object with a checked
property, not a DOM eventchecked prop can accept true, false, or "indeterminate" as values