Checkbox
Checkboxes allow users to select one or more items from a set, or turn an option on or off. Follows the Material Design 3 Checkbox specification.
Usage
import { Checkbox } from '@rootnative/components'
import { mdiResolver } from '@rootnative/components/mdi'
import { ThemeProvider } from '@rootnative/core'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { useState } from 'react'
import { View } from 'react-native'
export default function App() {
const [isChecked, setIsChecked] = useState(false)
return (
<SafeAreaProvider>
<ThemeProvider iconResolver={mdiResolver}>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Checkbox value={isChecked} onValueChange={setIsChecked} />
</View>
</ThemeProvider>
</SafeAreaProvider>
)
}
Controlled or uncontrolled
Pass value with onValueChange to own the state, as above. Omit value and
Checkbox manages its own, starting from defaultValue:
<Checkbox defaultValue onValueChange={handleChange} />
onValueChange still fires either way. In earlier prereleases, passing
onValueChange without value did nothing visually — the callback fired but
the control never moved. See the changelog if you are upgrading.
Multiple Checkboxes
import { Checkbox } from '@rootnative/components'
import { mdiResolver } from '@rootnative/components/mdi'
import { ThemeProvider } from '@rootnative/core'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { useState } from 'react'
import { View } from 'react-native'
export default function App() {
const [a, setA] = useState(true)
const [b, setB] = useState(false)
const [c, setC] = useState(false)
return (
<SafeAreaProvider>
<ThemeProvider iconResolver={mdiResolver}>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', gap: 12 }}>
<Checkbox value={a} onValueChange={setA} />
<Checkbox value={b} onValueChange={setB} />
<Checkbox value={c} onValueChange={setC} />
</View>
</ThemeProvider>
</SafeAreaProvider>
)
}
Disabled
import { Checkbox } from '@rootnative/components'
import { mdiResolver } from '@rootnative/components/mdi'
import { ThemeProvider } from '@rootnative/core'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { View } from 'react-native'
export default function App() {
return (
<SafeAreaProvider>
<ThemeProvider iconResolver={mdiResolver}>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', gap: 12 }}>
<Checkbox value={false} onValueChange={() => {}} disabled />
<Checkbox value onValueChange={() => {}} disabled />
</View>
</ThemeProvider>
</SafeAreaProvider>
)
}
In a list row
To let the full ListItem toggle the checkbox, put onPress on the row and
give the checkbox value with no onValueChange. The checkbox then only shows
the state, and the row takes the press. See
Selection controls in a row.
Props
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
value | boolean | - | No | Whether the checkbox is checked (controlled). Pass this together with `onValueChange` to own the state. Omit it and the component manages its own state, starting from `defaultValue`. |
defaultValue | boolean | | No | Initial value when uncontrolled. Ignored once `value` is passed. |
onValueChange | (value: boolean) => void | - | No | Callback fired when the checkbox is toggled. Receives the new value. With `value` set and no `onValueChange`, the checkbox only shows the state. It takes no press, leaves the tab order, and is hidden from assistive technology. Use this in a pressable `ListItem`, and give the row `role="checkbox"` and `aria-checked`. The row then carries the press and the state. A disabled checkbox is never hidden. |
indeterminate | boolean | | No | Render the MD3 indeterminate ("mixed") state — a dash mark on the selected container colors. Wins over `value` visually, and reports `checked: 'mixed'` to accessibility. |
error | boolean | | No | Render the MD3 error state: `error`-colored outline when unchecked, and an `error` container with `onError` mark when checked or indeterminate. State-layer (hover, focus, press) colors also use `error`. The standard disabled treatment wins over the error state. |
checkIcon | IconSource | check | No | Icon shown when the checkbox is checked. Accepts a string name (resolved via the theme's `iconResolver`, for example `mdiResolver`), a pre-rendered element, or a render function that receives `{ size, color }`. Override this when your `iconResolver` doesn't map the default `'check'` name (e.g. a Lucide-only resolver). |
containerColor | string | - | No | Override the container (box) color when checked. State-layer colors (hover, press) are derived automatically. |
contentColor | string | - | No | Override the checkmark icon color. |
style | StyleProp<ViewStyle> | - | No | Style applied to the root container. Static form only — the function form `(state) => style` is not supported because the component drives its container background through Reanimated. Use `containerColor` / `contentColor` for state-aware styling. |
hrefAttrs | { target?: string; rel?: string; download?: string | boolean; } | - | No | Web only. The `target`, `rel` and `download` of the `<a>` that a view with an `href` renders, for example under Expo Router's `<Link asChild>`. `target: '_blank'` opens the link in a new tab. Native ignores it. |
onKeyDown | (event: PressableKeyDownEvent) => void | - | No | - |