Skip to content

Tags Input ​

A neo-brutalist style tag entry component built on reka-ui primitives. Commonly used in form scenarios such as article tags, email recipients, and keyword filtering. Supports keyboard shortcuts, delimiter-based auto-add, and multiple color variants.

Demo ​

Preview

默认

vue
tailwind
brutalism

主要

typescript
vite
cva

次要

reka-ui
lucide
pnpm

强调

neo-brutalism
design
tokens

危险

bug
deprecated
breaking

成功

stable
tested
released

自定义 aria-label

vue
a11y

Installation ​

pnpm dlx brutx-vue@latest add tags-input

Usage ​

vue
<script setup>
import { ref } from 'vue'
import {
    TagsInput,
    TagsInputInput,
    TagsInputItem,
    TagsInputItemText,
    TagsInputItemDelete
} from 'brutx-ui-vue'

const tags = ref(['vue', 'css'])
</script>

<template>
    <TagsInput v-model="tags">
        <TagsInputItem v-for="tag in tags" :key="tag" :value="tag">
            <TagsInputItemText>{{ tag }}</TagsInputItemText>
            <TagsInputItemDelete />
        </TagsInputItem>
        <TagsInputInput placeholder="Add tag..." />
    </TagsInput>
</template>

Variants ​

You can customize the color scheme of individual tags using the variant prop on TagsInputItem:

VariantDescription
primaryDefault coral background with black bold border
secondaryMint green background
accentBrutal yellow background
successClassic green background
dangerClassic red background
defaultPlain white background
vue
<template>
    <TagsInputItem value="css" variant="secondary">
        <TagsInputItemText>CSS</TagsInputItemText>
        <TagsInputItemDelete />
    </TagsInputItem>
</template>

Sub-components ​

ComponentDescription
TagsInputRoot component that manages the tag list state
TagsInputInputText input field
TagsInputItemIndividual tag item container
TagsInputItemTextTag text content
TagsInputItemDeleteTag delete button

API Reference ​

TagsInput

TagsInput — Props
NameTypeDefaultDescription
modelValue
Nullable
AcceptableInputValue[] | null | undefined
—
The controlled list of tag values, synchronized with v-model. Each value may be a string, number, bigint, or object.
Details

Declared type

AcceptableInputValue[] | null | undefined

Literal values

  • null

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

defaultValue
AcceptableInputValue[] | undefined
—
The initial tag list for uncontrolled use. Use modelValue when the list must stay synchronized with external state.
Details

Declared type

AcceptableInputValue[] | undefined

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

addOnPaste
boolean | undefined
—
Splits pasted text using delimiter and attempts to add the resulting tags, subject to max and duplicate rules.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

addOnTab
boolean | undefined
—
Commits the current input as a tag when the Tab key is pressed.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

addOnBlur
boolean | undefined
—
Commits the current input as a tag when the input loses focus.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

duplicate
boolean | undefined
—
Allows duplicate tag values in the list. When false, a duplicate value is treated as invalid.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

disabled
boolean | undefined
—
Disables user interaction with the tags-input group and its child items.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

delimiter
string | RegExp | undefined
—
The delimiter used to commit typed input and split pasted text. Accepts a string or regular expression.
Details

Declared type

string | RegExp | undefined

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

dir
Direction | undefined
—
Sets the reading direction for the combobox. When omitted, it inherits ConfigProvider or defaults to left-to-right.
Details

Declared type

Direction | undefined

Literal values

  • "ltr"
  • "rtl"

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

max
number | undefined
—
The maximum number of tags. Further additions are rejected and emit invalid at the limit; 0 means unlimited.
Details

Declared type

number | undefined

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

id
string | undefined
—
The DOM ID passed to the tags-input root primitive to identify this input group.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

convertValue
((value: string) => AcceptableInputValue) | undefined
—
Converts typed strings into tag values. It is required when using object values with TagsInputInput.
Details

Declared type

((value: string) => AcceptableInputValue) | undefined

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

displayValue
((value: AcceptableInputValue) => string) | undefined
—
Converts a tag value to display text, for example when rendering object values or adding a display suffix.
Details

Declared type

((value: AcceptableInputValue) => string) | undefined

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

asChild
boolean | undefined
—
Merges the component props and interaction behavior into its single child, which replaces the default rendered element.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

as
AsTag | Component | undefined
—
Selects the HTML tag or Vue component rendered for this tags-input part; asChild takes precedence when both are set.
Details

Declared type

AsTag | Component | undefined

Literal values

  • "a"
  • "button"
  • "div"
  • "form"
  • "h2"
  • "h3"
  • "img"
  • "input"
  • "label"
  • "li"
  • "nav"
  • "ol"
  • "p"
  • "span"
  • "svg"
  • "template"
  • "ul"

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

name
string | undefined
—
The form field name used when this tags input is submitted with its owning form.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

required
boolean | undefined
—
Marks the tags input as required before its owning form can be submitted.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

class
string | undefined
—
Additional CSS classes applied to the tags-input root container.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

TagsInput.vue:7

packages/ui/src/components/tags-input/TagsInput.vue

ariaLabel
string | undefined
—
The accessible name of the tags-input group. When omitted, the localized tagsInput.label text is used.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

TagsInput.vue:7

packages/ui/src/components/tags-input/TagsInput.vue

TagsInput — Events
NameSignature or typeDescription
@update:modelValue
[payload: AcceptableInputValue[]]
Emits the updated tag array when the list changes so a controlled v-model can be synchronized.
Details

Declared type

[payload: AcceptableInputValue[]]

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

@invalid
[payload: AcceptableInputValue]
Emits the rejected tag value when an addition is a duplicate or would exceed max.
Details

Declared type

[payload: AcceptableInputValue]

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

@addTag
[payload: AcceptableInputValue]
Emits the newly added value after a tag is successfully added.
Details

Declared type

[payload: AcceptableInputValue]

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

@removeTag
[payload: AcceptableInputValue]
Emits the removed value after a tag is successfully removed.
Details

Declared type

[payload: AcceptableInputValue]

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

TagsInput — Slots
NameSignature or typeDescription
#default
{}
Composes the tag items and input field. The slot scope exposes modelValue; it usually contains TagsInputItem and TagsInputInput.
Details

Declared type

{}

Source

TagsInput.vue

packages/ui/src/components/tags-input/TagsInput.vue

TagsInputInput

TagsInputInput — Props
NameTypeDefaultDescription
placeholder
string | undefined
—
Placeholder text shown while the input is empty.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

TagsInputInput.vue

packages/ui/src/components/tags-input/TagsInputInput.vue

autoFocus
boolean | undefined
—
Moves focus to the input when the component mounts.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInputInput.vue

packages/ui/src/components/tags-input/TagsInputInput.vue

maxLength
number | undefined
—
Limits the number of characters that can be entered in the input.
Details

Declared type

number | undefined

Default value details

Not declared
—

Source

TagsInputInput.vue

packages/ui/src/components/tags-input/TagsInputInput.vue

asChild
boolean | undefined
—
Merges the component props and interaction behavior into its single child, which replaces the default rendered element.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInputInput.vue

packages/ui/src/components/tags-input/TagsInputInput.vue

as
AsTag | Component | undefined
—
Selects the HTML tag or Vue component rendered for this tags-input part; asChild takes precedence when both are set.
Details

Declared type

AsTag | Component | undefined

Literal values

  • "a"
  • "button"
  • "div"
  • "form"
  • "h2"
  • "h3"
  • "img"
  • "input"
  • "label"
  • "li"
  • "nav"
  • "ol"
  • "p"
  • "span"
  • "svg"
  • "template"
  • "ul"

Default value details

Not declared
—

Source

TagsInputInput.vue

packages/ui/src/components/tags-input/TagsInputInput.vue

class
string | undefined
—
Additional CSS classes applied to the native tags-input field.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

TagsInputInput.vue:10

packages/ui/src/components/tags-input/TagsInputInput.vue

TagsInputItem

TagsInputItem — Props
NameTypeDefaultDescription
variant
"accent" | "danger" | "default" | "primary" | "secondary" | "success" | undefined
"primary"
Sets the color variant for an individual tag.
Details

Declared type

NonNullable<"default" | "primary" | "secondary" | "success" | "danger" | "accent" | null | undefined> | undefined

Literal values

  • "accent"
  • "danger"
  • "default"
  • "primary"
  • "secondary"
  • "success"

Default value details

Resolved value
"primary"

Source

TagsInputItem.vue:15

packages/ui/src/components/tags-input/TagsInputItem.vue

class
string | undefined
undefined
Additional CSS classes applied to the individual tag container.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

TagsInputItem.vue:16

packages/ui/src/components/tags-input/TagsInputItem.vue

value
Required
AcceptableInputValue
—
The value represented by this tag, which must match an item in the root tag list.
Details

Declared type

AcceptableInputValue

Default value details

Not declared
—

Source

TagsInputItem.vue

packages/ui/src/components/tags-input/TagsInputItem.vue

disabled
boolean | undefined
—
Prevents interaction with this tag.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInputItem.vue

packages/ui/src/components/tags-input/TagsInputItem.vue

asChild
boolean | undefined
—
Merges the component props and interaction behavior into its single child, which replaces the default rendered element.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInputItem.vue

packages/ui/src/components/tags-input/TagsInputItem.vue

as
AsTag | Component | undefined
—
Selects the HTML tag or Vue component rendered for this tags-input part; asChild takes precedence when both are set.
Details

Declared type

AsTag | Component | undefined

Literal values

  • "a"
  • "button"
  • "div"
  • "form"
  • "h2"
  • "h3"
  • "img"
  • "input"
  • "label"
  • "li"
  • "nav"
  • "ol"
  • "p"
  • "span"
  • "svg"
  • "template"
  • "ul"

Default value details

Not declared
—

Source

TagsInputItem.vue

packages/ui/src/components/tags-input/TagsInputItem.vue

TagsInputItem — Slots
NameSignature or typeDescription
#default
{}
Renders the tag item content, commonly TagsInputItemText and TagsInputItemDelete.
Details

Declared type

{}

Source

TagsInputItem.vue

packages/ui/src/components/tags-input/TagsInputItem.vue

TagsInputItemDelete

TagsInputItemDelete — Props
NameTypeDefaultDescription
class
string | undefined
undefined
Additional CSS classes applied to the tag delete button.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

TagsInputItemDelete.vue:14

packages/ui/src/components/tags-input/TagsInputItemDelete.vue

ariaLabel
string | undefined
undefined
The delete button’s accessible name. When omitted, the localized default delete text is used.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

TagsInputItemDelete.vue:15

packages/ui/src/components/tags-input/TagsInputItemDelete.vue

type
"button" | "submit" | "reset" | undefined
"button"
Sets the native button type. The default button value avoids accidental form submission.
Details

Declared type

"button" | "submit" | "reset" | undefined

Literal values

  • "button"
  • "reset"
  • "submit"

Default value details

Resolved value
"button"

Source

TagsInputItemDelete.vue:16

packages/ui/src/components/tags-input/TagsInputItemDelete.vue

asChild
boolean | undefined
—
Merges the component props and interaction behavior into its single child, which replaces the default rendered element.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInputItemDelete.vue

packages/ui/src/components/tags-input/TagsInputItemDelete.vue

as
AsTag | Component | undefined
—
Selects the HTML tag or Vue component rendered for this tags-input part; asChild takes precedence when both are set.
Details

Declared type

AsTag | Component | undefined

Literal values

  • "a"
  • "button"
  • "div"
  • "form"
  • "h2"
  • "h3"
  • "img"
  • "input"
  • "label"
  • "li"
  • "nav"
  • "ol"
  • "p"
  • "span"
  • "svg"
  • "template"
  • "ul"

Default value details

Not declared
—

Source

TagsInputItemDelete.vue

packages/ui/src/components/tags-input/TagsInputItemDelete.vue

TagsInputItemDelete — Slots
NameSignature or typeDescription
#default
{}
Customizes the delete button content; an X icon is shown when omitted.
Details

Declared type

{}

Source

TagsInputItemDelete.vue

packages/ui/src/components/tags-input/TagsInputItemDelete.vue

TagsInputItemText

TagsInputItemText — Props
NameTypeDefaultDescription
asChild
boolean | undefined
—
Merges the component props and interaction behavior into its single child, which replaces the default rendered element.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Not declared
—

Source

TagsInputItemText.vue

packages/ui/src/components/tags-input/TagsInputItemText.vue

as
AsTag | Component | undefined
—
Selects the HTML tag or Vue component rendered for this tags-input part; asChild takes precedence when both are set.
Details

Declared type

AsTag | Component | undefined

Literal values

  • "a"
  • "button"
  • "div"
  • "form"
  • "h2"
  • "h3"
  • "img"
  • "input"
  • "label"
  • "li"
  • "nav"
  • "ol"
  • "p"
  • "span"
  • "svg"
  • "template"
  • "ul"

Default value details

Not declared
—

Source

TagsInputItemText.vue

packages/ui/src/components/tags-input/TagsInputItemText.vue

class
string | undefined
—
Additional CSS classes applied to the tag text element.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

TagsInputItemText.vue:10

packages/ui/src/components/tags-input/TagsInputItemText.vue

TagsInputItemText — Slots
NameSignature or typeDescription
#default
{}
Renders the text content of the tag.
Details

Declared type

{}

Source

TagsInputItemText.vue

packages/ui/src/components/tags-input/TagsInputItemText.vue

Accessibility ​

  • ARIA Attributes: TagsInput provides aria-label via locale by default (e.g., "Tags Input" in English); falls back to t('tagsInput.label') when not provided
  • Custom Labels: When a more specific description is needed (e.g., "Article tags", "Recipients"), use the ariaLabel prop to customize
vue
<script setup>
import { ref } from 'vue'
import {
    TagsInput,
    TagsInputInput,
    TagsInputItem,
    TagsInputItemText,
    TagsInputItemDelete
} from 'brutx-ui-vue'

const tags = ref(['vue', 'css'])
</script>

<template>
    <TagsInput v-model="tags" aria-label="Article tags">
        <TagsInputItem v-for="tag in tags" :key="tag" :value="tag">
            <TagsInputItemText>{{ tag }}</TagsInputItemText>
            <TagsInputItemDelete />
        </TagsInputItem>
        <TagsInputInput placeholder="Add tag..." />
    </TagsInput>
</template>

FAQ ​

Q: How do I use objects as tag values instead of strings?

A: When tag values are objects, you must provide a convertValue function to convert the input string to the target object type. It is also recommended to provide a displayValue function to customize the tag display text. If convertValue is not provided, the component will use strings as tag values.

Q: Why doesn't adding a tag work after setting the max attribute?

A: When the number of tags reaches the max limit, new tags will not be added and the invalid event will be triggered. You can listen to this event to display a message to the user. If max is set to 0, there is no limit on the number of tags.

Q: How do I automatically split multiple tags on paste?

A: Set addOnPaste to true, and text containing delimiters will be automatically split into multiple tags when pasted. The default delimiter is a comma (,), which can be customized via the delimiter prop (supports strings and regular expressions). For example, set delimiter=";" to split by semicolons.

Brute force builds.