simbiosis/nova-emoji-field
A Laravel Nova field that adds an emoji picker to your resources, letting users select and store emoji values through a simple, native-looking input. Lightweight and easy to drop into any Nova form.
composer.json in the repo and check the laravel/nova constraint in require. If it only allows ^3.0, it will not work on Nova 4/5 without a fork.composer require simbiosis/nova-emoji-field
Nova field packages register their own service provider through extra.laravel.providers; most Nova 4 fields also call Nova::script(...)/Nova::style(...) from boot(), so no manual provider registration is usually needed. Verify with php artisan about or php artisan vendor:publish --tag=nova-emoji-field if the repo exposes tags.src/EmojiField.php — the field class, its $component name, and any resolve/fill overrides.resources/js/field.js and resources/js/components/Field.vue (or IndexField.vue/DetailField.vue) — reveals which emoji picker library is bundled and which props it accepts.dist/js/field.js — must exist, or the field renders an empty box in production.utf8mb4:
// config/database.php
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
Schema::table('posts', fn (Blueprint $t) => $t->string('icon')->nullable());
// or explicitly: ->charset('utf8mb4')
If you skip this, MySQL throws Incorrect string value: '\xF0\x9F...' on the first save — the single most common failure with this kind of field.use Simbiosis\NovaEmojiField\EmojiField;
public function fields(NovaRequest $request): array
{
return [
EmojiField::make('Icon')
->rules('nullable', 'string', 'max:1')
->help('Pick one emoji for the status badge'),
];
}
Render it in your app with {{ $model->icon }} — but ensure the Blade template and JSON responses are served as UTF-8.icon/mood/reaction column with ->rules('max:1'). Note max:1 is character-counted by Laravel via mb_strlen, so a single-codepoint emoji (👍) passes, but ZWJ sequences (👨👩👧) count as multiple codepoints and will fail. If you need full grapheme support, don't validate with max — validate against an allowlist or store the picker's shortcode instead.icon (the emoji) and icon_name (:thumbsup:) if the picker exposes one. Shortcodes are ASCII, searchable, and portable across fonts/terminals where the glyph may not render.IndexField.vue, the emoji renders inline in the resource table. If not, fall back to Text::make('Icon') for the table and use EmojiField only on forms where appropriate via ->onlyOnForms() / ->hideFromIndex().Text::make('Icon', fn () => $this->icon . ' ' . $this->icon_name) for detail pages when the field type is form-only.Select with emoji labels is more deterministic and avoids the free-form picker entirely:
Select::make('Status')->options([
'🟢' => 'Green — Healthy',
'🟡' => 'Amber — Degraded',
'🔴' => 'Red — Down',
]),
Reserve EmojiField for genuinely open-ended input (user avatars, reaction sets, taxonomy icons).->default('📌') works for form prefill as long as the JS component reads field.value on mount — worth a manual test, since tiny packages often skip the null-value branch.categories table with an icon field managed in Nova, rendered next to category names on the front end. Store it as a string, not json, so it stays queryable and avoids JSON encoding pitfalls.resources/js with your own <emoji-picker> props. The package's prebuilt dist/js/field.js is the artifact Nova actually loads, so source edits without npm run prod do nothing.Laravel\Nova\Fields\Field and dropping in emoji-mart yourself is a few hours' work.field.js/field.css. Nova only loads assets registered via Nova::script/Nova::style during boot(); a package that relies on vendor:publish and manual registration will silently fail otherwise. Run php artisan nova:publish and php artisan optimize:clear.utf8mb4 trap applies at every layer. Connection charset, column collation, and serialization. Use json_encode($data, JSON_UNESCAPED_UNICODE) if you return emoji in APIs, or your mobile client will show \ud83d\udc4d. For MySQL dumps/imports, --default-character-set=utf8mb4.max:1 is misleading. As noted, it's codepoint-counted, not grapheme-counted. 👍🏽 (with skin-tone modifier) is two codepoints and will fail max:1. If single-grapheme enforcement matters, validate with grapheme_strlen() in a custom rule.EmojiField::$component) and whether it emits input/change the way Nova 4 expects.class StatusEmoji extends \Simbiosis\NovaEmojiField\EmojiField
{
public $component = 'emoji-field'; // keep, or point at your own built component
How can I help you explore Laravel packages today?