Skip to main content
Version: v0.22.x

EmojiPicker

EmojiPicker is a full React Native emoji keyboard: 1,923 emojis in 9 categories, keyword search, skin tones, recently used, a category bar, and filtering by Emoji version so older devices never show empty boxes. Emojis render with the system font; no images or fonts are bundled.

import { EmojiPicker } from '@elik56a/react-native-pickers';
Loading…
<>
  <Text style={{ fontSize: 24, minHeight: 36, marginBottom: 8 }}>
    {text}
  </Text>
  <EmojiPicker onSelect={(emoji) => setText((t) => t + emoji)} />
</>

Try the props​

Platform
categoryBarPosition
columns
<EmojiPicker onSelect={insert} />

onSelect​

onSelect: (emoji: string, data: Emoji) => void

emoji is the character to insert, with the current skin tone applied. data is the base emoji's metadata:

interface Emoji {
emoji: string; // base character, e.g. '👍'
name: string; // 'thumbs up'
keywords: string[]; // search tags
category: EmojiCategory;
version: number; // Emoji version it was introduced in, e.g. 13.1
skins?: string[]; // 5 skin-tone variants (light → dark) when supported
}

Categories​

type EmojiCategory = 'smileys' | 'people' | 'animals' | 'food' | 'travel' | 'activities' | 'objects' | 'symbols' | 'flags';

categories filters and orders the sections and the category bar:

Loading…
<EmojiPicker
  height={300}
  categories={['food', 'animals', 'activities']}
  onSelect={() => {}}
  showSkinTones={false}
/>

Hide specific characters with exclude={['🖕', '🍆']}.

The search field matches names and keywords, ranks name-prefix matches first, and requires every word to match (cat face → 🐱). Search across a custom list in your own UI with searchEmojis.

Skin tones​

The ✋ button next to search opens a tone menu. Tones are numbers:

type SkinTone = 0 | 1 | 2 | 3 | 4 | 5; // 0 = default yellow, 1–5 = light → dark

Tones apply to every emoji that supports them, in the grid and in what onSelect returns. Control or persist the tone:

const [tone, setTone] = useState<SkinTone>(0);
<EmojiPicker skinTone={tone} onSkinToneChange={setTone} onSelect={insert} />

Use defaultSkinTone for uncontrolled, or showSkinTones={false} to hide the button.

Recently used​

Picked emojis go to a Recently used section at the top (up to maxRecent, default 24, most recent first). The list stores base emojis, so they re-render in whatever tone is current.

In EmojiPickerSheet and EmojiPickerField, the sheet keeps them, so they last between openings. A pick that closes the sheet shows up under Recently used the next time it opens, not while it closes, so the grid doesn't jump as it fades or slides away, as on the iOS emoji keyboard.

The picker keeps recents in memory by default. To persist them across launches, control them:

Persisting recents with AsyncStorage
import AsyncStorage from '@react-native-async-storage/async-storage';

function Picker({ onPick }: { onPick: (e: string) => void }) {
const [recent, setRecent] = useState<string[]>([]);

useEffect(() => {
AsyncStorage.getItem('emoji-recent').then((v) => v && setRecent(JSON.parse(v)));
}, []);

return (
<EmojiPicker
recent={recent}
onRecentChange={(next) => {
setRecent(next);
AsyncStorage.setItem('emoji-recent', JSON.stringify(next));
}}
onSelect={onPick}
/>
);
}

Seed a starter set with defaultRecent={['👍', '❤️', '😂']}, or turn the section off with showRecent={false}.

Older devices: maxEmojiVersion​

Emojis newer than the device's font render as empty boxes (common on older Android). Hide them by version:

import { Platform } from 'react-native';

<EmojiPicker
maxEmojiVersion={Platform.OS === 'android' && Platform.Version < 30 ? 12 : undefined}
onSelect={insert}
/>

Designs​

Like every picker, it follows the design of the platform it runs on, after that platform's own emoji picker:

iosmaterialweb
Categoriesat the bottom, like the iOS emoji keyboardat the bottom, like Gboardon top
Current categorya gray rounded filla tinted pillan underline
Searcha short gray search bara tall pillan outlined input with a focus ring
Section titlesUPPERCASESentence caseSentence case

Use the iOS / Android / Web switch on any example above to compare. categoryBarPosition="top" or "bottom" puts the bar in one place on every platform.

Layout​

Loading…
<EmojiPicker
  height={340}
  columns={7}
  emojiSize={30}
  categoryBarPosition="bottom"
  showSectionHeaders={false}
  onSelect={() => {}}
/>
  • columns (default 8) sets emojis per row. Cells are square and fill the width.
  • emojiSize sets the font size (default about 62% of the cell).
  • height (default 380) is the total height including search and category bar.
  • categoryBarPosition: 'auto' (default) puts the bar where the design does, at the bottom on iOS and Android and on top on the web; 'top' or 'bottom' fixes it. Hide the bar with showCategoryBar={false}.
  • showSectionHeaders={false} removes the "Smileys & Emotion" style headers.

Translating labels and icons​

Every label is replaceable. The categoryLabels keys are the categories plus recent and search. Icons can be strings (rendered as text) or any React node:

Loading…
<EmojiPicker
  height={320}
  searchPlaceholder="Rechercher"
  emptyText="Aucun emoji"
  categoryLabels={{
    recent: 'Récents',
    smileys: 'Smileys et émotions',
    people: 'Personnes',
    animals: 'Animaux et nature',
    food: 'Nourriture',
    travel: 'Voyages',
    activities: 'Activités',
    objects: 'Objets',
    symbols: 'Symboles',
    flags: 'Drapeaux',
    search: 'Résultats',
  }}
  categoryIcons={{ smileys: '🙂', food: '🥐' }}
  onSelect={() => {}}
/>

Custom emoji cells​

renderEmoji(emoji, data, size) replaces the character, for example to render a custom image set like Twemoji:

<EmojiPicker
renderEmoji={(emoji, data, size) => <Image source={{ uri: twemojiUrl(emoji) }} style={{ width: size, height: size }} />}
onSelect={insert}
/>

In a sheet​

<EmojiPickerSheet visible={open} onClose={() => setOpen(false)} onSelect={(e) => setText((t) => t + e)} />

The sheet closes after each pick by default (closeOnSelect={false} to keep it open). → EmojiPickerSheet

In a form field​

EmojiPickerField opens the sheet from a field and shows value, the emoji you keep in state. Use renderTrigger for an icon button instead of a field. Switch presentation in the panel: auto opens a dropdown under the field on the web and a bottom sheet on iOS and Android.

Platform
presentation
<EmojiPickerField
label="Icon"
placeholder="Pick an icon"
value={icon}
onSelect={setIcon}
/>

→ Picker fields

Props​

PropTypeDefaultDescription
onSelect(emoji: string, data: Emoji) => voidrequiredCalled with the toned character and its metadata.
columnsnumber8Emojis per row.
emojiSizenumber~62% of cellEmoji font size.
heightnumber380Total height.
categoriesEmojiCategory[]all 9Which categories to show, in order.
excludestring[]—Characters to hide.
maxEmojiVersionnumber—Hide emojis newer than this Emoji version.
searchablebooleantrueShow the search field.
searchPlaceholderstring'Search emoji'Search hint.
emptyTextstring'No emoji found'Empty search result text.
showCategoryBarbooleantrueShow the category tabs.
categoryBarPosition'auto' | 'top' | 'bottom''auto'Tab bar position. auto: bottom in the iOS and Material designs, top on the web.
showSectionHeadersbooleantrueSection title rows.
categoryLabelsPartial<Record<EmojiCategory | 'recent' | 'search', string>>EnglishSection and tab labels.
categoryIconsPartial<Record<EmojiCategory | 'recent', ReactNode>>emoji iconsTab icons.
skinToneSkinTone—Controlled tone.
defaultSkinToneSkinTone0Initial tone.
onSkinToneChange(tone: SkinTone) => void—Tone picked in the menu.
showSkinTonesbooleantrueShow the tone button.
recentstring[]—Controlled recents (base characters).
defaultRecentstring[][]Initial recents.
onRecentChange(recent: string[]) => void—New recents after each pick.
showRecentbooleantrueShow and update recents.
maxRecentnumber24Recents kept.
renderEmoji(emoji: string, data: Emoji, size: number) => ReactNode—Custom cell content.
styleStyleProp<ViewStyle>—Container style.
stylesSlotStyles<EmojiPickerSlot>—Slots below.
themeDeepPartial<PickerTheme>—Theme override.
design'ios' | 'material' | 'web'from PickersProviderThe look to follow, over the provider's: iOS, Material or web.
testIDstring—Test ID.

Slots​

SlotElement
containerOuter view
headerSearch + tone row
searchInputSearch TextInput
skinToneButton / skinToneMenuTone button / menu
categoryBarTab bar
categoryTab / activeCategoryTabTabs
categoryIndicatorActive-tab underline (web design; iOS and Material mark the tab itself)
sectionHeader / sectionHeaderTextSection titles
emojiCell / emojiTextGrid cells
empty / emptyTextNo search results

Data and utilities​

The emoji data comes from emojibase (MIT) and is parsed lazily on first use. The helpers are exported for your own UIs (reactions bars, :shortcode autocomplete): getAllEmojis, searchEmojis, findEmoji, withSkinTone, EMOJI_CATEGORIES, DEFAULT_CATEGORY_LABELS, DEFAULT_CATEGORY_ICONS. → Emoji utilities