Tags Input

PohonGitHub
An input element that displays interactive tags.
Apple
Banana
<script setup lang="ts">
import { ATagsInputInput, ATagsInputItem, ATagsInputItemDelete, ATagsInputItemText, ATagsInputRoot } from 'akar';
import { ref } from 'vue';

const modelValue = ref(['Apple', 'Banana']);
</script>

<template>
  <ATagsInputRoot
    v-model="modelValue"
    class="text-sm color-text-highlighted px-2.5 py-1.5 rounded-md bg-background inline-flex flex-wrap gap-1.5 ring ring-ring-accented ring-inset transition-colors-280 items-center relative has-focus-visible:(ring-2 ring-primary ring-inset)"
  >
    <ATagsInputItem
      v-for="item in modelValue"
      :key="item"
      :value="item"
      class="text-xs color-text font-medium px-1.5 py-0.5 rounded-sm bg-background-elevated inline-flex gap-0.5 wrap-anywhere ring ring-ring-accented ring-inset items-center data-[state='active']:bg-background-accented data-[disabled]:(opacity-75 cursor-not-allowed)"
    >
      <ATagsInputItemText />
      <ATagsInputItemDelete class="color-text-dimmed rounded-xs inline-flex transition-colors-280 items-center hover:(color-text bg-background-accented/75) disabled:pointer-events-none">
        <i class="i-lucide:x shrink-0 size-3.5" />
      </ATagsInputItemDelete>
    </ATagsInputItem>

    <ATagsInputInput
      placeholder="Fruits..."
      class="border-0 bg-transparent flex-1 placeholder:color-text-dimmed focus:outline-none disabled:(opacity-75 cursor-not-allowed)"
    />
  </ATagsInputRoot>
</template>

Features

  • Can be controlled or uncontrolled.
  • Full keyboard navigation.
  • Limit the number of tags.
  • Accept value from clipboard.
  • Clear button to reset all tags values.

Anatomy

Import all parts and piece them together.

<script setup>
import { ATagsInputClear, ATagsInputInput, ATagsInputItem, ATagsInputItemDelete, ATagsInputItemText, ATagsInputRoot } from 'akar';
</script>

<template>
  <ATagsInputRoot>
    <ATagsInputItem>
      <ATagsInputItemText />
      <ATagsInputItemDelete />
    </ATagsInputItem>

    <ATagsInputInput />
    <ATagsInputClear />
  </ATagsInputRoot>
</template>

Pohon

One benefit of using Akar is its flexibility and low-level control over the components. However, this also means that you may need to manually construct more complex UI elements by combining multiple Akar components together.

If you feel there's a lot of elements that needs to be constructed manually using Akar, consider using Pohon UI instead. It provides a higher-level abstraction over Akar components with pre-defined styles and behaviors that can help you build UIs faster.

API Reference

Root

Contains all the tags input component parts.

Props

Prop Default Type
as'div'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

addOnBlurboolean

When true allow adding tags blur input

addOnPasteboolean

When true, allow adding tags on paste. Work in conjunction with delimiter prop.

addOnTabboolean

When true allow adding tags on tab keydown

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

convertValue((value: string) => AcceptableInputValue)

Convert the input value to the desired type. Mandatory when using objects as values and using ATagsInputInput

defaultValue[]AcceptableInputValue[]

The value of the tags that should be added. Use when you do not need to control the state of the tags input

delimiter','string | RegExp

The character or regular expression to trigger the addition of a new tag. Also used to split tags for @paste event

dir'ltr' | 'rtl'

The reading direction of the combobox when applicable.
If omitted, inherits globally from AConfigProvider or assumes LTR (left-to-right) reading mode.

disabledboolean

When true, prevents the user from interacting with the tags input.

displayValuevalue.toString()((value: AcceptableInputValue) => string)

Display the value of the tag. Useful when you want to apply modifications to the value like adding a suffix or when using object as values

duplicateboolean

When true, allow duplicated tags.

idstring
max0number

Maximum number of tags.

modelValueAcceptableInputValue[] | null
namestring

The name of the field. Submitted with its owning form as part of a name/value pair.

requiredboolean

When true, indicates that the user must set the value before the owning form can be submitted.

Emits

Event Type
addTag[payload: AcceptableInputValue]

Event handler called when tag is added

invalid[payload: AcceptableInputValue]

Event handler called when the value is invalid

removeTag[payload: AcceptableInputValue]

Event handler called when tag is removed

update:modelValue[payload: AcceptableInputValue[]]

Event handler called when the value changes

Slots

Slot Type
modelValuestring | Record<string, any>

The controlled value of the tags input. Can be bind as v-model.

Data Attributes

Attribute Value
[data-disabled]Present when disabled
[data-focused]Present when focus on input
[data-invalid]Present when input value is invalid

Item

The component that contains the tag.

Props

Prop Default Type
as'div'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

disabledboolean

When true, prevents the user from interacting with the tags input.

value*string | Record<string, any>

Value associated with the tags

Data Attributes

Attribute Value
[data-state]'active' | 'inactive'
[data-disabled]Present when disabled

ItemText

The textual part of the tag. Important for accessibility.

Props

Prop Default Type
as'span'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

ItemDelete

The button that delete the associate tag.

Props

Prop Default Type
as'button'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Data Attributes

Attribute Value
[data-state]'active' | 'inactive'
[data-disabled]Present when disabled

Input

The input element for the tags input.

Props

Prop Default Type
as'input'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

autoFocusboolean

Focus on element when mounted.

maxLengthnumber

Maximum number of character allowed.

placeholderstring

The placeholder character to use for empty tags input.

Data Attributes

Attribute Value
[data-invalid]Present when input value is invalid

Clear

The button that remove all tags.

Props

Prop Default Type
as'button'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Data Attributes

Attribute Value
[data-disabled]Present when disabled

Examples

Paste behavior

You can automatically add tags on paste by passing the add-on-paste prop.

<script setup lang="ts">
import { ATagsInputRoot } from 'akar';
</script>

<template>
  <ATagsInputRoot
    v-model="modelValue"
    add-on-paste
  >
  </ATagsInputRoot>
</template>

Multiple delimiters

You can pass RegExp as delimiter to allow multiple characters to trigger addition of a new tag. When add-on-paste is passed it will be also used to split tags for @paste event.

<script setup lang="ts">
import { ATagsInputInput, ATagsInputItem, ATagsInputItemDelete, ATagsInputItemText, ATagsInputRoot } from 'akar';

// split by space, comma, semicolon, tab, or newline
const delimiter = /[ ,;\t\n\r]+/;
</script>

<template>
  <ATagsInputRoot
    v-model="modelValue"
    :delimiter="delimiter"
    add-on-paste
  >
  </ATagsInputRoot>
</template>

Accessibility

Keyboard Interactions

Key Description
Delete

When tag is active, remove it and set the tag on right active.

Backspace

When tag is active, remove it and set the tag on left active. If there are no tags to the left, either the next tags gets focus, or the input.

ArrowRight

Set the next tag active.

ArrowLeft

Set the previous tag active.

Home

Set the first tag active.

End

Set the last tag active.