Skip to content

Checkbox

A Checkbox wears the checkbox pattern from @hozo/patterns: on the Web it is a <button> with role="checkbox", so the browser makes it focusable and lets Space toggle it, and on React Native it is a Pressable with the same role. The box and its tick are drawn from the checked state the pattern reports, so the look cannot disagree with what a screen reader announces.

Chosen: Lunch
CheckboxDemo.tsx
import { Text, View } from '@hozo/core'
import { Checkbox } from '@hozo/ui'
import { useState } from 'react'
const MEALS = ['Breakfast', 'Lunch', 'Dinner']
export function CheckboxDemo() {
const [meals, setMeals] = useState<string[]>(['Lunch'])
const all = meals.length === MEALS.length ? true : meals.length === 0 ? false : 'mixed'
return (
<View className="gap-2">
<Checkbox checked={all} onCheckedChange={(next) => setMeals(next ? MEALS : [])}>
All meals
</Checkbox>
{MEALS.map((meal) => (
<Checkbox
key={meal}
className="ps-6"
checked={meals.includes(meal)}
onCheckedChange={(next) =>
setMeals((chosen) => (next ? [...chosen, meal] : chosen.filter((m) => m !== meal)))
}
>
{meal}
</Checkbox>
))}
<Text className="text-sm text-hozo-text-muted">Chosen: {meals.join(', ') || 'none'}</Text>
</View>
)
}
  • checked: true, false or 'mixed'. Mixed is the state no input attribute can express: the parent above is mixed while some but not all of the meals are chosen.
  • onCheckedChange: called with the next true or false. Pressing a mixed box checks it.
  • defaultChecked: for an uncontrolled checkbox.
  • disabled, accessibilityLabel and className do what they say. The children are the label, and pressing the label toggles the box.