Skip to main content
2plot.ai

dash-emoji-mart — emoji picker for Dash

An emoji picker for Plotly Dash 4.

emoji-mart — the picker behind Missive, and the one most React apps reach for — wrapped as a single Dash component.

PyPI Python Dash License Docs

Documentation · PyPI · Changelog · Discord

dash-emoji-mart


The goal is a component that is universal but specifically elegant on mobile: an emoji, icon and picture selector that is intuitive on any device.

Install

pip install dash-emoji-mart

Python 3.9+ and Dash 4.1+. The compiled JavaScript bundle ships inside the package — no Node, no build step, no external_scripts. The full emoji data set is bundled too, so the picker works offline and makes no requests of its own.

Iconify icon-set support is an optional extra:

pip install "dash-emoji-mart[iconify]"

Quick start

from dash import Dash, callback, html, Input, Output
from dash_emoji_mart import DashEmojiMart

app = Dash(__name__)
app.layout = html.Div([
    DashEmojiMart(id="picker"),
    html.Div(id="out", style={"fontSize": 48}),
])

@callback(Output("out", "children"), Input("picker", "value"))
def show(value):
    return value or "Pick one"

if __name__ == "__main__":
    app.run(debug=True)

Reading a selection

Every pick writes two props in one update, so a callback taking both fires once:

Prop Type Contents
value str The native glyph ("😀"), or the image URL for a custom emoji.
selectedEmoji dict The whole emoji-mart object — id, name, native, unified, shortcodes, keywords, skin, and src for custom emojis.

selectedEmoji is the cleanest way to tell a built-in emoji from a custom one, since only custom emojis carry src:

@callback(Output("out", "children"), Input("picker", "selectedEmoji"))
def show(emoji):
    if not emoji:
        return "Nothing picked"
    if emoji.get("src"):
        return html.Img(src=emoji["src"], style={"height": 32})
    return emoji["native"]

clickedOutside is an n_clicks-style counter that increments on each click outside the picker — the signal for closing a popover.

Custom emojis

Categories of your own images, GIFs or SVGs sit alongside the built-in ones:

DashEmojiMart(
    id="picker",
    custom=[{
        "id": "team",
        "name": "Team",
        "emojis": [{
            "id": "party_parrot",
            "name": "Party Parrot",
            "keywords": ["dance", "party"],
            "skins": [{"src": "https://example.com/parrot.gif"}],
            "native": "",
            "unified": "custom",
        }],
    }],
    categoryIcons={"team": {"svg": '<svg width="1em" height="1em" ...></svg>'}},
    categories=["frequent", "team", "people"],   # place it in the order you want
)

Custom emojis have no native glyph, so value comes back as the image URL. Full details: Custom emojis.

Iconify icon sets

Iconify hosts 150+ icon sets, several of them emoji sets far larger than the one emoji-mart bundles — twemoji has ~4,000 glyphs, OpenMoji ~4,200. dash_emoji_mart.iconify reshapes any of them into pickable categories:

from dash_emoji_mart import DashEmojiMart
from dash_emoji_mart.iconify import iconify_to_emoji_mart

DashEmojiMart(
    id="picker",
    custom=iconify_to_emoji_mart("twemoji", max_icons_per_category=60),
)

Responses are cached on disk for 24 hours (DASH_EMOJI_MART_CACHE_DIR relocates it), and a network failure degrades to an empty category list rather than an error. Full details: Iconify icon sets.

Picker in a popover

Very few apps want a 400px picker sitting in the page. dmc.Popover gives you a trigger that opens the picker and dismisses it on an outside click, both client-side, so the only callback you write is the one that closes it after a pick:

@callback(
    Output("popover", "opened"),
    Input("picker", "value"),
    prevent_initial_call=True,
)
def close_on_pick(_value):
    return False

Do not also add a callback that toggles opened from the trigger's n_clicks: dmc.Popover has already flipped opened itself by the time it runs, so reading it as State and returning not opened closes the popover on the same click that opened it. For a hand-rolled panel — no dmc.Popover — use the picker's clickedOutside counter instead.

Full worked example: Picker in a popover.

Props

The complete, always-current table is at emojimart.2plot.dev/api-reference, and in the component docstring (help(DashEmojiMart)). The commonly used ones:

Prop Default Choices
perLine 9 Emojis per row
emojiSize 24 px
emojiButtonSize 36 px
emojiButtonRadius "100%" any CSS radius, e.g. "6px"
theme "auto" auto, light, dark
set "native" native, apple, facebook, google, twitter
locale "en" en, ar, be, cs, de, es, fa, fi, fr, hi, it, ja, ko, nl, pl, pt, ru, sa, tr, uk, vi, zh
categories [] (all) frequent, people, nature, foods, activity, places, objects, symbols, flags. Built-ins only — do not combine with custom, see below
navPosition "top" top, bottom, none
previewPosition "bottom" top, bottom, none
previewEmoji "point_up" emoji id shown when nothing is hovered
searchPosition "sticky" sticky, static, none
skinTonePosition "preview" preview, search, none
skin 1 16
emojiVersion 14 max Emoji version to show
maxFrequentRows 4 0 disables the frequent category
exceptEmojis [] emoji ids to hide from the grid — search still finds them, see below
noResultsEmoji "cry" shown when a search finds nothing
noCountryFlags False hide country flags from the grid — search still finds them, see below
icons "auto" auto, outline, solid
autoFocus False focus the search input on mount
dynamicWidth False fill the container instead of sizing from perLine
emojiButtonColors [] hover backgrounds, cycled
className / style applied to the wrapper element
persistence / persisted_props / persistence_type standard Dash persistence

set, locale and custom are read once, when emoji-mart builds its internal store. Changing them on a mounted picker has no visible effect — wrap it in a html.Div(..., id=...) whose id varies with the value to force a remount (Dash keys each child on its id; a key= prop is not read for reconciliation). Every other prop updates in place.

exceptEmojis and noCountryFlags filter the grid, not the search. Measured against emoji-mart 5.6.0: both remove the emoji from its category, while SearchIndex.search matches over the unfiltered emoji map. With noCountryFlags=True the flags category shrinks to a small safe list and typing "united" still returns 🇬🇧 🇺🇸 🇦🇪 🇺🇳. Treat them as tidying, not as access control.

Do not pass categories together with custom. emoji-mart filters categories against a snapshot it takes on the first picker initialised in the page's lifetime, so custom ids resolve on that first picker and are silently dropped on every one after it — making the result depend on which page a user opened first. Omit categories when using custom; your categories are then appended after the built-ins.

Development

git clone https://github.com/pip-install-python/dash-emoji-mart
cd dash_emoji_mart

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt      # docs site + the component, editable

# markdown2dash pins gunicorn<22, against the CVE-driven gunicorn>=23 floor in
# requirements.txt. pip cannot resolve both, so it installs without its
# dependency set — everything it actually needs is already in the line above.
pip install --no-deps markdown2dash==0.1.2

npm install
npm run build                        # webpack bundle + generated Python classes

python run.py                        # the docs site at http://127.0.0.1:8050

npm run build writes into dash_emoji_mart/ — both the bundle and the generated DashEmojiMart.py. Both are committed: that is what lets pip install work without Node, and what lets the Docker image build without it.

Before opening a PR:

python scripts/smoke_test.py         # renders every docs page, checks every route
python scripts/check_release.py      # version drift, stale bundle, packaging leaks

CI runs both against Dash 4.1.0 → 4.4.1 and installs the built wheel on Python 3.9 → 3.13. See CONTRIBUTING.md and RELEASING.md.

Documentation site

The docs at emojimart.2plot.dev are this repository's docs/ directory: one folder per page, holding a markdown file and the example.py that renders its live demo. pages/markdown.py walks them and registers each as a Dash page — adding a page means adding a folder, with no Python wiring anywhere else.

Every page also serves /<page>/llms.txt with its prose and complete example source, for pasting into a chat window.

Deployment is a Render Blueprint (render.yaml) building Dockerfile.

Upgrading from 0.0.x

0.2.0 raises the floor to Dash 4.1 / Python 3.9 and removes four props that no Dash app could ever have used (onEmojiSelect, onClickOutside, onAddCustomEmoji, getSpritesheetURL — all function-typed, and Dash cannot serialise a Python function). value is unchanged, so callbacks reading it keep working. See the changelog for the full list.

Credits

Built on emoji-mart by Missive. Icon sets from Iconify. Documentation shell from the dash-documentation-boilerplate.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dash_emoji_mart-0.2.1.tar.gz (222.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dash_emoji_mart-0.2.1-py3-none-any.whl (209.1 kB view details)

Uploaded Python 3

File details

Details for the file dash_emoji_mart-0.2.1.tar.gz.

File metadata

  • Download URL: dash_emoji_mart-0.2.1.tar.gz
  • Upload date:
  • Size: 222.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for dash_emoji_mart-0.2.1.tar.gz
Algorithm Hash digest
SHA256 62fd4a96d843e67e6d857eff4caf1d55c527114f7a4be2760d1b99adfb14e3c7
MD5 dc294f33d02698a1e78e742009d35199
BLAKE2b-256 62f6edb4582d45d61d6ac5e4593a3426ebea8d3a95fcf2ab1acf9d12bffd528d

See more details on using hashes here.

Provenance

The following attestation bundles were made for dash_emoji_mart-0.2.1.tar.gz:

Publisher: release.yml on pip-install-python/dash-emoji-mart

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dash_emoji_mart-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: dash_emoji_mart-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 209.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for dash_emoji_mart-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f6581825600cf732aaac047d992135568ce1c39c75b9107e645db3fcf34f9a45
MD5 649d15cee35dce2a8db33ab662169906
BLAKE2b-256 2128fba7b9b3a4e9cc17496e54b1122593747c63059540848316bb7e5d3341da

See more details on using hashes here.

Provenance

The following attestation bundles were made for dash_emoji_mart-0.2.1-py3-none-any.whl:

Publisher: release.yml on pip-install-python/dash-emoji-mart

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page