Lynx/Modules/Emoji Picker/EmojiPicker
@sigx/lynx-emoji · Stable · Component library

EmojiPicker#

The full headless emoji picker: a search row, a category tab bar, a recycled glyph grid, a skin-tone long-press popover and a persistent recents tab. Unstyled beyond neutral inline fallbacks — theme it via classes, render props or a themed wrapper. Pure JS, identical on iOS and Android.

Import#

TSX
import { EmojiPicker } from '@sigx/lynx-emoji';

Basic usage#

Give EmojiPicker a dataset and an onPick handler. Because it is a flex column, it must live in a bounded-height container — without a concrete height ceiling it resolves to zero height and nothing renders. The enData binding is the bundled English dataset (re-exported from the root); pass your own locale from @sigx/lynx-emoji/data/<locale> to tree-shake it away.

TSX
import { EmojiPicker, enData } from '@sigx/lynx-emoji';

function ReactionPicker({ onInsert }: { onInsert: (glyph: string) => void }) {
  return (
    <view style={{ height: '360px' }}>
      <EmojiPicker
        data={enData}
        onPick={({ glyph }) => onInsert(glyph)}
      />
    </view>
  );
}

The onPick payload is an EmojiPickEvent carrying the datum, the tone-resolved glyph to insert, and the active tone. data is optional with an EmojiProvider in scope and required without — it is fixed at mount, and the picker throws if neither a data prop nor a provider is available.

Layout and labels#

columns, cellSize, showRecents, showSearch, searchPlaceholder and emptyLabel tune the surface without touching the theme. The grid defaults to 8 columns of 26px cells; emptyLabel shows when the current slice is empty.

TSX
import { EmojiPicker, enData } from '@sigx/lynx-emoji';

function CompactPicker({ onInsert }: { onInsert: (glyph: string) => void }) {
  return (
    <view style={{ height: '320px' }}>
      <EmojiPicker
        data={enData}
        columns={9}
        cellSize={24}
        showRecents
        searchPlaceholder="Find an emoji"
        emptyLabel="No matches"
        onPick={({ glyph }) => onInsert(glyph)}
      />
    </view>
  );
}

Theming#

The picker is headless with neutral inline-style fallbacks only. There are two theming surfaces: the classes slot map (EmojiSlotClasses, 13 slots — root, search, grid, cell, and so on) and the three render props (renderCell, renderCategoryTab, renderSearchInput). When a class is supplied for a slot, that slot's inline fallback style is dropped. @sigx/lynx-daisyui ships a ready-made skin.

TSX
import { EmojiPicker, enData } from '@sigx/lynx-emoji';
import { EmojiPickerSheet, emojiClasses } from '@sigx/lynx-daisyui';

function Themed({ insert }: { insert: (glyph: string) => void }) {
  return (
    <view style={{ height: '360px' }}>
      <EmojiPicker
        data={enData}
        classes={emojiClasses}
        onPick={({ glyph }) => insert(glyph)}
      />
    </view>
  );
}

A theme package can also extend props onto EmojiPickerProps by augmenting the empty EmojiPropsExtensions interface (the declare module '@sigx/lynx-emoji' pattern).

Sharing recents across surfaces#

With no provider in scope, EmojiPicker builds a private context from its data prop. When more than one picker surface exists, wrap them in an EmojiProvider so they share one dataset, search index, recents list and skin-tone preference. The provider wins over a local data prop, so the surfaces below need no data of their own.

TSX
import { EmojiProvider, EmojiPicker, enData } from '@sigx/lynx-emoji';

function Pickers({ insert }: { insert: (glyph: string) => void }) {
  return (
    <EmojiProvider data={enData} recentsCap={48}>
      <view style={{ height: '360px' }}>
        <EmojiPicker onPick={({ glyph }) => insert(glyph)} />
      </view>
    </EmojiProvider>
  );
}

For chat-composer and bottom-sheet presentations, prefer the KeyboardPanelPicker and SheetPicker wrappers, which size themselves and accept every EmojiPickerProps field except style and onPick.

Props#

PropTypeDescription
dataEmojiDataLocale dataset, fixed at mount. Optional with an EmojiProvider in scope, required without. Default: enData when imported.
columnsnumberGrid columns. Default 8.
showRecentsbooleanShow the persistent recents tab. Default true.
showSearchbooleanShow the search row. Default true.
searchPlaceholderstringPlaceholder text for the search field.
emptyLabelstringShown when the current slice is empty.
cellSizenumberGlyph cell size in px. Default 26.
classesEmojiSlotClassesPer-slot class overrides (13 slots); supplying a slot class drops its inline fallback.
classstringExtra classes on the picker root.
styleRecord<string, string | number>Inline style on the picker root.
renderCellEmojiRenderCellReplaces a grid cell's content: (datum, glyph) => JSXElement.
renderCategoryTabEmojiRenderCategoryTabReplaces a category tab's content: (tab, glyph, active) => JSXElement.
renderSearchInputEmojiRenderSearchInputReplaces the whole search row, driven by an EmojiSearchApi.

Events#

EventTypeDescription
onPick(event: EmojiPickEvent) => voidFired when an emoji is picked. The payload carries datum, the tone-resolved glyph to insert, and the active tone.

See also#

  • API reference — every export, typed (EmojiPickerProps, EmojiPickEvent, the render-prop and theming types).
  • Usage — guides and complete examples, including the keyboard panel, bottom sheet and markdown integration.
  • EmojiProvider — share recents and skin tones across multiple picker surfaces.