Components
EmojiPicker
A search field, a row of category buttons and a scrolling grid of emoji, with a preview of the emoji under the pointer or the focus. Built in: 536 common emoji in eight categories, with English names to search. It has no frame: put it in a Popover, or use it inside MessageActions.
Preview
import { EmojiPicker } from "@/components/ui/emoji-picker"
const pickEmoji = (emoji: string) => { /* Insert the emoji where the caret is. */ }
<EmojiPicker frequent={["👍", "❤️", "😂", "🎉", "🙏", "🔥"]} onEmojiSelect={pickEmoji} className="rounded-container border border-border p-sm" />Usage
When to use
- Pick an emoji to put in a message or as a reaction.
- Let someone search a set of emoji by name.
When not to use
- Pick from a few fixed reactions. Use the quick reactions in MessageActions.
- Pick an icon for a project or a page. Use a grid of icon Buttons in a Popover.
- Rate something. Use Rating.
Examples
Picker
import { EmojiPicker } from "@/components/ui/emoji-picker"
const pickEmoji = (emoji: string) => { /* Insert the emoji where the caret is. */ }
<EmojiPicker onEmojiSelect={pickEmoji} className="rounded-container border border-border p-sm" />Frequently used
Emoji the user picks most come first, in their own section.
import { EmojiPicker } from "@/components/ui/emoji-picker"
const pickEmoji = (emoji: string) => { /* Insert the emoji where the caret is. */ }
<EmojiPicker frequent={["👍", "❤️", "😂", "🎉", "🙏", "🔥"]} onEmojiSelect={pickEmoji} className="rounded-container border border-border p-sm" />In a popover
The usual place: a button beside a field opens it.
import { IconMoodSmile } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"
import { EmojiPicker } from "@/components/ui/emoji-picker"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
const pickEmoji = (emoji: string) => { /* Insert the emoji where the caret is. */ }
<Popover>
<PopoverTrigger asChild>
<Button variant="secondary" iconOnly aria-label="Add emoji">
<IconMoodSmile size={16} />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-sm">
<EmojiPicker autoFocus onEmojiSelect={pickEmoji} />
</PopoverContent>
</Popover>Do and don't
Do
- Open it from a button in a Popover, and close the Popover when an emoji is picked.
- Pass frequent with the user's most used emoji, kept by your app.
- Pass categories with translated names when search should work in the page's language.
Don't
- Do not use it to pick reactions only; MessageActions offers quick reactions first.
- Do not shrink it below 8 columns of md buttons on touch screens.
- Do not show emoji as images of text; keep the system emoji font.
Props
| Name | Type | Values | Default | Description |
|---|---|---|---|---|
| onEmojiSelect | (emoji: string) => void | - | - | Called with the emoji the user picks, such as 👍. |
| frequent | string[] | - | - | Emoji the user picks most, shown first. Keep the list yourself, such as in local storage. |
| categories | { id: string; label: string; emojis: { emoji: string; name: string; keywords?: string[] }[] }[] | - | - | The categories to show. Default: the built-in set. The ids smileys, people, animals, food, activities, travel, objects and symbols pick a built-in icon. |
| columns | number | - | 8 | Emoji per row. |
| showPreview | boolean | - | true | Shows the emoji under the pointer or the focus, with its name, under the grid. |
| autoFocus | boolean | - | false | Focuses the search field on mount, such as when the picker opens in a Popover. |
| labels | { picker?: string; search?: string; searchPlaceholder?: string; categories?: string; frequent?: string; results?: string; empty?: string } | - | - | Names and headings. Defaults: Emoji, Search emoji, Search, Emoji categories, Frequently used, Results, No emoji found. Vietnamese: Biểu tượng cảm xúc, Tìm biểu tượng cảm xúc, Tìm kiếm, Nhóm biểu tượng, Dùng thường xuyên, Kết quả, Không tìm thấy biểu tượng nào. |
Anatomy
| Part | Description |
|---|---|
| root | The picker: search, categories, grid and preview, stacked, 288px wide. |
| search | An Input in size sm with a search icon. |
| nav | The row of category buttons, hidden while searching. |
| category | A 28px icon button that scrolls its section into view, with a 44px touch target. The section in view takes the muted accent fill. |
| viewport | The 256px scrolling area of sections. |
| section | One category: its heading over its grid. |
| heading | The category name above its emoji. |
| item | One emoji button, the size of an md control, at the xl text size. |
| empty | The text shown when nothing matches the search. |
| preview | The emoji under the pointer or the focus, with its name, under a line. |
Accessibility
Role: group
| Keys | Action |
|---|---|
| Arrow Down | From the search field, moves into the grid. |
| Arrow keys | In the grid, move by one emoji or one row. Arrow Up from the first row goes back to the search field. |
| Home / End | In the grid, move to the first or the last emoji. |
| Enter / Space | Picks the focused emoji. Enter in the search field picks the first result. |
| Tab | Moves from the search field to the category buttons, then to the grid, which is one tab stop. |
- A group named by labels.picker (EN `Emoji`, VI `Biểu tượng cảm xúc`). The search field is named by labels.search.
- Each emoji is a button named by its name, such as EN `thumbs up`, so a screen reader never reads only the glyph.
- Each section is a region named by its heading. The category buttons are named by their category and the one in view has aria-current.
- The preview under the grid is drawn only; the buttons already say their names.
- When nothing matches, the empty text is a polite status, EN `No emoji found`.
- Built-in names are English. Pass categories with names in another language to search in it.
Install
npx werewolf-ui add emoji-pickerRun npx werewolf-ui init once in your app before adding components. Init sets up tokens, their CSS import and agent rules. Add installs this component and its dependencies while preserving your theme. See Installation for requirements and the alternative registry setup.