Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Emoji Picker Command Menu Block for React

A team chat's emoji menu shown open over its composer: names and shortcodes, a skin-tone switch for hands and people, and Enter adds an emoji to the message under the list while the menu stays open.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Add emoji to a message without leaving the keyboard with this emoji picker command menu for React with Base UI. It opens from the composer of the #launch channel in Chatterbox Row, a team chat, whose header holds an outline field with its ⌘ K cap, and the channel is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The menu is the catalog Command: thirty-four emoji in five groups, each row the glyph, its name and its :shortcode:, with a Frequently used group of six above them until you type. A skin-tone ToggleGroup over the list re-tones every hand and person at once. Enter adds the highlighted emoji to the message in the field at the foot of the menu, at the caret, and the menu stays open so several can be added; the drawn composer behind it shows the message as it grows. Escape closes the menu and the status line says what the message reads. Emoji are the one place this library draws glyphs as data: the operating system's font paints them, and each one is hidden from assistive technology with its name beside it. For preview the menu is drawn open in place when the page loads; the field, or Ctrl or ⌘ K while focus is in the block, opens the real command dialog with the same emoji, tone, message and query. For chat, comments and any field that takes a reaction.

FAQ

Why is the menu already open, and what do I keep?

So you can see it without a click. On load the menu is the Command, the tone switch and the message field drawn inline under a picture of the channel, in a plain shell that is not modal, so nothing is trapped, hidden or focused and the page around the preview keeps working. The header's field opens the real command dialog, modal, with its focus trap, Escape and focus return, and the inline copy stays closed until a reload. Both show the same Palette and share the block's state, so the message you wrote in the copy is the one the dialog opens with. In your app keep the dialog and drop the copy: the "in-place" state, the scrim with its shell and the Escape and blur effects.

How does the skin tone work?

Six chips, one always chosen, each drawn as a hand in its tone. A hand or a person in the list is its base glyph plus the Unicode modifier for the tone (a colour selector is dropped first), so choosing Dark turns the waving hand, the thumbs up, the clap and the others at once and leaves the rest as they are. The switch sits outside the command, because its keys would take Enter from the buttons; Tab reaches it from the list. The status line says which tone is chosen.

What does Enter do, and where does the emoji go?

It puts the highlighted emoji into the message field at the foot of the menu, at the caret where you last left it (at the end if you have not clicked in), and the menu stays open for the next one. The message is a field of its own, so you can type around the emoji; Clear empties it and the status line says so. Escape closes the menu and the status line reads the message back, with "Nothing was sent". The drawn composer behind the menu mirrors the message, since the scrim sinks the stage.

What stays local, and how do I wire it?

All of it. The emoji, the tone and the message are state in the block, nothing is sent or saved, and nothing touches the clipboard. In your app replace EMOJI with your set (or a full emoji data package), keep Frequently used in the user's settings, and send message from the composer's own submit.

Is it accessible from the keyboard?

Yes. Type to search, the arrow keys move through the emoji, Enter adds one, and Escape closes the menu and puts focus on the field; Tab reaches the tone switch, the message field and Clear. Ctrl or ⌘ K opens the dialog while focus is inside the block, and only then. The rows are options of a cmdk listbox; the block turns off its own fuzzy filter and lists the rows itself. Every glyph is hidden from assistive technology; a row is read as its name and its shortcode.

  • Pro

    A page builder's icon picker as a command menu shown open over a block's settings: forty icons drawn at the chosen size and stroke, two sliders that restyle every row, and Enter copies the JSX.

  • Pro

    A notes editor's formatting menu shown open over a note: a real textarea with a sample sits above seven rows that format its selection or insert a block, and a preview and a mono line show the result.

  • Pro

    A help desk's reply library as a command menu shown open over a ticket: choosing a reply with slots turns the menu into a short form, a textarea previews the filled reply, and Enter inserts it.

  • Pro

    Recent Items Command Menu

    Search everything

    A project hub's command menu shown open on what you opened lately: Today, Yesterday and Earlier buckets before you type, recent matches first when you do, opening a row moves it to the top, and a last row clears the list.

  • Pro

    Basic Command Menu

    Search everything

    A team workspace's home page with its command menu shown open: eleven pages in three groups, a shortcut on the five most used, matches marked, an empty state that says what to try and a foot with the key hints and a spoken count.

  • Pro

    A motion tool's preset menu shown open over its transitions panel: easing curves, springs and durations each drawn as a 24 px curve, a track band that runs the highlighted preset's real CSS timing once on an arrow key or Replay, and a text reading under reduced motion.