Emoji Picker
The full modern emoji set (~1,900 base emoji, Unicode 16.0) with category tabs, fuzzy search, recents, and a stickers tab. One shared dataset in @refraction-ui/emoji-picker backs the picker, the composer's : trigger, and rich-editor shortcodes — they never diverge.
Examples
Browse categories or search, and click an emoji to select it. Category switches, hover, and press are animated (reduced-motion aware).
Uniform rendering (the render seam)
Native emoji look different on every OS. By default the picker renders uniform Twemoji SVGs (lazily loaded, one small file per glyph) so everyone sees the same set — WhatsApp's approach. Rendering flows through a single emojiRenderer seam (codepoint → ReactNode), so you can swap to native glyphs, a self-hosted mirror, or another set (Noto/Fluent/Lottie) with one prop — the data and the picker are untouched.
import { EmojiPicker, nativeEmojiRenderer } from '@refraction-ui/react-emoji-picker'
// Swap the uniform Twemoji default for OS-native glyphs — data + picker unchanged.
<EmojiPicker emojiRenderer={nativeEmojiRenderer} />
// Or self-host the uniform assets (no public CDN):
<EmojiPicker twemojiBaseUrl="/emoji" />Attribution: Twemoji graphics are © Twitter and the Twemoji contributors, licensed CC-BY 4.0. Apps shipping the default Twemoji renderer must preserve this attribution.
Stickers
The ⭐ tab renders stickerSets. A small bundled starter pack ships by default (one sticker self-animates via SMIL to prove the animated path); host or future packs plug in through the same prop, and the stickerRenderer seam supports svg, image (static or animated WebP), and lottie (supply a player). Pass stickerSets={[]} to hide the tab.
Open the ⭐ tab. The starter pack ships bundled; the pulsing heart proves the animated (SMIL) render path. Host packs plug in via the stickerSets prop.
Installation
pnpm add @refraction-ui/react-emoji-pickerUsage
import { EmojiPicker } from '@refraction-ui/react-emoji-picker'
export function MyComponent() {
// Uniform Twemoji glyphs by default; onSelect gives the full entry.
return <EmojiPicker onSelect={(e) => console.log(e.emoji, e.shortcode)} />
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
onSelect | (emoji: EmojiEntry) => void | -- | Called with the selected emoji entry (glyph, name, category, keywords, shortcode). |
onStickerSelect | (sticker: StickerItem) => void | -- | Called with the selected sticker. |
recentEmojis | EmojiEntry[] | -- | Initial recents, most-recent-first. |
emojiRenderer | (emoji: EmojiEntry) => ReactNode | twemojiRenderer | Render seam. Default paints uniform Twemoji SVGs; pass nativeEmojiRenderer (or your own) to swap. |
twemojiBaseUrl | string | -- | Base URL for Twemoji assets — point at a self-hosted mirror to avoid the public CDN. |
stickerSets | StickerSet[] | [STARTER_STICKER_SET] | Sticker sets for the ⭐ tab. Pass [] to hide the tab; pass host/third-party packs to extend it. |
stickerRenderer | (sticker: StickerItem) => ReactNode | defaultStickerRenderer | Sticker render seam (svg / image / lottie). Supply a Lottie player here for animated Lottie stickers. |
className | string | -- | Additional CSS classes. |