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

SkinTonePopover#

The skin-tone chooser: a centered overlay row of an emoji's base glyph plus its five uniform tone variants, shown when a tonal cell is long-pressed. Selecting one inserts that variant and sets the sticky, grid-wide tone preference; a backdrop tap dismisses. It renders position:absolute within the picker root — no portal or caret math.

Import#

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

Basic usage#

SkinTonePopover is one of the headless parts EmojiPicker is assembled from. Use it directly when you build a custom picker layout: long-press a cell to capture the EmojiDatum, render the popover for it, and apply the chosen tone to your grid. The datum must have s variants (long-press only fires for tonal emoji), and toneLabels is the dataset's data.skinTones array (localized labels, indexed tone-1).

TSX
import { component } from '@sigx/lynx';
import {
  EmojiGrid,
  SkinTonePopover,
  glyphForTone,
  createEmojiContext,
  enData,
} from '@sigx/lynx-emoji';
import type { EmojiDatum, SkinTone } from '@sigx/lynx-emoji';

export const CustomGrid = component(({ signal }) => {
  const ctx = createEmojiContext(enData);
  const state = signal<{ toned: EmojiDatum | null }>({ toned: null });

  return () => (
    <view style={{ height: '320px' }}>
      <EmojiGrid
        emojis={ctx.data.emojis}
        tone={ctx.skinTone.state.tone}
        onPick={(datum) => ctx.recents.push(datum)}
        onPickTone={(datum) => { state.toned = datum; }}
      />
      {state.toned && (
        <SkinTonePopover
          datum={state.toned}
          toneLabels={ctx.data.skinTones}
          activeTone={ctx.skinTone.state.tone}
          onSelect={(tone: SkinTone) => {
            ctx.skinTone.set(tone);
            state.toned = null;
          }}
          onClose={() => { state.toned = null; }}
        />
      )}
    </view>
  );
});

onSelect carries the picked SkinTone (0 is the base glyph; 1..5 are light to dark). Call skinTone.set(tone) to apply it grid-wide and persist it, then resolve each cell's glyph with glyphForTone(datum, tone). onClose fires on a backdrop tap without a selection.

Theming#

The popover is headless with neutral inline fallbacks only. backdropClass styles the dismiss layer, class the row container, and cellClass each variant swatch — these are the same three slots EmojiPicker exposes through its classes map as popoverBackdrop, popover and popoverCell (see EmojiSlotClasses).

TSX
<SkinTonePopover
  datum={datum}
  toneLabels={data.skinTones}
  activeTone={tone}
  backdropClass="bg-black/40"
  class="rounded-box bg-base-100 p-2"
  cellClass="p-1"
  onSelect={(t) => skinTone.set(t)}
  onClose={() => dismiss()}
/>

Props#

PropTypeDescription
datumEmojiDatumThe tonal emoji to choose a variant for. Required; must have uniform tone variants (datum.s).
toneLabelsstring[]Localized skin-tone labels (data.skinTones), indexed tone-1. Required.
activeToneSkinToneThe currently selected tone (0 base, 1..5 light to dark) to highlight.
backdropClassstringClass for the dismiss backdrop layer.
classstringClass for the popover row container.
cellClassstringClass for each variant swatch cell.

Events#

EventTypeDescription
onSelect(tone: SkinTone) => voidFired when a tone variant is chosen. Inserts the variant and is where you call skinTone.set(tone) to make the preference sticky.
onClose() => voidFired when the backdrop is tapped to dismiss without a selection.

See also#