Emoji Picker

A complete picker: searchable, with a scroll-spy category nav, a pinned frequently-used row, persisted recents and a hovered preview. Categories mount lazily, so a large set never paints at once.

Frequently used
Smileys & Emotion
People & Body
Animals & Nature
Pick an emoji

Last picked: 👋

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Add this component (its dependencies come along)npx koalaui-cli@latest add emoji-picker

Usage#

usage.tsxTSX
import { EmojiPicker } from "@/components/ui/emoji-picker"export function Example() {  return <EmojiPicker onEmojiSelect={(char, datum) => console.log(char, datum.name)} />}

In a popover#

The most common flow: a trigger opens the picker in a Radix popover that closes on select. Compose EmojiPickerPopover, EmojiPickerTrigger (use asChild to keep your own button), and EmojiPickerContent.

Recents & presets#

The picker tracks a recently used row automatically and persists it to localStorage (set storageKey, or pass null to disable). For full control, drive recent / onRecentChange yourself. The presets row is a fixed quick-pick list pinned above the categories; override it with the presets prop.

recents-presets.tsxTSX
<EmojiPicker  presets={["👍", "❤️", "😂", "🎉", "🚀"]}  recent={recent}  onRecentChange={setRecent}  recentLimit={16}/>

Density#

Density retunes the panel width, viewport height, grid gap, and glyph size, never color or radius. comfortable is the marketing default; compact tightens it for application UI. It also resolves from a surrounding DensityProvider.

comfortable
Frequently used
Smileys & Emotion
People & Body
Animals & Nature
Pick an emoji
compact
Frequently used
Smileys & Emotion
People & Body
Animals & Nature
Pick an emoji

Minimal#

Every region is toggleable. Drop the preview footer and the recents/presets rows with showPreview, showRecent, and showPresets for a lean search-and-grid.

Smileys & Emotion
People & Body
Animals & Nature

Performance#

Categories mount in batches. Only categoriesPerPage are in the DOM at first, and a bottom sentinel reveals the next batch as you scroll (search results stream the same way). Counts only ever grow, so scroll height never jitters. Lower the value for a lighter first paint, or pass your own fuller dataset via data without changing the component.

performance.tsxTSX
// Mount two categories per scroll batch instead of three.<EmojiPicker categoriesPerPage={2} data={myFullUnicodeSet} />

FAQ#

Render the bare `EmojiPicker` when the panel lives permanently in the layout, for example a sidebar or a reaction tray. Use `EmojiPickerPopover` with `EmojiPickerTrigger` and `EmojiPickerContent` for the common click-a-button-then-pick flow, since the content closes the popover on select by default.