# Checkbox

Import: `import { Checkbox } from '@neo4j-ndl/react'`

## Props

### Checkbox

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `ariaLabel` | `string` |  |  | The aria label of the checkbox. Required if the label is not a string. |
| `hasLeadingLabel` | `boolean` |  |  | Whether the label should be displayed before the checkbox |
| `isChecked` | `boolean` |  |  | Whether the checkbox is checked |
| `isDefaultChecked` | `boolean` |  |  | Checks the input by default in uncontrolled mode |
| `isDisabled` | `boolean` |  | `false` | Whether the checkbox is disabled |
| `isFluid` | `boolean` |  | `false` | Whether the checkbox & label should take the full available width of its container |
| `isIndeterminate` | `boolean` |  | `false` | Whether the checkbox is indeterminate |
| `label` | `ReactNode` |  |  | The label of the checkbox. If not a string, supply an aria label for screen reader support. |
| `onChange` | `((event: ChangeEvent<HTMLInputElement, Element>) => void)` |  |  | The callback function triggered when the checkbox value changes |
| `onClick` | `((event: MouseEvent<HTMLInputElement, MouseEvent>) => void)` |  |  | The callback function triggered when the checkbox is clicked |
| `ref` | `Ref<HTMLInputElement>` |  |  | A ref to apply to the root element. |
| `value` | `string \| number \| readonly string[]` |  |  | The value of the checkbox |

## Accessibility

## Implementation guidelines

The Checkbox component uses implicit label wrapping to associate the visible label with the input for screen readers. If you omit the label prop or use an invalid label (no text content), the `ariaLabel` prop will be required to ensure an accessible name.

## Examples

### Default

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { Checkbox } from '@neo4j-ndl/react';

const Component = () => {
  return <Checkbox label="Uncontrolled checkbox" />;
};

export default Component;
```

### Controlled

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { Checkbox } from '@neo4j-ndl/react';
import { useState } from 'react';

const Component = () => {
  const [isChecked, setIsChecked] = useState(false);
  return (
    <Checkbox
      isChecked={isChecked}
      onChange={(event) => setIsChecked(event.target.checked)}
      label="Controlled checkbox"
    />
  );
};

export default Component;
```

### Disabled

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { Checkbox } from '@neo4j-ndl/react';

const Component = () => {
  return <Checkbox label="Checkbox label" isDisabled />;
};

export default Component;
```

### Fluid

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { Checkbox } from '@neo4j-ndl/react';

const Component = () => {
  return <Checkbox isFluid />;
};

export default Component;
```

### Full

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { Checkbox } from '@neo4j-ndl/react';
import { useState } from 'react';

const Component = () => {
  const [childCheckboxes, setChildCheckboxes] = useState({
    childOne: false,
    childThree: true,
    childTwo: false,
  });

  const handleParentCheckboxChange = (
    event: React.ChangeEvent<HTMLInputElement>,
  ) => {
    const isChecked = event.target.checked;

    // Update child checkboxes based on parent checkbox state.
    setChildCheckboxes({
      childOne: isChecked,
      childThree: isChecked,
      childTwo: isChecked,
    });
  };

  const handleChildCheckboxChange = (
    childKey: keyof typeof childCheckboxes,
  ) => {
    // Set currently clicked child checkbox.
    setChildCheckboxes((prevState) => ({
      ...prevState,
      [childKey]: !prevState[childKey],
    }));
  };

  const isParentChecked = Object.values(childCheckboxes).every(
    (isChildChecked) => isChildChecked,
  );

  const isParentIndeterminate =
    Object.values(childCheckboxes).some((isChildChecked) => isChildChecked) &&
    !isParentChecked;

  return (
    <div className="n-flex n-flex-col n-items-start n-gap-1">
      <Checkbox
        isChecked={isParentChecked}
        isIndeterminate={isParentIndeterminate}
        label="Parent checkbox"
        onChange={(event) => {
          handleParentCheckboxChange(event);
        }}
      />
      <Checkbox
        className="n-ml-7"
        isChecked={childCheckboxes.childOne}
        label="Child checkbox 1"
        onChange={() => handleChildCheckboxChange('childOne')}
      />
      <Checkbox
        className="n-ml-7"
        isChecked={childCheckboxes.childTwo}
        label="Child checkbox 2"
        onChange={() => handleChildCheckboxChange('childTwo')}
      />
      <Checkbox
        className="n-ml-7"
        isChecked={childCheckboxes.childThree}
        label="Child checkbox 3"
        onChange={() => handleChildCheckboxChange('childThree')}
      />
    </div>
  );
};

export default Component;
```

### Has Label Before

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { Checkbox } from '@neo4j-ndl/react';

const Component = () => {
  return <Checkbox label="Checkbox label" hasLeadingLabel />;
};

export default Component;
```

### Indeterminate

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { Checkbox, FilledButton } from '@neo4j-ndl/react';
import { useState } from 'react';

const Component = () => {
  const [isChecked, setIsChecked] = useState(false);
  const [isIndeterminate, setIsIndeterminate] = useState(true);

  return (
    <div
      style={{
        alignItems: 'center',
        display: 'flex',
        flexDirection: 'column',
        gap: '10px',
      }}
    >
      <Checkbox
        isChecked={isChecked}
        isIndeterminate={isIndeterminate}
        onChange={(event) => {
          setIsChecked(event.target.checked);
          setIsIndeterminate(event.target.indeterminate);
        }}
        ariaLabel="Indeterminate checkbox"
      />
      <div style={{ marginTop: '25px', width: '100%' }}>
        <div>Checkbox checked state: {isChecked.toString()}</div>
        <div>Checkbox indeterminate state: {isIndeterminate.toString()}</div>
      </div>
      <div>
        <FilledButton onClick={() => setIsChecked((prev: boolean) => !prev)}>
          Toggle checked
        </FilledButton>
        <FilledButton
          onClick={() => setIsIndeterminate((prev: boolean) => !prev)}
          style={{ marginLeft: '10px' }}
        >
          Toggle indeterminate
        </FilledButton>
      </div>
    </div>
  );
};

export default Component;
```

### Label Before

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { Checkbox } from '@neo4j-ndl/react';

const Component = () => {
  return <Checkbox hasLeadingLabel label="Label" />;
};

export default Component;
```

### No Label

```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';

import { Checkbox } from '@neo4j-ndl/react';

const Component = () => {
  return <Checkbox ariaLabel="no-label-provided" />;
};

export default Component;
```
