Skip to content

Emoji Picker

<loomi-emoji-picker> is a searchable, keyboard-friendly emoji picker web component. The trigger is the emoji itself — clicking it opens a dropdown (built on @loomidev/popover) with a search box, category tabs, and a 7-per-row emoji grid. It is form-associated, so a selected emoji submits under name like a native form control.

Terminal window
npm install @loomidev/emoji-picker lit
import "@loomidev/emoji-picker";
<loomi-emoji-picker name="reaction" label="Reaction"></loomi-emoji-picker>

The built-in emoji set is a compact curated list, not the full operating-system emoji keyboard. Assign .data with your own larger set when your product needs a different selection, or newer platform-specific symbols the built-in set doesn’t have yet. Each item accepts emoji, name or label, value, category, and keywords — custom items don’t get the skin-tone picker described below, since they carry no tone variants of their own.

const picker = document.querySelector("loomi-emoji-picker");
picker.data = [
{ emoji: "🟢", name: "Green status", value: "green", category: "status" },
{ emoji: "🔴", name: "Red status", value: "red", category: "status" },
];
<loomi-emoji-picker emojis="😀, 😎, 🚀, ❤️"></loomi-emoji-picker>

Clicking the trigger opens a dropdown containing a search box, a row of category tabs, and a grid of emoji (7 per row). Set searchable="false" or show-categories="false" to drop either piece; inline renders the same body permanently in place of a trigger, with no dropdown at all.

<loomi-emoji-picker searchable="false" show-categories="false"></loomi-emoji-picker>
<loomi-emoji-picker inline></loomi-emoji-picker>

When the active emoji set includes emoji that support skin tones (true of the built-in curated set), a hand emoji sits as a suffix on the search input. Clicking it opens a 6-way tone menu (default plus the 5 Fitzpatrick tones); the chosen tone applies to every emoji in the grid that has tone variants — and to selected-value/the submitted form value once one is picked. The choice is remembered in localStorage for the next time the picker opens.

Emoji supplied through .data or emojis don’t carry tone variants, so the hand suffix is omitted when the picker is showing only custom data.

By default the trigger shows only the selected emoji (or a placeholder face) — nothing else. Set show-text to also show the name/placeholder text next to it, useful when the picker needs to read clearly as a labeled field rather than a compact icon button.

<loomi-emoji-picker show-text selected-value="🚀"></loomi-emoji-picker>

Unlike most boolean HTML attributes, show-text (along with show-categories and searchable) understands the literal string "false", so turning it back off in markup works as expected too:

<loomi-emoji-picker show-text="false"></loomi-emoji-picker>

For the library-wide baseline, see Foundations — Accessibility.

For the shared container and viewport rules, see Foundations — Responsive behavior.

For theme activation, token overrides, and contrast guidance, see Foundations — Dark mode.

NameDefaultDescription
name""Form field name.
selected-value""Current submitted value. Defaults to the emoji itself.
label""Optional field label.
placeholderPick an emojiClosed trigger placeholder.
inlinefalseRender the panel directly instead of a trigger dropdown.
searchabletrueShow the search input.
show-categoriestrueShow category tabs.
show-textfalseShow the selected emoji’s name (or placeholder) next to the trigger emoji.
requiredfalseMark the picker invalid until a value is selected.
disabledfalseDisable the trigger.
readonlyfalsePrevent changes while keeping the current value readable.
sizemediumsmall, regular, medium, or big.

change fires with detail: { value, emoji, item } after selection.

loomi-emoji-select fires with detail: { value, emoji, name, category, item }.

MethodDescription
reset()Clears the selected value.
validate()Shows validation and returns whether the picker is valid.
checkValidity()Mirrors native form validity.
reportValidity()Shows the browser validation UI where supported.
  • @loomidev/core
  • @loomidev/popover