Skip to article
Integrations / Web component

Web component

<emojisense-picker> for Vue, Svelte, Angular and plain HTML.

On this page

<emojisense-picker> is a complete emoji picker as a custom element. It works without a framework and inside Vue, Svelte and Angular. With an empty query it shows every emoji by category. While someone types, it shows the ranked results.

Install

npm install @emojisense/web-component

Without a bundler, load the self-contained build, dist/emojisense-picker.js (about 10 KB compressed, search engine included):

HTML
<script type="module" src="/vendor/emojisense-picker.js"></script>

Use

HTML
<emojisense-picker
  pack-url="https://api.emojisense.com/v1/pack/0.1.0"
  shards-url="https://api.emojisense.com/p/0.1.0"
  endpoint="https://api.emojisense.com"
  key="pk_live_…"
  locale="en"
  columns="9"
  skin-tone="none"
  emoji-set="native"
></emojisense-picker>

<script type="module">
  import "@emojisense/web-component"; // registers <emojisense-picker>

  const picker = document.querySelector("emojisense-picker");
  picker.addEventListener("emoji-select", (event) => {
    const { emoji, label, id } = event.detail; // "👍🏽", "thumbs up", "1F44D"
  });
</script>
AttributePropertyDefaultMeaning
pack-urlpackUrl—Pack version directory. The core pack renders first, the extension pack loads when idle.
shards-urlshardsUrl—Precomputed results (layer 2), asked before the API.
endpointendpoint—The API (layer 3). Omit it and shards-url for fully offline search.
key, publishable-keypublishableKey—Publishable key. Use publishable-key in Vue and React, which reserve key.
localelocaleenAnother locale loads that pack next to English.
columnscolumns9Emoji per row (1–24)
skin-toneskinTonenonenone, light, medium-light, medium, medium-dark, dark
emoji-setemojiSetnativenative draws the system font. twemoji, noto and fluent draw images of a hosted set and need endpoint.
placeholderplaceholderSearch emoji…Input placeholder and accessible name
custom-emojicustomEmojioffLoad the key’s custom emoji from endpoint (GET /v1/custom-pack). They are searched on the device and drawn as images.
tenanttenant—Your id for one of your customers: adds that tenant’s custom emoji.
culture-urlcultureUrl—The culture files, for example https://api.emojisense.com/v1/culture/0.1.0. Emoji for the culture and the moment join the results after the top result, never above it. Without it the ranking is the canonical one.
regionregionthe browser’sAn ISO 3166-1 code such as BR, for regional culture entries. Without the attribute, the region of the browser’s language, read on the device and never sent. region="" turns regional entries off.
show-relevant-nowshowRelevantNowoffShow a row of seasonal and event emoji from the culture file above the browse view.
—packs—Pack objects to use instead of fetching pack-url
—culture—A culture file to use instead of fetching culture-url
—query""Read or set the search text
—status, engine—idle, loading, ready or error; the engine once ready

The emoji-select event bubbles and crosses shadow roots. Its detail is { emoji, label, id }, with the skin tone applied to emoji. A custom emoji has emoji :shortcode: and id C-<id>, and adds imageUrl and shortcode.

Keyboard: focus stays in the input. Arrow keys move through the grid by visual rows, Enter selects, the first Escape clears the query and the next Escape reaches your page, for example to close a popover.

Frameworks

<script setup lang="ts">
import "@emojisense/web-component";
import type { EmojiSelectEvent } from "@emojisense/web-component";

const packUrl = "https://api.emojisense.com/v1/pack/0.1.0";
const onSelect = (event: EmojiSelectEvent) => insert(event.detail.emoji);
</script>

<template>
  <emojisense-picker
    :pack-url="packUrl"
    publishable-key="pk_live_…"
    @emoji-select="onSelect"
  />
</template>

Vue must know that the tag is a custom element:

vite.config.ts
// vite.config.ts
vue({
  template: {
    compilerOptions: { isCustomElement: (tag) => tag.startsWith("emojisense-") },
  },
});

Svelte 4 uses on:emoji-select={…} instead of onemoji-select.

Theme

The default theme follows prefers-color-scheme or the host’s color-scheme, and animates only when the person allows motion. Change it with CSS custom properties and parts:

CSS
emojisense-picker {
  --emojisense-accent: #ffd23f; /* selected tile */
  --emojisense-ink: #1e1631; /* text and outlines */
  --emojisense-background: #ffffff;
  --emojisense-radius: 1.25rem;
  --emojisense-cell-size: 2.5rem;
  --emojisense-height: 20rem;
  --emojisense-font-family: "Figtree", system-ui, sans-serif;
}

/* A flat look: no outlines, no depth. */
emojisense-picker::part(root) { border: 0; box-shadow: none; }
emojisense-picker::part(option) { border-color: transparent; box-shadow: none; }

Parts: root, search, pill, viewport, listbox, group, relevant-now (the relevant-now row), group-label, option, image (an image of a hosted set), active, message, sticker.

Another tag name

TypeScript
import { defineEmojisensePicker } from "@emojisense/web-component";

defineEmojisensePicker("my-emoji-picker");

@emojisense/web-component/element exports the class without registering anything.