frimousse

repository·main·Indexed 23 days ago

https://github.com/liveblocks/frimousse

A lightweight, unstyled, and composable emoji picker for React. It is dependency-free, tree-shakable, and uses virtualization for high performance. The library provides a composable API via EmojiPicker.Root and its sub-components (Search, Viewport, Loading, Empty, and List), as well as hooks like useActiveEmoji and useSkinTone. It supports React versions 18 and 19 and TypeScript 5.1+.

Tokens
4.6K
Snippets
7
Records
33
Agent score
83%

What's inside frimousse

  1. Compose an EmojiPicker component

    main

    Frimousse is unstyled and composable. You build your UI by importing EmojiPicker parts and arranging them within a EmojiPicker.Root.

    Key parts include:

    • EmojiPicker.Root: The provider/container for the picker.
    • EmojiPicker.Search: The search input field.
    • EmojiPicker.Viewport: A container for the loading, empty, and list states.
    • EmojiPicker.Loading: Shown while emoji data is being fetched.
    • EmojiPicker.Empty: Shown when no results match the search.
    • EmojiPicker.List: The virtualized list of emojis.

    You can style these parts using Tailwind CSS, CSS-in-JS, or by targeting the [frimousse-*] attributes present on each part.

    import { EmojiPicker } from "frimousse";
    
    export function MyEmojiPicker() {
      return (
        <EmojiPicker.Root>
          <EmojiPicker.Search />
          <EmojiPicker.Viewport>
            <EmojiPicker.Loading>Loading…</EmojiPicker.Loading>
            <EmojiPicker.Empty>No emoji found.</EmojiPicker.Empty>
            <EmojiPicker.List />
          </EmojiPicker.Viewport>
        </EmojiPicker.Root>
      );
    }
  2. Use the EmojiPickerStoreProvider and useEmojiPickerStore hook

    main

    The emoji picker store is distributed via a React Context. To access the store within your component tree, wrap your components in the EmojiPickerStoreProvider and consume the state using the useEmojiPickerStore hook.

    If you attempt to use useEmojiPickerStore outside of a provider, it will throw an error: "EmojiPicker.Root is missing."

  3. Configure the EmojiPickerRoot component

    main

    The EmojiPickerRoot component is the main entry point for the emoji picker. You can customize its behavior, locale, skin tone, and data source using the following props:

    • onEmojiSelect: Callback function invoked when an emoji is selected. Receives the selected Emoji object.
    • locale: The locale for the emoji picker (e.g., "en"). Defaults to "en".
    • skinTone: The default skin tone for the picker. Defaults to "none".
    • columns: The number of columns in the emoji list. Defaults to 10.
    • emojiVersion: Manually control which emoji version is visible. Defaults to the most recent version supported by the browser.
    • emojibaseUrl: The base URL for fetching Emojibase data. Defaults to "https://cdn.jsdelivr.net/npm/emojibase-data". You can point this to a CDN like "https://unpkg.com/emojibase-data" or a self-hosted location.
    • sticky: Whether category headers should be sticky. Defaults to true.
  4. Search emojis with searchEmojis()

    main

    The searchEmojis function filters and ranks a list of emojis based on a search string. It uses a scoring mechanism where matches in the emoji label are weighted higher (score of 10) than matches in the tags (score of 1). The results are returned in descending order of their score.

    • emojis: An array of EmojiDataEmoji objects to search through.
    • search (optional): The search string. If omitted, the full list is returned.
  5. Generate emoji picker data with getEmojiPickerData()

    main

    The getEmojiPickerData function transforms raw emoji data into a structured format optimized for rendering an emoji picker UI, supporting categorization, grid columns, searching, and skin tones.

    Parameters

    • data: The source EmojiData containing all emojis and categories.
    • columns: The number of emojis to display per row (used for chunking).
    • skinTone: A SkinTone value (e.g., from the SkinTone type) to apply to compatible emojis. If undefined or 'none', the default emoji is used.
    • search: The current search string to filter emojis.

    Returns

    Returns an EmojiPickerData object containing:

    • count: Total number of emojis matching the search.
    • categories: An array of EmojiPickerDataCategory describing category labels and their position in the grid.
    • categoriesStartRowIndices: Indices indicating where each category begins in the rows array.
    • rows: An array of EmojiPickerDataRow containing chunks of emojis grouped by category.
    • skinTones: The available skin tones from the source data.
  6. Get skin tone variations with getEmojibaseSkinToneVariations()

    main

    Given an emoji object that contains skin tone information, getEmojibaseSkinToneVariations returns a mapping of skin tone keys to their corresponding emoji characters.

    This is useful for implementing emoji pickers that allow users to select different skin tones for a single emoji base.

  7. Selectors for EmojiPickerStore state

    main

    The store provides several selector functions to easily access and derive state. These are useful for optimizing component re-renders.

    • $search(state): Returns the current search string.
    • $activeEmoji(state): Returns the currently active EmojiPickerEmoji if an interaction is occurring, otherwise undefined.
    • $isEmpty(state): Returns true if data is undefined or the count is 0.
    • $isLoading(state): Returns true if essential layout data (like rowHeight or viewportHeight) or the data itself is missing.
    • $rowsCount(state): Returns the number of rows in the data.
    • $categoriesCount(state): Returns the number of categories.
    • $categoriesRowsStartIndices(state): Returns the starting row indices for each category.
    • $skinTones(state): Returns the available skin tones.

    Additionally, use sameEmojiPickerEmoji(a, b) and sameEmojiPickerRow(a, b) to perform equality checks between emoji and row objects.