# Pixel reactions
> Pixel like button whose heart explodes and snaps back filled; press and hold opens four more reactions that the same pixels fly into.
- Element: `<px-react>`
- React: `import { PxReact } from "@/components/lumesec/px-react"`
- Collection: Pixel Lab (https://elements.lumesec.ai/components/pixel-lab)
- Registry item: https://elements.lumesec.ai/r/px-react.json
- Page: https://elements.lumesec.ai/components/pixel-lab/react



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

```html
<script type="module" src="https://elements.lumesec.ai/cdn/px-react.js"></script>

<px-react count="128"></px-react>
```

## Playground

Change a prop and the component updates. Props marked live animate to the new value; the others rebuild the element.

## Installation

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

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-react.json
```

## Usage

React:

```tsx
import { PxReact } from "@/components/lumesec/px-react";

export function Example() {
  return (
    <PxReact count={128} />
  );
}
```

HTML:

```html
<script type="module" src="https://elements.lumesec.ai/cdn/px-react.js"></script>

<px-react count="128"></px-react>
```

## Behaviour

The heart’s pixels explode outward and snap back filled. Unliking drains it row by row to an outline. Press and hold for four more reactions; picking one sends the same pixels flying into its shape.

## API reference

### Attributes

| Attribute | React prop | Type     | Default | Description                                          |
| --------- | ---------- | -------- | ------- | ---------------------------------------------------- |
| `count`   | `count`    | `number` | `128`   | Starting reaction count. Read once on first connect. |

### Events

Events bubble and cross the shadow boundary unless the description says otherwise.

| Event   | React prop | Detail                                 | Description                                                                                                  |
| ------- | ---------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `react` | `onReact`  | `{ liked: boolean, reaction: string }` | Fires on like, unlike and when a reaction is picked. `reaction` is `Love`, `Star`, `Zap`, `Fire` or `Spark`. |

### Methods

Call them on the element, for example through a React ref.

| Method                | Description                                                                                                     |
| --------------------- | --------------------------------------------------------------------------------------------------------------- |
| `toggle()`            | Likes or unlikes with the current reaction and adjusts the count by one.                                        |
| `pick(index: number)` | Selects reaction 0 to 4 (`Love`, `Star`, `Zap`, `Fire`, `Spark`), marks it liked and moves focus to the button. |

## Keyboard

| Keys                                    | Action                                                    |
| --------------------------------------- | --------------------------------------------------------- |
| ArrowUp (on the button)                 | Open the reaction palette and focus the current reaction. |
| ArrowLeft / ArrowRight (in the palette) | Move focus between reactions, wrapping around.            |
| Escape (in the palette)                 | Close the palette and return focus to the button.         |

## Accessibility

* The main control is a native button with `aria-pressed` for the liked state and `aria-label="Like. Press and hold for more reactions"`; after a pick the label starts with the reaction name.
* The palette has `role="menu"`; each reaction is a button with `role="menuitem"` and an `aria-label`.
* The count is plain text without a live region.
* Reduced motion: pixels move straight to their new shape without exploding, the palette opens without its pop-in and the spark bursts are skipped.

## Theming

The element reads your shadcn theme tokens through its shadow root, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

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

To restyle only LumeSec elements, set the matching `--ui-*` overrides: `--ui-accent`, `--ui-border`, `--ui-danger`, `--ui-fg`, `--ui-muted`, `--ui-raised`, `--ui-shine`, `--ui-surface` and `--ui-warn`.

## Notes

* A press held for 430 ms opens the palette instead of toggling. Pressing anywhere else in the component closes it.
* The button is a fixed 76 by 76px; the palette opens above it.


