# Tag input
> Tag input where Enter or comma adds a chip and Backspace twice removes the last; duplicates shake and removed tags break into pixels.
- React: `import { PxTags } from "@/components/lumesec/px-tags"`
- Collection: Pixel UI (https://elements.lumesec.ai/components/pixel-ui)
- Registry item: https://elements.lumesec.ai/r/px-tags.json
- Page: https://elements.lumesec.ai/components/pixel-ui/tags



Live preview: https://elements.lumesec.ai/view/px-tags

Demo source:

```tsx
import { PxTags } from "@/components/lumesec/px-tags";

export default function PxTagsDemo() {
  return (
    <div className="w-full max-w-[400px] rounded-[14px] border border-border bg-card px-5 py-[18px] shadow-[0_14px_34px_-20px_rgb(0_0_0/0.4)]">
      <PxTags
        name="topics"
        label="Topics"
        defaultValue={["design", "pixels"]}
        suggestions={["motion", "accessibility", "forms"]}
        max={6}
      />
    </div>
  );
}
```

## Playground

Change a prop and the component re-renders. Props marked remounts set an initial value, so the component starts over.

## Installation

```bash
npx shadcn@latest add @lumesec/px-tags
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/px-tags.json
```

## Usage

React:

```tsx
import { PxTags } from "@/components/lumesec/px-tags";

export function Example() {
  return (
    <PxTags
      name="topics"
      label="Topics"
      defaultValue={["design", "pixels"]}
      suggestions={["motion", "accessibility", "forms"]}
      max={6}
    />
  );
}
```

## Behaviour

Enter or comma adds a tag, Backspace on an empty field marks the last one and a second press removes it. Removed tags break into pixels; duplicates shake instead of being added.

## API reference

### Props

Also accepts every prop of `<div>` (`React.ComponentProps<"div">`), spread onto the root element.

| Prop            | Type                        | Default                       | Description                                                                                                                 |
| --------------- | --------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `value`         | `readonly string[]`         | —                             | Controlled tags. Use with `onValueChange`.                                                                                  |
| `defaultValue`  | `readonly string[]`         | `[]`                          | Initial tags when uncontrolled.                                                                                             |
| `label`         | `React.ReactNode`           | `"Tags"`                      | Label above the field, linked to the input.                                                                                 |
| `placeholder`   | `string`                    | `"Add a tag and press Enter"` | Placeholder of the input.                                                                                                   |
| `suggestions`   | `readonly string[]`         | `[]`                          | Shown as "+ name" buttons under the field; clicking one adds it.                                                            |
| `max`           | `number`                    | `8`                           | Maximum number of tags. Adding beyond it shakes the field and shows a message.                                              |
| `name`          | `string`                    | —                             | Form field name; the tags submit joined with commas.                                                                        |
| `disabled`      | `boolean`                   | `false`                       | Dims the field and disables the input, the remove buttons and the suggestion buttons.                                       |
| `onValueChange` | `(value: string[]) => void` | —                             | Called when tags are added (Enter, comma, a suggestion or a paste) or removed. A paste that adds several tags reports once. |

### Ref

`ref` points at the root `HTMLDivElement`.

## Keyboard

| Keys                    | Action                                                     |
| ----------------------- | ---------------------------------------------------------- |
| Enter / ,               | Add the typed text as a tag.                               |
| Backspace (empty field) | First press marks the last tag; a second press removes it. |
| Any other key           | Clears the mark.                                           |

## Accessibility

* A native `<input>` labelled by a `<label htmlFor>`.
* Each chip's remove button has an `aria-label` of "Remove" followed by the tag.
* The counter ("2 of 6 tags") and the limit message are in an `aria-live="polite"` region.
* Chips are plain elements without a list role. Removing one returns focus to the input. The pixel canvas is `aria-hidden`.
* With `name`, a hidden input submits the tags joined with commas. There is no validity check; `max` is enforced by refusing new tags. Form reset removes all tags (it does not restore `defaultValue`), clears the typed text and calls `onValueChange`.
* Reduced motion: chips appear without scaling in or a pixel spray, removed chips vanish without breaking into pixels and the duplicate and limit shakes are skipped.

## Theming

Styled with Tailwind classes on your shadcn theme tokens, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--foreground`, `--muted-foreground`, `--card`, `--border`, `--muted`, `--lumesec`, `--lumesec-shine` and `--destructive`.

## Notes

* Tags are trimmed and inner whitespace is collapsed; case-insensitive duplicates are refused.
* Pasting text that contains commas adds each part as a tag.
* A long tag is truncated with an ellipsis inside its chip.


