---
title: Filter
description: A styled checkbox component for filtering content, with optional dropdown indicator
---

```tsx
'use client';

import { Filter } from '@/ui/forms/Filter';
import { Icon } from '@clubmed/trident-icons';

export function FilterDemo() {
  return (
    <Filter checked={false}>
      <div className="flex items-center gap-x-8">
        <Icon name="Filters" />
        Category Filter
      </div>
    </Filter>
  );
}
```

## Installation

Using the CLI:

```bash
npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/filter.json
```

Or manually, copy the following code into `/ui/forms/filter.tsx`:

```tsx
import clsx from 'clsx';
import { useId, type ComponentPropsWithoutRef } from 'react';
import { Icon } from '@clubmed/trident-icons';

export interface FilterProps
  extends Omit<ComponentPropsWithoutRef<'input'>, 'size' | 'onChange' | 'value'> {
  /**
   * Is it attached to a dropdown?
   */
  hasDropdown?: boolean;
  /**
   * @deprecated use ["data-testid"] instead
   */
  dataTestId?: string;
  'data-testid'?: string;
  value?: string | number | boolean;
  onChange?: (event: Event, value: boolean) => void;
}

export function Filter(props: FilterProps) {
  const internalId = useId();

  const {
    id = internalId,
    name = id,
    className,
    dataTestId,
    disabled = false,
    'data-testid': dataTestIdProp,
    tabIndex = 0,
    hasDropdown,
    onChange,
    value,
    children,
    ...rest
  } = props;

  return (
    <div className={clsx(className, 'relative')}>
      <label data-testid={`filter-container-${id}`} className="relative">
        <input
          {...rest}
          id={id}
          name={name}
          data-testid={dataTestIdProp ?? dataTestId}
          type="checkbox"
          tabIndex={tabIndex}
          data-name="Filter"
          value={typeof value === 'boolean' ? String(value) : value}
          disabled={disabled}
          onChange={(e) => {
            onChange?.(e.nativeEvent, e.target.checked);
          }}
        />
        <span>
          <span className="font-semibold">{children}</span>

          <Icon className="check" width={null} name="CheckDefault" color="black" />

          {hasDropdown && (
            <Icon name="ArrowDefaultDown" className="ml-8" width="24px" color="black" />
          )}
        </span>
      </label>
    </div>
  );
}
```

## Usage

```tsx showLineNumbers
'use client';

import { useState } from 'react';
import { Filter } from '@/docs/lib/ui/forms/filter';

export function Component() {
  const [checked, setChecked] = useState(false);

  return (
    <Filter
      name="category"
      checked={checked}
      onChange={(_, value) => setChecked(value)}
    >
      Category Filter
    </Filter>
  );
}
```

## API Reference

### Filter

| Prop         | Type                                         | Default     | Description                                                                       |
| ------------ | -------------------------------------------- | ----------- | --------------------------------------------------------------------------------- |
| `children`   | `ReactNode`                                  | `undefined` | Label content displayed next to icons                                             |
| `hasDropdown` | `boolean`                                   | `undefined` | Displays a dropdown arrow icon when `true`                                        |
| `dataTestId` | `string`                                     | `undefined` | Deprecated alias for `data-testid`                                                |
| `data-testid` | `string`                                    | `undefined` | Test identifier forwarded to the native input                                     |
| `className`  | `string`                                     | `undefined` | Additional classes on the outer wrapper                                           |
| `onChange`   | `(event: Event, value: boolean) => void` | `undefined` | Change handler receiving browser event, checked value             |

`Filter` also supports standard HTML input attributes (`checked`, `defaultChecked`, `name`, `value`, `disabled`, etc.).

## Notes

- **Checkbox-based**: Filter is built on a native checkbox input, providing proper semantics and keyboard accessibility out of the box
- **Check icon**: When checked, displays a check icon (CheckDefault) to indicate the selected state
- **Dropdown indicator**: Set `hasDropdown={true}` to show an arrow icon, useful when the filter opens a dropdown menu
- **Normalized onChange**: Uses the shared forms contract `onChange(event, value)`
- **Composability**: Can be used directly inside `Checkboxes` for grouped selection behavior
- **Disabled state**: When disabled, prevents clicks and keyboard interactions
- **Data attributes**: Includes `data-name="Filter"` for styling and `data-testid` for testing
- **Keyboard support**: Fully keyboard accessible with configurable `tabIndex`
