<!-- Generated by scripts/gen-docs.mts from the JSDoc in registry/. Do not edit; run `pnpm run docs`. -->

# ReactionBar

A message's reactions: each one's emoji and how many chose it, with the person's own pressed and tinted, and quick reactions to add with a single press. Pressing a reaction calls `onReact` with its key, so the app adds the person's reaction or takes it back. Each reaction is a toggle button (`aria-pressed`) that screen readers hear by name and count ("Like, 3"). Without `onReact` the reactions are read-only, and with nothing to show it renders nothing.

```tsx
import { ReactionBar } from "@/components/ouro/reaction-bar/reaction-bar";
```

## Example

```tsx
<ReactionBar reactions={message.reactions} quick={quickReactions} onReact={(key) => toggleReaction(message.id, key)} />
```

## Usage

Place it in `Message`'s `attachments`.

## Use instead when

- Use `ToggleGroup` instead for a choice between options, and `Badge` for a single count.

## Props

Type: `ReactionBarProps`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string` |  | Layout only: margins, placement (`mt-1`). Appearance classes warn in development. |
| `disabled` | `boolean` |  | Keeps the counts but turns off reacting, for example while the app is offline. |
| `label` | `string` | `"Reactions"` | What screen readers hear for the group, for other languages. |
| `mineLabel` | `string` | `"including you"` | What screen readers hear after a read-only reaction that is the person's own. |
| `onReact` | `((key: string, event: MouseEvent<HTMLElement>) => void)` |  | Called with a reaction's key when it is pressed, to add the person's reaction or take it back. The click event comes second, so the app can check `event.isTrusted` before it acts. Without it the reactions are read-only. |
| `quick` | `readonly ReactionOption[]` |  | Reactions offered for a single press, after the counts. One that is already in `reactions` shows there instead. Shown only with `onReact`. |
| `reactions` (required) | `readonly Reaction[]` |  | The message's reactions, in the order they show. |
| `ref` | `Ref<HTMLDivElement>` |  | Reaches the rendered element. |

## Native attributes

Also accepts the attributes in React's `HTMLAttributes` (`id`, `aria-*`, event handlers), passed to the rendered element, except those named on this page.

## Don't use

These are not props. Passing one fails the type check with the fix in the error, and in development a console message names the fix.

- `items`: Not a prop. The reactions are `reactions`: `<ReactionBar reactions={message.reactions}>`.
- `onReactionClick`: Not a prop. A pressed reaction calls `onReact`: `<ReactionBar onReact={(key) => react(key)}>`.

## `className` is for layout only

Pass margins, width and grid placement (`mt-4`, `w-full`, `col-span-2`). Your classes always win over Ouro UI's: ReactionBar merges `className` last with `cn` (tailwind-merge), so a class that conflicts with its own replaces it.[^layout-classes]

Appearance comes from props, not classes. In development, a class that sets appearance logs one warning per component instance, naming the prop to use instead. A class sets appearance when, after its variants (`hover:`, `sm:`) and any `!` are removed, it starts with `bg-`, `text-`, `border-`, `rounded-`, `shadow-`, `font-`, `ring-`, `from-`, `via-`, `to-`, `fill-` or `stroke-`, or is `border`, `rounded`, `shadow` or `ring`, or has a `dark:` variant. Text wrapping, overflow and table layout classes (`text-wrap`, `text-ellipsis`, `border-collapse`) are layout and do not warn.

Alignment classes (`text-center`) warn too: set alignment on a parent element.

## Types

### `Reaction`

A reaction on a message, with how many people chose it.

```ts
interface Reaction extends ReactionOption {
  /** How many people reacted this way. */
  count: number;
  /** The person using the app is one of them: the reaction is pressed and tinted. */
  mine?: boolean | undefined;
}
```

### `ReactionOption`

A reaction someone can add: its key, its spoken name and what it shows.

```ts
interface ReactionOption {
  /** Identifies the reaction ("like"); `onReact` receives it. */
  key: string;
  /** What screen readers hear for it ("Like"). */
  label: string;
  /** What it shows: an emoji ("👍") or an icon element. Screen readers hear `label` instead. */
  emoji: ReactNode;
}
```

[^layout-classes]: test:registry/ouro/components/ouro/reaction-bar/reaction-bar.test.tsx::ReactionBar > forwards a ref and lets app layout classes win verify:testExists(registry/ouro/components/ouro/reaction-bar/reaction-bar.test.tsx::ReactionBar > forwards a ref and lets app layout classes win)
