# Checkbox

Checkbox is a type of control component that allows user to select one or more options from a set. They can also be used alone to switch between on and off.

## Import

```tsx
import { Checkbox } from '@coinbase/cds-mobile/controls/Checkbox'
```

## Examples

### Basic Usage

Checkbox UI and state management are separated so that you can swap in any form or state code you like.

```jsx
function BasicCheckbox() {
  const [isChecked, setIsChecked] = useState(false);
  return (
    <Checkbox value="newsletter" onChange={setIsChecked} checked={isChecked}>
      Subscribe to newsletter
    </Checkbox>
  );
}
```

### Custom Layout

If you don't want to use the default label or layout style, you can just not provide `children` to the `Checkbox` component. However, you should think about wrapping the custom label and `Checkbox` in a `Pressable` to increase the tap target.

```jsx
function CustomLayoutCheckbox() {
  const [isChecked, setIsChecked] = useState(false);
  return (
    <Pressable onPress={() => setIsChecked(!isChecked)}>
      <HStack justifyContent="space-between" alignItems="center" paddingY={2}>
        <VStack gap={0} alignItems="flex-start">
          <Text font="body">Premium Features</Text>
          <Text font="caption" color="fgMuted">
            Access to advanced tools and priority support
          </Text>
        </VStack>
        <Checkbox value="premium" onChange={setIsChecked} checked={isChecked} />
      </HStack>
    </Pressable>
  );
}
```

### Different States

Checkboxes support various states including disabled and indeterminate.

```jsx
function CheckboxStates() {
  const [checked, setChecked] = useState(false);
  const [indeterminate, setIndeterminate] = useState(true);

  return (
    <VStack gap={2}>
      <Checkbox value="enabled" onChange={setChecked} checked={checked}>
        Normal checkbox
      </Checkbox>
      <Checkbox value="disabled-unchecked" checked={false} disabled>
        Disabled & unchecked
      </Checkbox>
      <Checkbox value="disabled-checked" checked={true} disabled>
        Disabled & checked
      </Checkbox>
      <Checkbox
        value="indeterminate"
        indeterminate={indeterminate}
        onChange={() => {
          setIndeterminate(false);
          // Handle the change as needed
        }}
        accessibilityLabel="Partially selected option"
      >
        Indeterminate state
      </Checkbox>
    </VStack>
  );
}
```

### Accessibility

Mobile checkboxes should include proper accessibility labels and hints for screen readers.

```jsx
function AccessibleCheckbox() {
  const [settings, setSettings] = useState({
    notifications: true,
    location: false,
    analytics: false,
  });

  const updateSetting = (key) => {
    setSettings((prev) => ({ ...prev, [key]: !prev[key] }));
  };

  return (
    <VStack gap={2}>
      <Checkbox
        value="notifications"
        checked={settings.notifications}
        onChange={() => updateSetting('notifications')}
        accessibilityLabel="Enable push notifications"
        accessibilityHint="Receive alerts about important updates"
      >
        Push Notifications
      </Checkbox>
      <Checkbox
        value="location"
        checked={settings.location}
        onChange={() => updateSetting('location')}
        accessibilityLabel="Share location data"
        accessibilityHint="Used for location-based features"
      >
        Location Services
      </Checkbox>
      <Checkbox
        value="analytics"
        checked={settings.analytics}
        onChange={() => updateSetting('analytics')}
        accessibilityLabel="Allow analytics tracking"
        accessibilityHint="Helps improve the app experience"
      >
        Analytics
      </Checkbox>
    </VStack>
  );
}
```

### Custom Colors

Like other control components (i.e. Radio, Switch), you can customize the color of the Checkbox by setting the `controlColor` prop.

```jsx
function CustomColors() {
  const [checked, setChecked] = useState(false);

  return (
    <Checkbox
      controlColor="accentBoldGreen"
      onChange={() => setChecked((s) => !s)}
      checked={checked}
    >
      Custom control color
    </Checkbox>
  );
}
```

For more advanced color customization, you can use additional style props like `background`, `borderColor`, `borderRadius`, and `borderWidth`:

```jsx
function AdvancedCustomColors() {
  const [checked, setChecked] = useState(false);

  return (
    <Checkbox
      background={checked ? 'accentBoldPurple' : 'bgNegative'}
      borderColor={checked ? 'bgPositive' : 'bgPrimary'}
      borderRadius={200}
      borderWidth={500}
      checked={checked}
      controlColor="bgPositive"
      onChange={() => setChecked((s) => !s)}
    >
      Advanced styling
    </Checkbox>
  );
}
```

### Multiple Checkboxes

For multiple checkbox scenarios, use [ControlGroup](/components/inputs/ControlGroup) with `accessibilityRole="group"` for better accessibility and state management:

```jsx
function MultipleCheckboxes() {
  const options = [
    { value: 'email', children: 'Email notifications' },
    { value: 'sms', children: 'SMS notifications' },
    { value: 'push', children: 'Push notifications' },
  ];

  const [selectedValues, setSelectedValues] = useState(['email']);

  const handleChange = (value, checked) => {
    setSelectedValues((prev) => (checked ? [...prev, value] : prev.filter((v) => v !== value)));
  };

  return (
    <ControlGroup
      accessibilityRole="group"
      ControlComponent={Checkbox}
      label="Notification Preferences"
      options={options}
      value={selectedValues}
      onChange={handleChange}
      name="notifications"
    />
  );
}
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `background` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | Background color of the overlay (element being interacted with). |
| `borderColor` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
| `borderRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `100` | Optional.Sets the border width of the checkbox. |
| `checked` | `boolean` | No | `-` | Set the control to selected/on. |
| `children` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Label for the control option. |
| `color` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
| `controlColor` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `bgPrimary bgPrimary` | Sets the checked/active color of the control. |
| `disabled` | `boolean` | No | `-` | Disable user interaction. |
| `indeterminate` | `boolean` | No | `-` | Enable indeterminate state. Useful when you want to indicate that sub-items of a control are partially filled. |
| `onChange` | `((value: T, checked?: boolean \| undefined) => void) \| undefined` | No | `-` | Toggle control selected state. |
| `onPointerCancel` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerCancelCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerDown` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerDownCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerEnter` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerEnterCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerLeave` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerLeaveCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerMove` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerMoveCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerUp` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerUpCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPress` | `((event: GestureResponderEvent) => void) \| null` | No | `-` | Called when a single tap gesture is detected. |
| `readOnly` | `boolean` | No | `-` | Set the control to ready-only. Similar effect as disabled. |
| `ref` | `null \| (instance: View \| null) => void \| RefObject<View>` | No | `-` | - |
| `style` | `ViewStyle` | No | `-` | - |
| `testID` | `string` | No | `-` | Used to locate this view in end-to-end tests. |
| `value` | `string` | No | `-` | Value of the option. Useful for multiple choice. |


