Tag Input

The Tag Input component (<x-tag-input>) is a flexible, badge-styled input for collecting multiple values from the user — perfect for tags, labels, keywords, or recipient lists. It is built on top of Tagify and wraps it into a familiar field component that integrates seamlessly with Livewire.

Tags can be plain strings or rich objects ({ value, type }) — the latter enabling per-tag colors via the badge system. State is fully two-way bound via wire:model, including server-driven resets, suggestion whitelists and validation errors.

Basic Usage

At its simplest, the Tag Input is bound to an array property via wire:model. The user types a value and presses Enter (or a delimiter) to add it as a tag.

1<x-tag-input id="basic-tags" label="Tags" placeholder="Add a tag and press enter" />

Suggestions

Provide a list of autocomplete suggestions via the suggestions prop. As the user types, matching suggestions appear in a dropdown.

1<x-tag-input
2 id="suggestions-tags"
3 label="Stack"
4 placeholder="Start typing..."
5 :suggestions="['Laravel', 'Livewire', 'Alpine.js', 'Tailwind CSS', 'Pest', 'Inertia', 'Filament']"
6/>

Enforce Whitelist

Set enforceWhitelist to true to allow only values that exist in the suggestions list. Anything else is rejected.

Only tags from the whitelist can be added.
1<x-tag-input
2 id="enforce-whitelist-tags"
3 label="Allowed Tags Only"
4 hint="Only tags from the whitelist can be added."
5 placeholder="Pick a tag..."
6 :suggestions="['Bug', 'Feature', 'Documentation', 'Question']"
7 :enforceWhitelist="true"
8/>

Object Mode

In object mode, each tag is stored as an object instead of a plain string. This enables per-tag colors by attaching a type (badge type) to every suggestion.

The bound property will receive an array like:

1[
2 ['value' => 'Bug', 'type' => 'danger'],
3 ['value' => 'Feature', 'type' => 'success'],
4]
1<x-tag-input
2 id="object-mode-tags"
3 label="Issue Labels"
4 placeholder="Add a label..."
5 :objectMode="true"
6 defaultType="primary"
7 :suggestions="[
8 ['value' => 'Bug', 'type' => 'red'],
9 ['value' => 'Feature', 'type' => 'green'],
10 ['value' => 'Documentation', 'type' => 'primary'],
11 ['value' => 'Question', 'type' => 'yellow'],
12 ]"
13/>
14 
15{{--
16 In objectMode the wire:model property will receive an array of objects
17 like [['value' => 'Bug', 'type' => 'danger'], ...] instead of plain strings.
18--}}

Labels (Display vs. Value)

Decouple the displayed text from the stored value by attaching a label field to each suggestion. The user sees and searches by the human-readable label, while the underlying value (typically an ID) is what flows back into your Livewire property.

A typical suggestion looks like:

1['value' => 'user_42', 'label' => 'Anna Müller', 'type' => 'primary']
1<x-tag-input
2 id="labels-tags"
3 label="Assignees"
4 placeholder="Pick a user..."
5 :objectMode="true"
6 :enforceWhitelist="true"
7 :suggestions="[
8 ['value' => 'user_1', 'label' => 'Anna Müller', 'type' => 'primary'],
9 ['value' => 'user_2', 'label' => 'Ben Schneider', 'type' => 'success'],
10 ['value' => 'user_3', 'label' => 'Clara Fischer', 'type' => 'warning'],
11 ['value' => 'user_4', 'label' => 'David Weber', 'type' => 'danger'],
12 ]"
13/>
14 
15{{--
16 `label` decouples the displayed text from the stored value. Tagify will
17 render and search by `label`, while `value` (e.g. a user ID) is what
18 flows back into your Livewire array. Perfect for assignee pickers,
19 relation selectors, or any case where the underlying identifier should
20 stay hidden from the user.
21--}}

Default Type

The defaultType prop sets the badge type used for tags that don't carry their own type. It maps directly to the badge color system.

TypeDescription
primaryDefault — main brand color.
successPositive / confirmation.
warningCaution / attention.
dangerErrors / destructive items.
grayNeutral.
blackHigh-contrast accent.
1<x-tag-input
2 id="default-type-tags"
3 label="Success Tags"
4 defaultType="emerald"
5 placeholder="Add a tag..."
6/>

Badge Style

Choose how tag badges are rendered using the badgeStyle prop. The style applies to both the rendered tags and the suggestion dropdown.

StyleDescription
solidDefault — filled background.
invertInverted color scheme.
labelSubtle label-like appearance.
outlineBordered, transparent background.
1<x-tag-input id="badge-style-solid" label="Solid (default)" badgeStyle="solid"
2 :suggestions="['Laravel', 'Livewire', 'Alpine.js']" />
3 
4<x-tag-input id="badge-style-invert" label="Invert" badgeStyle="invert"
5 :suggestions="['Laravel', 'Livewire', 'Alpine.js']" />
6 
7<x-tag-input id="badge-style-label" label="Label" badgeStyle="label"
8 :suggestions="['Laravel', 'Livewire', 'Alpine.js']" />
9 
10<x-tag-input id="badge-style-outline" label="Outline" badgeStyle="outline"
11 :suggestions="['Laravel', 'Livewire', 'Alpine.js']" />

Max Tags

Limit the number of tags the user can add via maxTags. Once the limit is reached, further input is rejected.

You can add up to 3 tags.
1<x-tag-input
2 id="max-tags-tags"
3 label="Top 3 Skills"
4 hint="You can add up to 3 tags."
5 :maxTags="3"
6 placeholder="Add a skill..."
7/>

Duplicates

By default duplicate tags are rejected. Set duplicates to true to explicitly allow them.

1<x-tag-input
2 id="duplicates-tags"
3 label="Allow Duplicates"
4 :duplicates="true"
5 placeholder="Same tag twice? No problem."
6/>

Pattern (Regex Validation)

Validate every tag against a regular expression using the pattern prop. Tags that don't match the pattern are visually flagged as invalid.

Only lowercase letters, digits and dashes are allowed.
1<x-tag-input
2 id="pattern-tags"
3 label="Slugs Only"
4 hint="Only lowercase letters, digits and dashes are allowed."
5 pattern="^[a-z0-9-]+$"
6 placeholder="my-awesome-tag"
7/>

Delimiters

Customize the characters that finalize a tag. Multiple delimiters can be combined using the regex alternation syntax (|). The default is ",".

Press comma or space to finalize a tag.
1<x-tag-input
2 id="delimiters-tags"
3 label="Comma or Space"
4 hint="Press comma or space to finalize a tag."
5 delimiters=", | "
6 placeholder="laravel livewire alpine"
7/>

Placeholder

Show helper text inside the empty input via the placeholder prop.

1<x-tag-input id="placeholder-tags" label="Tags" placeholder="Type something and press enter..." />

Sizes

The component supports the same sizes as other input components: sm, md, lg.

1<x-tag-input id="sizes-sm" size="sm" label="Small" placeholder="Small tag input" />
2<x-tag-input id="sizes-md" size="md" label="Medium" placeholder="Medium tag input" />
3<x-tag-input id="sizes-lg" size="lg" label="Large" placeholder="Large tag input" />

Disabled State

Use the disabled attribute to prevent any interaction with the component.

1<x-tag-input id="disabled-tags" label="Tags" disabled :suggestions="['Laravel', 'Livewire']" />

Read-only State

Use readonly to display existing tags without allowing edits or removals.

1<x-tag-input id="readonly-tags" label="Tags" readonly :suggestions="['Laravel', 'Livewire']" />

Subtle

Make the input blend in with the surrounding background using the subtle attribute — useful inside cards or toolbars.

1<x-tag-input id="subtle-tags" label="Subtle Tag Input" subtle placeholder="Blends with the background" />

Label Addons

Add any content next to the label using the labelAddon slot.

1<x-tag-input id="label-addon-tags" label="Tags">
2 <x-slot:labelAddon>
3 <x-button size="xs" type="link" tabindex="-1">Manage tags</x-button>
4 </x-slot:labelAddon>
5</x-tag-input>

Hint Text

Use the hint attribute to display a small note between the label and the input.

Press enter or comma to add a tag.
1<x-tag-input id="hint-tags" label="Tags" hint="Press enter or comma to add a tag." />

Descriptions

Use the description attribute to display additional context below the input.

Tags will be visible on the public profile.
1<x-tag-input
2 id="description-tags"
3 label="Tags"
4 description="Tags will be visible on the public profile."
5/>

Loading State

Combine wire:loading and wire:target to show a loading indicator while Livewire is processing a request triggered by the field.

1<x-tag-input id="loading-tags" wire:model="tags" wire:loading wire:target="tags" label="Tags" placeholder="Add a tag..." />

Tagify Options (Escape Hatch)

Need a Tagify setting that isn't exposed as a prop? Pass any extra configuration through the options prop — it is merged directly into the underlying Tagify settings, overriding component defaults.

1<x-tag-input
2 id="options-tags"
3 label="Custom Tagify Settings"
4 :suggestions="['Laravel', 'Livewire', 'Alpine.js']"
5 :options="[
6 'editTags' => true,
7 'trim' => true,
8 'dropdown' => [
9 'enabled' => 1,
10 'maxItems' => 5,
11 'closeOnSelect' => true,
12 ],
13 ]"
14/>
15 
16{{--
17 The `options` prop is an escape hatch: anything you pass here is merged
18 directly into the underlying Tagify settings, overriding component defaults.
19 See https://github.com/yairEO/tagify for the full list of options.
20--}}

Livewire Integration Example

A typical Livewire component using the Tag Input to collect post tags, with array validation and a reset after save:

1use Livewire\Component;
2 
3class EditPost extends Component
4{
5 /** @var array<int, string> */
6 public array $tags = [];
7 
8 public function save()
9 {
10 $this->validate([
11 'tags' => 'array|max:5',
12 'tags.*' => 'string|max:32',
13 ]);
14 
15 auth()->user()->posts()->create([
16 'tags' => $this->tags,
17 ]);
18 
19 $this->tags = [];
20 }
21 
22 public function render()
23 {
24 return view('livewire.edit-post');
25 }
26}

All Attributes

Complete reference of all available attributes for the <x-tag-input> component:

Attribute Type Default Description
wire:model String Livewire property to bind tags to. Array of strings (default) or array of objects (object mode).
label String false Label displayed above the field.
labelAddon Slot / HTML false Extra content rendered next to the label.
hint String false Helper text between label and input.
description String false Description text below the input.
placeholder String false Placeholder text inside the empty input.
size String md Field size: sm, md, lg.
subtle Boolean false Subtle style — blends with surroundings.
disabled Boolean false Disables the entire field.
readonly Boolean false Renders tags as read-only.
objectMode Boolean false Store tags as objects ({ value, type }) instead of plain strings.
defaultType String primary Badge type used for tags without an explicit type.
badgeStyle String solid Badge style: solid, invert, label, outline.
suggestions Array [] Autocomplete whitelist. Strings or { value, type, label? } objects. The optional label field is displayed to the user while value stays in the underlying state.
enforceWhitelist Boolean false Only allow values present in suggestions.
maxTags Integer false Maximum number of tags allowed.
duplicates Boolean false Allow duplicate tags.
pattern String (regex) false Regex pattern each tag must match. Invalid patterns are ignored.
delimiters String "," Characters / regex alternation that finalize a tag.
options Array [] Escape hatch — extra Tagify settings merged into the underlying instance.
show-errors Boolean true Whether to render validation errors below the field.