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

# EmojiText

A message's text with its emoji drawn from an image catalogue: each token (`:party:`, an emoji's first shortcode or else its id, as `EmojiPicker` and `Autocomplete` put into a `Composer`) and each emoji's `text` the catalogue lists becomes the emoji's image, which screen readers hear by name. A token the catalogue does not know stays as typed. `enlarge` shows a message of only emoji large.

```tsx
import { EmojiText } from "@/components/ouro/emoji/emoji";
```

## Example

```tsx
<Message author={author} time={sentAt}>
  <EmojiText text={message.body} catalogue={catalogue} enlarge />
</Message>
```

## Use instead when

- Use `Emoji` instead for a single emoji outside text, and plain text for an app that uses the platform's emoji font.

## Props

Type: `EmojiTextProps`.

| Prop | Type | Description |
| --- | --- | --- |
| `catalogue` (required) | `EmojiCatalogue` | The emoji to draw, which the app supplies. |
| `className` | `string` | Layout only: margins, width (`mt-1`). Appearance classes warn in development. |
| `enlarge` | `boolean` | Draws emoji that stand alone, up to three with nothing else but spaces, at more than twice the size, as chat apps show a message of only emoji. |
| `ref` | `Ref<HTMLSpanElement>` | The `<span>`. |
| `text` (required) | `string` | The text, with emoji as tokens (`:party:`, `:thumbs-up-tone3:`) or as the text the catalogue lists (`"🎉"`). |

## 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.

- `children`: Not a prop. The text goes in `text`, so EmojiText can find its emoji: `<EmojiText text={message.body} catalogue={catalogue} />`.

## `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: EmojiText 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

### `EmojiCatalogue`

An image-based emoji set, by category: what `EmojiPicker`, `ReactionBar`, `Autocomplete` and `EmojiText` draw instead of the platform's emoji font when an app passes it. Put an organization's custom emoji in a category of their own, labelled by the app. The image addresses are used as they are, so an app that loads images its own way (a content security policy, a custom scheme, signed or `blob:` URLs) puts the addresses it can load in the catalogue when it builds it. Ouro indexes a catalogue's emoji once, to find them in text. Build the catalogue once and pass that object, or give each copy the same `id`: a catalogue of new emoji objects on every render is indexed again each time, and warns in development. Adding or removing emoji is seen in a new catalogue object, even in the same array; to edit an emoji's shortcodes or text, pass a new emoji object, or a new `id`.

```ts
interface EmojiCatalogue {
  /**
   * Names this set of emoji, for an app that makes a new catalogue object, emoji and all, each
   * time it draws: catalogues with the same id share one index of their emoji, so change it when
   * the emoji change (`"contoso-2026-11"`), an emoji edited in place included. Without one, a
   * new catalogue object shares the index when it holds the same emoji objects in the same order,
   * and a catalogue of new emoji objects builds its own.
   */
  id?: string | undefined;
  /** The categories, in the order they show. An emoji in more than one counts once, by its id. */
  categories: readonly EmojiCatalogueCategory[];
}
```

### `EmojiCatalogueCategory`

A category of a catalogue: its name, the icon its button shows, and its emoji in order.

```ts
interface EmojiCatalogueCategory {
  /** Identifies the category, unique in the catalogue: `"people"`, `"custom"`. */
  id: string;
  /** Its name, shown as its heading and read for its button: `"People"`, or the organization's name for its custom emoji. */
  label: string;
  /** What its button in a picker's category bar shows: an icon element. Defaults to its first emoji's image. */
  icon?: ReactNode;
  /** Its emoji, in the order they show. */
  items: readonly EmojiItem[];
}
```

### `EmojiFilmstrip`

An animation drawn as a filmstrip: square frames stacked top to bottom in one image, so the frames are the image's height over its width.

```ts
interface EmojiFilmstrip {
  /** The filmstrip image's address. */
  src: string;
  /** Frames a second. */
  fps: number;
}
```

### `EmojiItem`

One emoji in an image catalogue: its id, its name and the image that draws it. An app maps its own emoji set to this, whether a standard set or an organization's custom emoji.

```ts
interface EmojiItem {
  /** Identifies the emoji, unique in the catalogue: `"party"`. Reactions, recents and `:id:` tokens use it. */
  id: string;
  /** Its name, which is the image's `alt`, what screen readers hear and what the search matches first: `"Party popper"`. */
  name: string;
  /**
   * The still image's address. It shows whenever the emoji is not playing, and always with reduced motion.
   */
  src: string;
  /** Sizes of the still image for sharper screens, as `<img srcset>`: `"party-2x.png 2x"`. */
  srcSet?: string | undefined;
  /**
   * An animated image (GIF, animated WebP or PNG), which plays while the pointer is on the emoji
   * or on the button around it, or that button has focus. With reduced motion it never plays.
   */
  animatedSrc?: string | undefined;
  /**
   * The animation as a filmstrip, square frames stacked top to bottom in one image, for an
   * emoji without `animatedSrc`: while the emoji plays, it steps through the frames at `fps`;
   * otherwise, and always with reduced motion, `src` shows.
   */
  filmstrip?: EmojiFilmstrip | undefined;
  /** The still image's width in pixels, given to the `<img>` so the page keeps its shape while it loads. It shows at the text's size. */
  width?: number | undefined;
  /** The still image's height in pixels, as `width`. */
  height?: number | undefined;
  /** Short names typed between colons, without them: `["party", "tada"]`. The first makes the emoji's token, `:party:`. */
  shortcodes?: readonly string[] | undefined;
  /** More words the search matches: `["celebrate", "hooray"]`. */
  keywords?: readonly string[] | undefined;
  /**
   * The emoji as plain text, such as its Unicode character (`"🎉"`), for places an image cannot
   * go (a copied message, a notification). `EmojiText` finds it in messages and draws the image;
   * Ouro never draws it as text.
   */
  text?: string | undefined;
  /** It is the organization's or app's own emoji rather than one of the standard set. Ouro draws it the same; apps can label or treat it apart. */
  custom?: boolean | undefined;
  /**
   * The emoji in Unicode's five skin tones, light to dark; leave it out for an emoji without tones.
   */
  skinTones?: readonly EmojiItemTone[] | undefined;
}
```

### `EmojiItemTone`

An emoji's image in one skin tone: `skinTones` on an `EmojiItem`.

```ts
interface EmojiItemTone {
  /** Identifies the emoji in this tone, unique in the catalogue: `"thumbs-up-tone3"`. Reactions and tokens use it. */
  id: string;
  /** The still image's address. */
  src: string;
  /** Sizes of the still image for sharper screens, as `<img srcset>`: `"wave-2x.png 2x"`. */
  srcSet?: string | undefined;
  /** An animated image (GIF, animated WebP or PNG), shown while the emoji plays; the still one shows otherwise. */
  animatedSrc?: string | undefined;
  /** The animation as a filmstrip of square frames, played while the emoji plays, for a tone without `animatedSrc`. */
  filmstrip?: EmojiFilmstrip | undefined;
  /**
   * The emoji in this tone as text (`"👍🏽"`), which `EmojiText` finds in messages; Ouro never draws it as text.
   */
  text?: string | undefined;
}
```

[^layout-classes]: test:registry/ouro/components/ouro/emoji/emoji.test.tsx::Emoji > passes the img attributes and ref through, and lets app layout classes win verify:testExists(registry/ouro/components/ouro/emoji/emoji.test.tsx::Emoji > passes the img attributes and ref through, and lets app layout classes win)
