Skip to article
Integrations / emoji-mart

emoji-mart

Keep emoji-mart and give it Emojisense ranking.

On this page

Keep emoji-mart 5 and give it Emojisense ranking. emoji-mart has no search hook, so @emojisense/emoji-mart offers two ways in. Both hand you emoji-mart’s own onEmojiSelect payload (id, native, unified, shortcodes, skin and more).

attachEmojisense (recommended)overrideSearchIndex (experimental)
HowHides emoji-mart’s search. Your input drives a ranked list next to the picker.Replaces SearchIndex.search, which emoji-mart’s own search box calls.
LayersDevice, shards and APIDevice only
Relies onPublic API onlyAn internal detail of emoji-mart 5.6

Install

npm install @emojisense/emoji-mart emojisense emoji-mart @emoji-mart/data
TypeScript
import data from "@emoji-mart/data";
import { Picker, Store } from "emoji-mart";
import { createEngine, createLayeredSemantic, loadPacks } from "emojisense";

const packs = await loadPacks({ baseUrl: "https://api.emojisense.com/v1/pack/0.1.0" });
const engine = createEngine(packs);
const semantic = createLayeredSemantic({
  shardsUrl: "https://api.emojisense.com/p/0.1.0",
  endpoint: "https://api.emojisense.com",
  key: "pk_live_…",
});

attachEmojisense

TypeScript
import { attachEmojisense } from "@emojisense/emoji-mart";

const onEmojiSelect = (emoji) => insert(emoji.native);
const picker = new Picker({ data, onEmojiSelect, searchPosition: "none" });
document.querySelector("#picker").append(picker);

attachEmojisense({
  picker,
  input: document.querySelector("#emoji-search"), // your <input>
  results: document.querySelector("#emoji-results"), // an empty element
  data,
  engine,
  semantic,
  onEmojiSelect,
  skin: () => Store.get("skin") ?? 1, // the skin chosen in emoji-mart's picker
});
  • An empty query shows emoji-mart’s picker. A typed query hides it and shows the ranking.
  • The input becomes an ARIA combobox and the results element an ARIA listbox. Arrow keys move, Enter selects, Escape clears the query.
  • Style the list with [data-emojisense-results] (a CSS grid), [role="option"][data-active] and [data-emojisense-results][data-empty].
  • renderEmoji: (emoji, selection) => node changes what a result shows, for example <em-emoji> for an image set.
  • dispose() removes the listeners and shows the picker again.

createEmojiMartSearch({ data, engine, semantic, onResults }) is the same search without a UI, for a list rendered by React, Vue or anything else.

overrideSearchIndex

TypeScript
import { SearchIndex } from "emoji-mart";
import { overrideSearchIndex } from "@emojisense/emoji-mart";

const restore = overrideSearchIndex(SearchIndex, { data, engine });
// emoji-mart's own search box now ranks with the Emojisense dictionary.
// restore() undoes it.

Limits

  • @emoji-mart/data 1.2.1 stops at Emoji 15.0. Results for newer emoji are dropped.
  • After emoji-mart’s init has run, results are limited to the emoji its picker lists.
  • Selections from the Emojisense list do not update emoji-mart’s “Frequently used” row. Call FrequentlyUsed.add(emoji) in your onEmojiSelect for that.
  • The override applies to every emoji-mart picker on the page, because SearchIndex is a singleton.
  • Always pass emoji-mart its data. Without it, emoji-mart fetches the data from a public CDN.