---
title: "Emoji Menu"
description: "Interactive emoji picker menu with search functionality for Tiptap editors. More in the docs."
canonical_url: "https://tiptap.dev/docs/ui-components/components/emoji-menu"
---

# Emoji Menu

Interactive emoji picker menu with search functionality for Tiptap editors. More in the docs.

A fully accessible emoji picker menu for Tiptap editors. Browse and search through emojis with keyboard navigation support, fallback images, and customizable filtering options.

> **Interactive demo:** [emoji menu](https://template.tiptap.dev/preview/tiptap-ui/emoji-menu)

## Installation

Add the component via the Tiptap CLI:

```bash
npx @tiptap/cli@latest add emoji-menu
```

## Components

### `<EmojiMenu />`

A comprehensive emoji picker menu with search and navigation capabilities.

#### Usage

```tsx
import { EmojiMenu } from '@/components/tiptap-ui/emoji-menu'
import { gitHubEmojis } from '@tiptap/extension-emoji'
import type { EmojiItem } from '@tiptap/extension-emoji'

export default function MyEmojiPicker() {
  const [selectedEmoji, setSelectedEmoji] = useState<EmojiItem | null>(null)

  const handleEmojiSelect = (emoji: EmojiItem) => {
    setSelectedEmoji(emoji)
    console.log('Selected emoji:', emoji.name, emoji.emoji)
  }

  const handleClose = () => {
    console.log('Emoji menu closed')
  }

  return (
    <EmojiMenu
      emojis={gitHubEmojis}
      onSelect={handleEmojiSelect}
      onClose={handleClose}
      showSearch={true}
      selector=".my-emoji-menu"
    />
  )
}
```

#### Props

| Name         | Type                    | Default              | Description                                    |
| ------------ | ----------------------- | -------------------- | ---------------------------------------------- |
| `emojis`     | `T[] extends EmojiItem` | `undefined`          | Array of emoji items to display                |
| `onSelect`   | `(emoji: T) => void`    | `undefined`          | Callback fired when an emoji is selected       |
| `onClose`    | `() => void`            | `undefined`          | Callback fired when the menu is closed         |
| `showSearch` | `boolean`               | `false`              | Whether to show the search input               |
| `selector`   | `string`                | `".emoji-menu-list"` | CSS selector for the scrollable menu container |

### `<EmojiMenuItem />`

Individual emoji item component used within the emoji menu.

#### Usage

```tsx
import { EmojiMenuItem } from '@/components/tiptap-ui/emoji-menu'
import type { EmojiItem } from '@tiptap/extension-emoji'

function CustomEmojiList({ emojis, onSelect, selectedIndex }) {
  return (
    <div>
      {emojis.map((emoji, index) => (
        <EmojiMenuItem
          key={emoji.name}
          emoji={emoji}
          index={index}
          isSelected={index === selectedIndex}
          onSelect={onSelect}
          selector=".custom-emoji-list"
        />
      ))}
    </div>
  )
}
```

#### Props

| Name         | Type                  | Default     | Description                                   |
| ------------ | --------------------- | ----------- | --------------------------------------------- |
| `emoji`      | `T extends EmojiItem` | `undefined` | The emoji item to render                      |
| `index`      | `number`              | `undefined` | The index of the emoji in the list            |
| `isSelected` | `boolean`             | `undefined` | Whether this emoji item is currently selected |
| `onSelect`   | `(emoji: T) => void`  | `undefined` | Callback fired when this emoji is selected    |
| `selector`   | `string`              | `undefined` | CSS selector for scroll container             |

## Utilities

### `getFilteredEmojis(props)`

Filters and sorts emoji data based on search query.

```tsx
import { getFilteredEmojis } from '@/components/tiptap-ui/emoji-menu'
import { gitHubEmojis } from '@tiptap/extension-emoji'

const filteredEmojis = getFilteredEmojis({
  query: 'smile',
  emojis: gitHubEmojis,
})

console.log('Filtered emojis:', filteredEmojis.length)
```

#### Parameters

| Name           | Type                    | Description                      |
| -------------- | ----------------------- | -------------------------------- |
| `props.query`  | `string`                | Search query to filter emojis by |
| `props.emojis` | `T[] extends EmojiItem` | Array of emoji items to filter   |

#### Returns

`T[]` - Filtered and sorted array of emoji items (max 100 results).

### `searchEmojiData(query, emojiData)`

Checks if an emoji matches the search query.

```tsx
import { searchEmojiData } from '@/components/tiptap-ui/emoji-menu'

const emoji = {
  name: 'grinning',
  shortcodes: ['grinning', 'grinning_face'],
  tags: ['face', 'smile'],
  emoji: '😀',
}

const matches = searchEmojiData('smile', emoji) // true
```

#### Parameters

| Name        | Type                  | Description                      |
| ----------- | --------------------- | -------------------------------- |
| `query`     | `string`              | Search query string              |
| `emojiData` | `T extends EmojiItem` | Emoji item to test against query |

#### Returns

`boolean` - Whether the emoji matches the search query.

## Search Functionality

The emoji menu supports intelligent search across multiple emoji properties:

### Search Fields

- **Name**: Primary emoji name (e.g., "grinning")
- **Shortcodes**: Alternative names (e.g., "grinning\_face")
- **Tags**: Descriptive tags (e.g., "face", "smile")

### Search Features

- **Case-insensitive**: Search works regardless of capitalization
- **Partial matching**: Finds emojis containing the search term
- **Multi-field search**: Searches across name, shortcodes, and tags
- **Result limiting**: Returns maximum 100 results for performance
- **Alphabetical sorting**: Results are sorted by emoji name

### Example Search Queries

```tsx
// Search by name
getFilteredEmojis({ query: 'heart', emojis }) // ❤️, 💖, 💕, etc.

// Search by tag
getFilteredEmojis({ query: 'face', emojis }) // 😀, 😃, 😄, etc.

// Search by shortcode
getFilteredEmojis({ query: 'grinning', emojis }) // 😀, 😃, etc.

// Empty query returns first 100 emojis
getFilteredEmojis({ query: '', emojis }) // First 100 emojis
```

## Keyboard Navigation

The emoji menu includes full keyboard navigation support:

- **Arrow Keys**: Navigate up/down through emoji list
- **Enter**: Select the currently highlighted emoji
- **Escape**: Close the menu
- **Type to Search**: Automatically focus search input and filter

Navigation is provided by the `useMenuNavigation` hook and includes:

- **Smart Scrolling**: Automatically scrolls selected item into view
- **Overflow Handling**: Prevents scrolling beyond menu boundaries
- **Focus Management**: Maintains focus states during navigation

### Custom Emoji Data

```tsx
const customEmojis = [
  {
    emoji: '🎉',
    name: 'party',
    shortcodes: ['party', 'celebration'],
    tags: ['celebrate', 'fun'],
    group: 'activities',
    emoticons: [],
    version: 1,
    fallbackImage: 'https://example.com/party-emoji.png',
  },
  // ... more custom emojis
]

function CustomEmojiPicker() {
  return (
    <EmojiMenu
      emojis={customEmojis}
      onSelect={(emoji) => console.log('Custom emoji:', emoji)}
      showSearch={true}
    />
  )
}
```

## Emoji Item Interface

The `EmojiItem` interface from `@tiptap/extension-emoji`:

```tsx
interface EmojiItem {
  emoji: string // The actual emoji character: "😀"
  name: string // Primary name: "grinning"
  shortcodes: string[] // Alternative names: ["grinning", "grinning_face"]
  tags: string[] // Descriptive tags: ["face", "smile"]
  group: string // Category group: "smileys-emotion"
  emoticons: string[] // Text representations: [":D"]
  version: number // Unicode version: 1.0
  fallbackImage?: string // Optional fallback image URL
}
```

## Requirements

### Dependencies

- `@tiptap/react` - Core Tiptap React integration
- `@tiptap/extension-emoji` - Emoji extension and types

### Optional Dependencies

- `sass` - For SCSS styling support
- `sass-embedded` - Enhanced Sass processing

### Referenced Components

- `use-menu-navigation` (hook)
- `button`, `button-group` (primitive)
- `input` (primitive)
- `card`, `card-body`, `card-header` (primitive)
- `tiptap-collab-utils` (lib)
