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

KeyboardPanelPicker#

A chat-composer presentation of the emoji picker: a panel that occupies exactly the soft keyboard's space, so toggling between emoji and keyboard never shifts the composer. It renders display:none when closed and remembers the largest keyboard height it has seen.

Import#

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

Basic usage#

Place KeyboardPanelPicker as the last child of a <KeyboardStickyView>, under the input row. The keyboard height comes from useKeyboard(), which needs a <SafeAreaProvider> ancestor. Drive its visibility with the required open prop and listen for picks with onPick:

TSX
import { KeyboardPanelPicker, enData } from '@sigx/lynx-emoji';
import { KeyboardStickyView } from '@sigx/lynx-keyboard';
import { signal } from '@sigx/reactivity';

function ChatComposer({ insert }: { insert: (glyph: string) => void }) {
    const emojiOpen = signal(false);

    return (
        <KeyboardStickyView>
            <view style={{ flexDirection: 'row' }}>
                {/* text input + a button that toggles emojiOpen.value */}
            </view>
            <KeyboardPanelPicker
                open={emojiOpen.value}
                data={enData}
                fallbackHeight={300}
                onPick={({ glyph }) => insert(glyph)}
            />
        </KeyboardStickyView>
    );
}

fallbackHeight (default 300) is used before the keyboard has ever opened, so the panel has a sensible size on first toggle. Unlike a bare EmojiPicker, the panel sizes itself — you do not need to wrap it in a bounded-height container.

Inherited picker props#

KeyboardPanelPicker accepts every EmojiPickerProps field except style and onPick (it owns both). That includes the data, layout and theming surface — columns, cellSize, showSearch, showRecents, searchPlaceholder, emptyLabel, the classes slot map, and the renderCell / renderCategoryTab / renderSearchInput render props. Theme it the same way you would an inline picker:

TSX
import { KeyboardPanelPicker, enData } from '@sigx/lynx-emoji';
import { emojiClasses } from '@sigx/lynx-daisyui';
import { KeyboardStickyView } from '@sigx/lynx-keyboard';

function ThemedPanel({ open, insert }: { open: boolean; insert: (g: string) => void }) {
    return (
        <KeyboardStickyView>
            <KeyboardPanelPicker
                open={open}
                data={enData}
                columns={9}
                classes={emojiClasses}
                onPick={({ glyph }) => insert(glyph)}
            />
        </KeyboardStickyView>
    );
}

Sharing recents with other surfaces#

With an EmojiProvider in scope the panel needs no data prop — it reads the shared dataset, search index, recents list and skin-tone preference, so a composer panel and a SheetPicker stay in sync:

TSX
import { EmojiProvider, KeyboardPanelPicker, enData } from '@sigx/lynx-emoji';
import { KeyboardStickyView } from '@sigx/lynx-keyboard';
import { signal } from '@sigx/reactivity';

function Composer({ insert }: { insert: (glyph: string) => void }) {
    const open = signal(false);

    return (
        <EmojiProvider data={enData} recentsCap={48}>
            <KeyboardStickyView>
                <KeyboardPanelPicker
                    open={open.value}
                    onPick={({ glyph }) => insert(glyph)}
                />
            </KeyboardStickyView>
        </EmojiProvider>
    );
}

Props#

KeyboardPanelPicker is Omit<EmojiPickerProps, 'style' | 'onPick'> plus the three fields below. See EmojiPickerProps for the full inherited set.

PropTypeDescription
openbooleanRequired. Whether the panel is shown. When false it renders display:none.
fallbackHeightnumberPanel height (px) used before the keyboard has ever opened. Default 300.
dataEmojiDataLocale dataset, fixed at mount. Optional with an <EmojiProvider> in scope, required without.
columnsnumberGrid column count. Default 8.
cellSizenumberGlyph cell size in px. Default 26.
showRecentsbooleanWhether the persistent recents tab is shown. Default true.
showSearchbooleanWhether the search row is shown. Default true.
searchPlaceholderstringPlaceholder for the search field.
emptyLabelstringShown when the current category slice is empty.
classesEmojiSlotClassesPer-slot class overrides (13 slots) — the theming surface.
classstringClass on the picker root.
renderCellEmojiRenderCellReplace a grid cell's content.
renderCategoryTabEmojiRenderCategoryTabReplace a category tab's content.
renderSearchInputEmojiRenderSearchInputReplace the whole search row.

style and onPick from EmojiPickerProps are intentionally excluded — the wrapper controls the panel's box, and onPick is redeclared as the event below.

Events#

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

See also#

  • API reference — the typed KeyboardPanelPickerProps.
  • Usage — the full chat-composer guide.
  • SheetPicker — bottom-sheet presentation for one-off / reaction pickers.
  • KeyboarduseKeyboard / KeyboardStickyView, used by this panel.