# Tags Input

URL: https://ark-ui.com/docs/components/tags-input
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/tags-input.mdx

A component that allows users to add tags to an input field.

---

<ComponentPreview id="TagsInput" />

## Anatomy

To set up the tags input correctly, you'll need to understand its anatomy and how we name its parts.

> Each part includes a `data-part` attribute to help identify them in the DOM.

<Anatomy id="tags-input" />

## Examples

Learn how to use the `TagsInput` component in your project. Let's take a look at the most basic example:

**Example: basic**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const Basic = () => {
  return (
    <TagsInput.Root>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Add Framework" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const Basic = () => (
  <TagsInput.Root>
    <TagsInput.Context>
      {(api) => (
        <>
          <TagsInput.Label>Frameworks</TagsInput.Label>
          <TagsInput.Control>
            <Index each={api().value}>
              {(value, index) => (
                <TagsInput.Item index={index} value={value()}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              )}
            </Index>
            <TagsInput.Input placeholder="Add Framework" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </TagsInput.Control>
        </>
      )}
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root>
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root>
  <TagsInput.Label>Frameworks</TagsInput.Label>
  <TagsInput.Control>
    <TagsInput.Context>
      {#snippet render(tags)}
        {#each tags().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      {/snippet}
    </TagsInput.Context>
    <TagsInput.Input placeholder="Add Framework" />
  </TagsInput.Control>
  <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Initial tags

To set the initial tag values, set the `defaultValue` prop.

**Example: initial-value**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const InitialValue = () => {
  return (
    <TagsInput.Root defaultValue={['React', 'Solid', 'Vue', 'Svelte']}>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Add tag" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const InitialValue = () => {
  return (
    <TagsInput.Root value={['React', 'Solid', 'Vue', 'Svelte']}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add tag" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </TagsInput.Control>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
import { ref } from 'vue'

const frameworks = ref(['React', 'Solid', 'Vue', 'Svelte'])
</script>

<template>
  <TagsInput.Root v-model="frameworks">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root value={['React', 'Svelte']}>
  <TagsInput.Label>Frameworks</TagsInput.Label>
  <TagsInput.Control>
    <TagsInput.Context>
      {#snippet render(tags)}
        {#each tags().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      {/snippet}
    </TagsInput.Context>
    <TagsInput.Input placeholder="Add Framework" />
  </TagsInput.Control>
  <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Max Tags

To limit the number of tags within the component, you can set the `max` property to the limit you want. The default
value is `Infinity`.

When the tag reaches the limit, new tags cannot be added except the `allowOverflow` prop is set to `true`.

**Example: max-with-overflow**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const MaxWithOverflow = () => {
  return (
    <TagsInput.Root max={3} allowOverflow>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Add Framework" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const MaxWithOverflow = () => {
  return (
    <TagsInput.Root max={3} allowOverflow>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </TagsInput.Control>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root :max="3" allowOverflow>
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root max={3} allowOverflow>
  <TagsInput.Label>Frameworks (Max 3, Overflow Allowed)</TagsInput.Label>
  <TagsInput.Control>
    <TagsInput.Context>
      {#snippet render(tags)}
        {#each tags().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      {/snippet}
    </TagsInput.Context>
    <TagsInput.Input placeholder="Add Framework" />
  </TagsInput.Control>
  <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Controlled

Use the `value` and `onValueChange` props to programmatically control the tags input's state. This allows you to manage
the tags array externally and respond to changes.

**Example: controlled**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { useState } from 'react'
import { XIcon } from 'lucide-react'

export const Controlled = () => {
  const [value, setValue] = useState<string[]>(['vue', 'react'])

  return (
    <>
      <p>Values: {value.join(', ')}</p>
      <TagsInput.Root value={value} onValueChange={(details) => setValue(details.value)}>
        <TagsInput.Context>
          {(api) => (
            <>
              <TagsInput.Label>Frameworks</TagsInput.Label>
              <TagsInput.Control>
                {api.value.map((value, index) => (
                  <TagsInput.Item key={index} index={index} value={value}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                ))}
                <TagsInput.Input placeholder="Add Framework" />
                <TagsInput.ClearTrigger>
                  <XIcon />
                </TagsInput.ClearTrigger>
              </TagsInput.Control>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.Root>
    </>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index, createSignal } from 'solid-js'

export const Controlled = () => {
  const [value, setValue] = createSignal<string[]>(['vue', 'react'])

  return (
    <>
      <p>Values: {value().join(', ')}</p>
      <TagsInput.Root value={value()} onValueChange={(details) => setValue(details.value)}>
        <TagsInput.Context>
          {(api) => (
            <>
              <TagsInput.Label>Frameworks</TagsInput.Label>
              <TagsInput.Control>
                <Index each={api().value}>
                  {(value, index) => (
                    <TagsInput.Item index={index} value={value()}>
                      <TagsInput.ItemPreview>
                        <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                        <TagsInput.ItemDeleteTrigger>
                          <XIcon />
                        </TagsInput.ItemDeleteTrigger>
                      </TagsInput.ItemPreview>
                      <TagsInput.ItemInput />
                    </TagsInput.Item>
                  )}
                </Index>
                <TagsInput.Input placeholder="Add Framework" />
                <TagsInput.ClearTrigger>
                  <XIcon />
                </TagsInput.ClearTrigger>
              </TagsInput.Control>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.Root>
    </>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
import { ref } from 'vue'

const value = ref<string[]>(['vue', 'react'])
</script>

<template>
  <p>Values: {{ value }}</p>
  <TagsInput.Root v-model="value">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'

  let value = $state<string[]>(['React', 'Svelte'])
</script>

<TagsInput.Root bind:value>
  <TagsInput.Label>Frameworks</TagsInput.Label>
  <TagsInput.Control>
    <TagsInput.Context>
      {#snippet render(tags)}
        {#each tags().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      {/snippet}
    </TagsInput.Context>
    <TagsInput.Input placeholder="Add Framework" />
  </TagsInput.Control>
  <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
  <TagsInput.HiddenInput />
</TagsInput.Root>

<div style="margin-top: 1rem;">
  <p>Current tags: {value.join(', ')}</p>
</div>

```

### Controlled Input Value

Use the `inputValue` and `onInputValueChange` props to control the text input field independently. This is useful for
clearing the input or pre-filling it programmatically.

**Example: controlled-input-value**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { useState } from 'react'
import { XIcon } from 'lucide-react'

export const ControlledInputValue = () => {
  const [inputValue, setInputValue] = useState('')

  return (
    <div>
      <div style={{ display: 'flex', gap: '8px', marginBottom: '12px' }}>
        <button type="button" onClick={() => setInputValue('React')}>
          Set to "React"
        </button>
        <button type="button" onClick={() => setInputValue('')}>
          Clear Input
        </button>
        <span style={{ fontSize: '14px', marginLeft: '8px' }}>Current input: "{inputValue}"</span>
      </div>

      <TagsInput.Root inputValue={inputValue} onInputValueChange={(details) => setInputValue(details.inputValue)}>
        <TagsInput.Context>
          {(tagsInput) => (
            <>
              <TagsInput.Label>Frameworks</TagsInput.Label>
              <TagsInput.Control>
                {tagsInput.value.map((value, index) => (
                  <TagsInput.Item key={index} index={index} value={value}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                ))}
              </TagsInput.Control>
              <TagsInput.Input placeholder="Add Framework" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.Root>
    </div>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index, createSignal } from 'solid-js'

export const ControlledInputValue = () => {
  const [inputValue, setInputValue] = createSignal('')

  return (
    <div>
      <div style={{ display: 'flex', gap: '8px', 'margin-bottom': '12px' }}>
        <button type="button" onClick={() => setInputValue('React')}>
          Set to "React"
        </button>
        <button type="button" onClick={() => setInputValue('')}>
          Clear Input
        </button>
        <span style={{ 'font-size': '14px', 'margin-left': '8px' }}>Current input: "{inputValue()}"</span>
      </div>

      <TagsInput.Root inputValue={inputValue()} onInputValueChange={(details) => setInputValue(details.inputValue)}>
        <TagsInput.Context>
          {(api) => (
            <>
              <TagsInput.Label>Frameworks</TagsInput.Label>
              <TagsInput.Control>
                <Index each={api().value}>
                  {(value, index) => (
                    <TagsInput.Item index={index} value={value()}>
                      <TagsInput.ItemPreview>
                        <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                        <TagsInput.ItemDeleteTrigger>
                          <XIcon />
                        </TagsInput.ItemDeleteTrigger>
                      </TagsInput.ItemPreview>
                      <TagsInput.ItemInput />
                    </TagsInput.Item>
                  )}
                </Index>
                <TagsInput.Input placeholder="Add Framework" />
                <TagsInput.ClearTrigger>
                  <XIcon />
                </TagsInput.ClearTrigger>
              </TagsInput.Control>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.Root>
    </div>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
import { ref } from 'vue'

const inputValue = ref('')
</script>

<template>
  <div>
    <div style="display: flex; gap: 8px; margin-bottom: 12px">
      <button type="button" @click="inputValue = 'React'">Set to "React"</button>
      <button type="button" @click="inputValue = ''">Clear Input</button>
      <span style="font-size: 14px; margin-left: 8px">Current input: "{{ inputValue }}"</span>
    </div>

    <TagsInput.Root :input-value="inputValue" @input-value-change="(details) => (inputValue = details.inputValue)">
      <TagsInput.Context v-slot="tagsInput">
        <TagsInput.Label>Frameworks</TagsInput.Label>
        <TagsInput.Control>
          <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
          <TagsInput.Input placeholder="Add Framework" />
          <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
        </TagsInput.Control>
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  </div>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'

  let inputValue = $state('')
</script>

<div>
  <div style="display: flex; gap: 8px; margin-bottom: 12px;">
    <button type="button" onclick={() => (inputValue = 'React')}>Set to "React"</button>
    <button type="button" onclick={() => (inputValue = '')}>Clear Input</button>
    <span style="font-size: 14px; margin-left: 8px;">Current input: "{inputValue}"</span>
  </div>

  <TagsInput.Root bind:inputValue>
    <TagsInput.Label>Frameworks</TagsInput.Label>
    <TagsInput.Control>
      <TagsInput.Context>
        {#snippet render(tags)}
          {#each tags().value as value, index (index)}
            <TagsInput.Item {index} {value}>
              <TagsInput.ItemPreview>
                <TagsInput.ItemText>{value}</TagsInput.ItemText>
                <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
              </TagsInput.ItemPreview>
              <TagsInput.ItemInput />
            </TagsInput.Item>
          {/each}
        {/snippet}
      </TagsInput.Context>
      <TagsInput.Input placeholder="Add Framework" />
    </TagsInput.Control>
    <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</div>

```

### Custom Delimiter

Use the `delimiter` prop with a regex pattern to specify multiple characters that can separate tags. By default, only
the Enter key creates tags.

**Example: delimiter**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

const DELIMITER_PATTERN = /[,;\s]/

export const Delimiter = () => {
  return (
    <TagsInput.Root delimiter={DELIMITER_PATTERN}>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks (separate with comma, semicolon, or space)</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Type and use comma, semicolon, or space" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

const DELIMITER_PATTERN = /[,;\s]/

export const Delimiter = () => (
  <TagsInput.Root delimiter={DELIMITER_PATTERN}>
    <TagsInput.Context>
      {(api) => (
        <>
          <TagsInput.Label>Frameworks (separate with comma, semicolon, or space)</TagsInput.Label>
          <TagsInput.Control>
            <Index each={api().value}>
              {(value, index) => (
                <TagsInput.Item index={index} value={value()}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              )}
            </Index>
            <TagsInput.Input placeholder="Type and use comma, semicolon, or space" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </TagsInput.Control>
        </>
      )}
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'

const DELIMITER_PATTERN = /[,;\s]/
</script>

<template>
  <TagsInput.Root :delimiter="DELIMITER_PATTERN">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks (separate with comma, semicolon, or space)</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Type and use comma, semicolon, or space" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'

  const DELIMITER_PATTERN = /[,;\s]/
</script>

<TagsInput.Root delimiter={DELIMITER_PATTERN}>
  <TagsInput.Label>Frameworks (separate with comma, semicolon, or space)</TagsInput.Label>
  <TagsInput.Control>
    <TagsInput.Context>
      {#snippet render(tags)}
        {#each tags().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      {/snippet}
    </TagsInput.Context>
    <TagsInput.Input placeholder="Type and use comma, semicolon, or space" />
  </TagsInput.Control>
  <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Disabled

Use the `disabled` prop to make the tags input non-interactive. Users won't be able to add, remove, or edit tags.

**Example: disabled**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const Disabled = () => {
  return (
    <TagsInput.Root defaultValue={['React', 'Solid', 'Vue']} disabled>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks (Disabled)</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Cannot interact when disabled" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const Disabled = () => (
  <TagsInput.Root defaultValue={['React', 'Solid', 'Vue']} disabled>
    <TagsInput.Context>
      {(api) => (
        <>
          <TagsInput.Label>Frameworks (Disabled)</TagsInput.Label>
          <TagsInput.Control>
            <Index each={api().value}>
              {(value, index) => (
                <TagsInput.Item index={index} value={value()}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              )}
            </Index>
            <TagsInput.Input placeholder="Cannot interact when disabled" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </TagsInput.Control>
        </>
      )}
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root :default-value="['React', 'Solid', 'Vue']" disabled>
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks (Disabled)</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Cannot interact when disabled" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root defaultValue={['React', 'Solid', 'Vue']} disabled>
  <TagsInput.Label>Frameworks (Disabled)</TagsInput.Label>
  <TagsInput.Control>
    <TagsInput.Context>
      {#snippet render(tags)}
        {#each tags().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      {/snippet}
    </TagsInput.Context>
    <TagsInput.Input placeholder="Cannot interact when disabled" />
  </TagsInput.Control>
  <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Invalid

Use the `invalid` prop to mark the tags input as invalid for form validation purposes.

**Example: invalid**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const Invalid = () => {
  return (
    <TagsInput.Root invalid>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Add Framework" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const Invalid = () => (
  <TagsInput.Root invalid>
    <TagsInput.Context>
      {(api) => (
        <>
          <TagsInput.Label>Frameworks</TagsInput.Label>
          <TagsInput.Control>
            <Index each={api().value}>
              {(value, index) => (
                <TagsInput.Item index={index} value={value()}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              )}
            </Index>
            <TagsInput.Input placeholder="Add Framework" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </TagsInput.Control>
        </>
      )}
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root invalid>
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root invalid>
  <TagsInput.Label>Frameworks</TagsInput.Label>
  <TagsInput.Control>
    <TagsInput.Context>
      {#snippet render(tags)}
        {#each tags().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      {/snippet}
    </TagsInput.Context>
    <TagsInput.Input placeholder="Add Framework" />
  </TagsInput.Control>
  <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Max Tag Length

Use the `maxLength` prop to limit the number of characters allowed per tag. This prevents users from creating overly
long tags.

**Example: max-tag-length**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const MaxTagLength = () => {
  return (
    <TagsInput.Root maxLength={10}>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks (max 10 characters per tag)</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Max 10 characters" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const MaxTagLength = () => (
  <TagsInput.Root maxLength={10}>
    <TagsInput.Context>
      {(api) => (
        <>
          <TagsInput.Label>Frameworks (max 10 characters per tag)</TagsInput.Label>
          <TagsInput.Control>
            <Index each={api().value}>
              {(value, index) => (
                <TagsInput.Item index={index} value={value()}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              )}
            </Index>
            <TagsInput.Input placeholder="Max 10 characters" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </TagsInput.Control>
        </>
      )}
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root :max-length="10">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks (max 10 characters per tag)</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Max 10 characters" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root maxLength={10}>
  <TagsInput.Label>Frameworks (max 10 characters per tag)</TagsInput.Label>
  <TagsInput.Control>
    <TagsInput.Context>
      {#snippet render(tags)}
        {#each tags().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      {/snippet}
    </TagsInput.Context>
    <TagsInput.Input placeholder="Max 10 characters" />
  </TagsInput.Control>
  <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Programmatic Control

Use the `useTagsInput` hook with `RootProvider` to access the component's API methods like `addValue()`, `setValue()`,
and `clearValue()` for full programmatic control.

**Example: programmatic-control**

#### React

```tsx
import { TagsInput, useTagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const ProgrammaticControl = () => {
  const tagsInput = useTagsInput()

  return (
    <>
      <div style={{ display: 'flex', gap: '8px', marginBottom: '12px' }}>
        <button type="button" onClick={() => tagsInput.addValue('React')}>
          Add React
        </button>
        <button type="button" onClick={() => tagsInput.addValue('Solid')}>
          Add Solid
        </button>
        <button type="button" onClick={() => tagsInput.setValue(['Vue', 'Svelte'])}>
          Set to Vue & Svelte
        </button>
        <button type="button" onClick={() => tagsInput.clearValue()}>
          Clear All
        </button>
      </div>

      <TagsInput.RootProvider value={tagsInput}>
        <TagsInput.Context>
          {(api) => (
            <>
              <TagsInput.Label>Frameworks (Programmatic Control)</TagsInput.Label>
              <TagsInput.Control>
                {api.value.map((value, index) => (
                  <TagsInput.Item key={index} index={index} value={value}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                ))}
              </TagsInput.Control>
              <TagsInput.Input placeholder="Add Framework" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.RootProvider>
    </>
  )
}

```

#### Solid

```tsx
import { TagsInput, useTagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const ProgrammaticControl = () => {
  const tagsInput = useTagsInput()

  return (
    <>
      <div style={{ display: 'flex', gap: '8px', 'margin-bottom': '12px' }}>
        <button type="button" onClick={() => tagsInput().addValue('React')}>
          Add React
        </button>
        <button type="button" onClick={() => tagsInput().addValue('Solid')}>
          Add Solid
        </button>
        <button type="button" onClick={() => tagsInput().setValue(['Vue', 'Svelte'])}>
          Set to Vue & Svelte
        </button>
        <button type="button" onClick={() => tagsInput().clearValue()}>
          Clear All
        </button>
      </div>

      <TagsInput.RootProvider value={tagsInput}>
        <TagsInput.Context>
          {(api) => (
            <>
              <TagsInput.Label>Frameworks (Programmatic Control)</TagsInput.Label>
              <TagsInput.Control>
                <Index each={api().value}>
                  {(value, index) => (
                    <TagsInput.Item index={index} value={value()}>
                      <TagsInput.ItemPreview>
                        <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                        <TagsInput.ItemDeleteTrigger>
                          <XIcon />
                        </TagsInput.ItemDeleteTrigger>
                      </TagsInput.ItemPreview>
                      <TagsInput.ItemInput />
                    </TagsInput.Item>
                  )}
                </Index>
                <TagsInput.Input placeholder="Add Framework" />
                <TagsInput.ClearTrigger>
                  <XIcon />
                </TagsInput.ClearTrigger>
              </TagsInput.Control>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.RootProvider>
    </>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput, useTagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'

const tagsInput = useTagsInput()
</script>

<template>
  <div>
    <div style="display: flex; gap: 8px; margin-bottom: 12px">
      <button type="button" @click="tagsInput.addValue('React')">Add React</button>
      <button type="button" @click="tagsInput.addValue('Solid')">Add Solid</button>
      <button type="button" @click="tagsInput.setValue(['Vue', 'Svelte'])">Set to Vue & Svelte</button>
      <button type="button" @click="tagsInput.clearValue()">Clear All</button>
    </div>

    <TagsInput.RootProvider :value="tagsInput">
      <TagsInput.Context v-slot="api">
        <TagsInput.Label>Frameworks (Programmatic Control)</TagsInput.Label>
        <TagsInput.Control>
          <TagsInput.Item v-for="(value, index) in api.value" :key="index" :index="index" :value="value">
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
          <TagsInput.Input placeholder="Add Framework" />
          <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
        </TagsInput.Control>
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.RootProvider>
  </div>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput, useTagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'

  const tags = useTagsInput()
</script>

<div>
  <div style="display: flex; gap: 8px; margin-bottom: 12px;">
    <button type="button" onclick={() => tags().addValue('React')}>Add React</button>
    <button type="button" onclick={() => tags().addValue('Solid')}>Add Solid</button>
    <button type="button" onclick={() => tags().setValue(['Vue', 'Svelte'])}>Set to Vue & Svelte</button>
    <button type="button" onclick={() => tags().clearValue()}>Clear All</button>
  </div>

  <TagsInput.RootProvider value={tags}>
    <TagsInput.Label>Frameworks (Programmatic Control)</TagsInput.Label>
    <TagsInput.Control>
      {#each tags().value as value, index (index)}
        <TagsInput.Item {index} {value}>
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{value}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
      {/each}
      <TagsInput.Input placeholder="Add Framework" />
    </TagsInput.Control>
    <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
    <TagsInput.HiddenInput />
  </TagsInput.RootProvider>
</div>

```

### Read-only

Use the `readOnly` prop to make tags visible but not editable. Users can view tags but cannot add, remove, or modify
them.

**Example: readonly**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const Readonly = () => {
  return (
    <TagsInput.Root defaultValue={['React', 'Solid', 'Vue']} readOnly>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks (Read-only)</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Cannot add tags in read-only mode" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const Readonly = () => (
  <TagsInput.Root defaultValue={['React', 'Solid', 'Vue']} readOnly>
    <TagsInput.Context>
      {(api) => (
        <>
          <TagsInput.Label>Frameworks (Read-only)</TagsInput.Label>
          <TagsInput.Control>
            <Index each={api().value}>
              {(value, index) => (
                <TagsInput.Item index={index} value={value()}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              )}
            </Index>
            <TagsInput.Input placeholder="Cannot add tags in read-only mode" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </TagsInput.Control>
        </>
      )}
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root :default-value="['React', 'Solid', 'Vue']" read-only>
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks (Read-only)</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Cannot add tags in read-only mode" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root defaultValue={['React', 'Solid', 'Vue']} readOnly>
  <TagsInput.Label>Frameworks (Read-only)</TagsInput.Label>
  <TagsInput.Control>
    <TagsInput.Context>
      {#snippet render(tags)}
        {#each tags().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      {/snippet}
    </TagsInput.Context>
    <TagsInput.Input placeholder="Cannot add tags in read-only mode" />
  </TagsInput.Control>
  <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Validating Tags

Before a tag is added, the `validate` function is called to determine whether to accept or reject a tag.

A common use-case for validating tags is preventing duplicates or validating the data type.

**Example: validation**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

const TAG_PATTERN = /^[a-zA-Z0-9-]+$/

const validateTag = (details: { value: string[]; inputValue: string }) => {
  const { value, inputValue } = details

  if (!inputValue || inputValue.trim() === '') {
    return false
  }

  if (value.includes(inputValue)) {
    return false
  }

  if (inputValue.length < 3) {
    return false
  }

  if (!TAG_PATTERN.test(inputValue)) {
    return false
  }

  return true
}

export const Validation = () => {
  return (
    <TagsInput.Root validate={validateTag}>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework (min 3 chars, alphanumeric)" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </TagsInput.Control>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const Validation = () => {
  return (
    <TagsInput.Root
      validate={(details) => {
        return !details.value.includes(details.inputValue)
      }}
    >
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </TagsInput.Control>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root
    :validate="
      (details) => {
        return !details.value.includes(details.inputValue)
      }
    "
  >
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root
  validate={(details) => {
    return !details.value.includes(details.inputValue)
  }}
>
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      </TagsInput.Control>
      <TagsInput.Input placeholder="Add Framework" />
      <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
    {/snippet}
  </TagsInput.Context>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Blur behavior

When the tags input is blurred, you can configure the action the component should take by passing the `blurBehavior`
prop.

- `add` — Adds the tag to the list of tags.
- `clear` — Clears the tags input value.

**Example: blur-behavior**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const BlurBehavior = () => {
  return (
    <TagsInput.Root blurBehavior="add">
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Add Framework" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const BlurBehavior = () => {
  return (
    <TagsInput.Root blurBehavior="add">
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </TagsInput.Control>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root blurBehavior="add">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root blurBehavior="add">
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      </TagsInput.Control>
      <TagsInput.Input placeholder="Add Framework" />
      <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
    {/snippet}
  </TagsInput.Context>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Paste behavior

To add a tag when a arbitrary value is pasted in the input element, pass the `addOnPaste` prop.

When a value is pasted, the component will:

- check if the value is a valid tag based on the `validate` option
- split the value by the `delimiter` option passed

**Example: paste-behavior**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const PasteBehavior = () => {
  return (
    <TagsInput.Root addOnPaste delimiter=",">
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Add Framework" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const PasteBehavior = () => {
  return (
    <TagsInput.Root addOnPaste delimiter=",">
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </TagsInput.Control>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root addOnPaste delimiter=",">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root addOnPaste delimiter=",">
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      </TagsInput.Control>
      <TagsInput.Input placeholder="Add Framework" />
      <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
    {/snippet}
  </TagsInput.Context>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Disable tag editing

by default the tags can be edited by double-clicking on the tag or focusing on them and pressing

<kbd>Enter</kbd>. To disable this behavior, pass `editable={false}`

**Example: disabled-editing**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const DisabledEditing = () => {
  return (
    <TagsInput.Root editable={false}>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Add Framework" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const DisabledEditing = () => {
  return (
    <TagsInput.Root editable={false}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </TagsInput.Control>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root :allowEditTag="false">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root value={['React', 'Svelte', 'Vue']} editable={false}>
  <TagsInput.Label>Frameworks (Read-only)</TagsInput.Label>
  <TagsInput.Control>
    <TagsInput.Context>
      {#snippet render(tags)}
        {#each tags().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      {/snippet}
    </TagsInput.Context>
    <TagsInput.Input placeholder="Add Framework" />
  </TagsInput.Control>
  <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Events

During the lifetime of the tags input interaction, here's a list of events we emit:

- `onValueChange` — invoked when the tag value changes.
- `onHighlightChange` — invoked when a tag has visual focus.
- `onValueInvalid` — invoked when the max tag count is reached or the `validate` function returns `false`.

**Example: on-event**

#### React

```tsx
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const OnEvent = () => {
  return (
    <TagsInput.Root
      onValueChange={(details) => {
        console.log('tags changed to:', details.value)
      }}
      onHighlightChange={(details) => {
        console.log('highlighted tag:', details.highlightedValue)
      }}
      onValueInvalid={(details) => {
        console.log('Invalid!', details.reason)
      }}
      max={3}
      allowOverflow
      validate={(details) => {
        return !details.value.includes(details.inputValue)
      }}
    >
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value}>
                  <TagsInput.ItemPreview>
                    <TagsInput.ItemText>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput />
                </TagsInput.Item>
              ))}
            </TagsInput.Control>
            <TagsInput.Input placeholder="Add Framework" />
            <TagsInput.ClearTrigger>
              <XIcon />
            </TagsInput.ClearTrigger>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Solid

```tsx
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const OnEvent = () => {
  return (
    <TagsInput.Root
      onValueChange={(details) => {
        console.log('tags changed to:', details.value)
      }}
      onHighlightChange={(details) => {
        console.log('highlighted tag:', details.highlightedValue)
      }}
      onValueInvalid={(details) => {
        console.log('Invalid!', details.reason)
      }}
      max={3}
      allowOverflow
      validate={(details) => {
        return !details.value.includes(details.inputValue)
      }}
    >
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label>Frameworks</TagsInput.Label>
            <TagsInput.Control>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </TagsInput.Control>
          </>
        )}
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'
</script>

<template>
  <TagsInput.Root
    @value-change="(details) => console.log(details)"
    @highlight-change="(details) => console.log(details)"
    @value-invalid="(details) => console.log(details)"
  >
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<TagsInput.Root
  onValueChange={(details) => {
    console.log('tags changed to:', details.value)
  }}
  onHighlightChange={(details) => {
    console.log('highlighted tag:', details.highlightedValue)
  }}
  onValueInvalid={(details) => {
    console.log('Invalid!', details.reason)
  }}
  max={3}
  allowOverflow
  validate={(details) => {
    return !details.value.includes(details.inputValue)
  }}
>
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value}>
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
        {/each}
      </TagsInput.Control>
      <TagsInput.Input placeholder="Add Framework" />
      <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
    {/snippet}
  </TagsInput.Context>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Using the Field Component

The `Field` component helps manage form-related state and accessibility attributes of a tags input. It includes handling
ARIA labels, helper text, and error text to ensure proper accessibility.

**Example: with-field**

#### React

```tsx
import { Field } from '@ark-ui/react/field'
import { TagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const WithField = (props: Field.RootProps) => {
  return (
    <Field.Root {...props}>
      <TagsInput.Root>
        <TagsInput.Context>
          {(tagsInput) => (
            <>
              <TagsInput.Label>Label</TagsInput.Label>
              <TagsInput.Control>
                {tagsInput.value.map((value, index) => (
                  <TagsInput.Item key={index} index={index} value={value}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                ))}
              </TagsInput.Control>
              <TagsInput.Input placeholder="Add Framework" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.Root>
      <Field.HelperText>Additional Info</Field.HelperText>
      <Field.ErrorText>Error Info</Field.ErrorText>
    </Field.Root>
  )
}

```

#### Solid

```tsx
import { Field } from '@ark-ui/solid/field'
import { TagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const WithField = (props: Field.RootProps) => {
  return (
    <Field.Root {...props}>
      <TagsInput.Root>
        <TagsInput.Context>
          {(tagsInput) => (
            <>
              <TagsInput.Label>Label</TagsInput.Label>
              <TagsInput.Control>
                <Index each={tagsInput().value}>
                  {(value, index) => (
                    <TagsInput.Item index={index} value={value()}>
                      <TagsInput.ItemPreview>
                        <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                        <TagsInput.ItemDeleteTrigger>
                          <XIcon />
                        </TagsInput.ItemDeleteTrigger>
                      </TagsInput.ItemPreview>
                      <TagsInput.ItemInput />
                    </TagsInput.Item>
                  )}
                </Index>
                <TagsInput.Input placeholder="Add Framework" />
                <TagsInput.ClearTrigger>
                  <XIcon />
                </TagsInput.ClearTrigger>
              </TagsInput.Control>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.Root>
      <Field.HelperText>Additional Info</Field.HelperText>
      <Field.ErrorText>Error Info</Field.ErrorText>
    </Field.Root>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { Field, type FieldRootProps } from '@ark-ui/vue/field'
import { TagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'

const props = defineProps<FieldRootProps>()
</script>

<template>
  <Field.Root v-bind="props">
    <TagsInput.Root>
      <TagsInput.Context v-slot="tagsInput">
        <TagsInput.Label>Label</TagsInput.Label>
        <TagsInput.Control>
          <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
            <TagsInput.ItemPreview>
              <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput />
          </TagsInput.Item>
          <TagsInput.Input placeholder="Add Framework" />
          <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
        </TagsInput.Control>
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
    <Field.HelperText>Additional Info</Field.HelperText>
    <Field.ErrorText>Error Info</Field.ErrorText>
  </Field.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Field } from '@ark-ui/svelte/field'
  import { TagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'
</script>

<Field.Root>
  <TagsInput.Root>
    <TagsInput.Context>
      {#snippet render(tagsInput)}
        <TagsInput.Label>Label</TagsInput.Label>
        <TagsInput.Control>
          {#each tagsInput().value as value, index (index)}
            <TagsInput.Item {index} {value}>
              <TagsInput.ItemPreview>
                <TagsInput.ItemText>{value}</TagsInput.ItemText>
                <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
              </TagsInput.ItemPreview>
              <TagsInput.ItemInput />
            </TagsInput.Item>
          {/each}
        </TagsInput.Control>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      {/snippet}
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
  <Field.HelperText>Additional Info</Field.HelperText>
  <Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>

```

### Using the Root Provider

The `RootProvider` component provides a context for the tags-input. It accepts the value of the `useTags-input` hook.
You can leverage it to access the component state and methods from outside the tags-input.

**Example: root-provider**

#### React

```tsx
import { TagsInput, useTagsInput } from '@ark-ui/react/tags-input'
import { XIcon } from 'lucide-react'

export const RootProvider = () => {
  const tagsInput = useTagsInput()

  return (
    <>
      <button onClick={() => tagsInput.focus()}>Focus</button>

      <TagsInput.RootProvider value={tagsInput}>
        <TagsInput.Context>
          {(tagsInput) => (
            <>
              <TagsInput.Label>Frameworks</TagsInput.Label>
              <TagsInput.Control>
                {tagsInput.value.map((value, index) => (
                  <TagsInput.Item key={index} index={index} value={value}>
                    <TagsInput.ItemPreview>
                      <TagsInput.ItemText>{value}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput />
                  </TagsInput.Item>
                ))}
              </TagsInput.Control>
              <TagsInput.Input placeholder="Add Framework" />
              <TagsInput.ClearTrigger>
                <XIcon />
              </TagsInput.ClearTrigger>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.RootProvider>
    </>
  )
}

```

#### Solid

```tsx
import { TagsInput, useTagsInput } from '@ark-ui/solid/tags-input'
import { XIcon } from 'lucide-solid'
import { Index } from 'solid-js'

export const RootProvider = () => {
  const tagsInput = useTagsInput()

  return (
    <>
      <button onClick={() => tagsInput().focus()}>Focus</button>

      <TagsInput.RootProvider value={tagsInput}>
        <TagsInput.Context>
          {(api) => (
            <>
              <TagsInput.Label>Frameworks</TagsInput.Label>
              <TagsInput.Control>
                <Index each={api().value}>
                  {(value, index) => (
                    <TagsInput.Item index={index} value={value()}>
                      <TagsInput.ItemPreview>
                        <TagsInput.ItemText>{value()}</TagsInput.ItemText>
                        <TagsInput.ItemDeleteTrigger>
                          <XIcon />
                        </TagsInput.ItemDeleteTrigger>
                      </TagsInput.ItemPreview>
                      <TagsInput.ItemInput />
                    </TagsInput.Item>
                  )}
                </Index>
                <TagsInput.Input placeholder="Add Framework" />
                <TagsInput.ClearTrigger>
                  <XIcon />
                </TagsInput.ClearTrigger>
              </TagsInput.Control>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.RootProvider>
    </>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { TagsInput, useTagsInput } from '@ark-ui/vue/tags-input'
import { XIcon } from 'lucide-vue-next'

const tagsInput = useTagsInput()
</script>

<template>
  <button @click="tagsInput.focus()">Focus</button>

  <TagsInput.RootProvider :value="tagsInput">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label>Frameworks</TagsInput.Label>
      <TagsInput.Control>
        <TagsInput.Item v-for="(value, index) in tagsInput.value" :key="index" :index="index" :value="value">
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" />
        <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
      </TagsInput.Control>
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.RootProvider>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { TagsInput, useTagsInput } from '@ark-ui/svelte/tags-input'
  import { XIcon } from 'lucide-svelte'

  const id = $props.id()

  const tags = useTagsInput({
    id,
    defaultValue: ['React', 'Svelte'],
  })
</script>

<div>
  <button onclick={() => tags().addValue('Vue')}>Add Vue</button>
  <button onclick={() => tags().clearValue()}>Clear All</button>

  <TagsInput.RootProvider value={tags}>
    <TagsInput.Label>Frameworks</TagsInput.Label>
    <TagsInput.Control>
      {#each tags().value as value, index (index)}
        <TagsInput.Item {index} {value}>
          <TagsInput.ItemPreview>
            <TagsInput.ItemText>{value}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput />
        </TagsInput.Item>
      {/each}
      <TagsInput.Input placeholder="Add Framework" />
    </TagsInput.Control>
    <TagsInput.ClearTrigger><XIcon /></TagsInput.ClearTrigger>
    <TagsInput.HiddenInput />
  </TagsInput.RootProvider>
</div>

```

> If you're using the `RootProvider` component, you don't need to use the `Root` component.

## Guides

### Navigating and Editing tags

When the input has an empty value or the caret is at the start position, the tags can be selected by using the arrow
left and arrow right keys. When "visual" focus in on any tag:

- Pressing <kbd>Enter</kbd> or double-clicking on the tag will put it in edit mode, allowing the user change its value
  and press <kbd>Enter</kbd> to commit the changes.
- Pressing <kbd>Delete</kbd> or <kbd>Backspace</kbd> will delete the tag that has _visual_ focus.

## API Reference

### Props

**Component API Reference**

#### React

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `addOnPaste` | `boolean` | No | Whether to add a tag when you paste values into the tag input |
| `allowOverflow` | `boolean` | No | Whether to allow tags to exceed max. In this case,
we'll attach `data-invalid` to the root |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `autoFocus` | `boolean` | No | Whether the input should be auto-focused |
| `blurBehavior` | `'clear' | 'add'` | No | The behavior of the tags input when the input is blurred
- `"add"`: add the input value as a new tag
- `"clear"`: clear the input value |
| `defaultInputValue` | `string` | No | The initial tag input value when rendered.
Use when you don't need to control the tag input value. |
| `defaultValue` | `string[]` | No | The initial tag value when rendered.
Use when you don't need to control the tag value. |
| `delimiter` | `string | RegExp` | No | The character that serves has:
- event key to trigger the addition of a new tag
- character used to split tags when pasting into the input |
| `disabled` | `boolean` | No | Whether the tags input should be disabled |
| `editable` | `boolean` | No | Whether a tag can be edited after creation, by pressing `Enter` or double clicking. |
| `form` | `string` | No | The associate form of the underlying input element. |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{
  root: string
  input: string
  hiddenInput: string
  clearBtn: string
  label: string
  control: string
  item: (opts: ItemProps) => string
  itemDeleteTrigger: (opts: ItemProps) => string
  itemInput: (opts: ItemProps) => string
}>` | No | The ids of the elements in the tags input. Useful for composition. |
| `inputValue` | `string` | No | The controlled tag input's value |
| `invalid` | `boolean` | No | Whether the tags input is invalid |
| `max` | `number` | No | The max number of tags |
| `maxLength` | `number` | No | The max length of the input. |
| `name` | `string` | No | The name attribute for the input. Useful for form submissions |
| `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component |
| `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Callback fired when a tag is highlighted by pointer or keyboard navigation |
| `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Callback fired when the input value is updated |
| `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component |
| `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component |
| `onValueChange` | `(details: ValueChangeDetails) => void` | No | Callback fired when the tag values is updated |
| `onValueInvalid` | `(details: ValidityChangeDetails) => void` | No | Callback fired when the max tag count is reached or the `validateTag` function returns `false` |
| `readOnly` | `boolean` | No | Whether the tags input should be read-only |
| `required` | `boolean` | No | Whether the tags input is required |
| `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states |
| `validate` | `(details: ValidateArgs) => boolean` | No | Returns a boolean that determines whether a tag can be added.
Useful for preventing duplicates or invalid tag values. |
| `value` | `string[]` | No | The controlled tag value |


**Root Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | root |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-disabled]` | Present when disabled |
| `[data-focus]` | Present when focused |
| `[data-empty]` | Present when the content is empty |


**ClearTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ClearTrigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | clear-trigger |
| `[data-readonly]` | Present when read-only |


**Control Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Control Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | control |
| `[data-disabled]` | Present when disabled |
| `[data-readonly]` | Present when read-only |
| `[data-invalid]` | Present when invalid |
| `[data-focus]` | Present when focused |


**HiddenInput Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Input Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Input Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | input |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-empty]` | Present when the content is empty |


**ItemDeleteTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemInput Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemPreview Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemPreview Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item-preview |
| `[data-value]` | The value of the item |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |


**Item Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `index` | `string | number` | Yes |  |
| `value` | `string` | Yes |  |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `disabled` | `boolean` | No |  |


**Item Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item |
| `[data-value]` | The value of the item |
| `[data-disabled]` | Present when disabled |


**ItemText Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemText Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item-text |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |


**Label Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Label Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | label |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-required]` | Present when required |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UseTagsInputReturn` | Yes |  |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


#### Solid

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `addOnPaste` | `boolean` | No | Whether to add a tag when you paste values into the tag input |
| `allowOverflow` | `boolean` | No | Whether to allow tags to exceed max. In this case,
we'll attach `data-invalid` to the root |
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `autoFocus` | `boolean` | No | Whether the input should be auto-focused |
| `blurBehavior` | `'clear' | 'add'` | No | The behavior of the tags input when the input is blurred
- `"add"`: add the input value as a new tag
- `"clear"`: clear the input value |
| `defaultInputValue` | `string` | No | The initial tag input value when rendered.
Use when you don't need to control the tag input value. |
| `defaultValue` | `string[]` | No | The initial tag value when rendered.
Use when you don't need to control the tag value. |
| `delimiter` | `string | RegExp` | No | The character that serves has:
- event key to trigger the addition of a new tag
- character used to split tags when pasting into the input |
| `disabled` | `boolean` | No | Whether the tags input should be disabled |
| `editable` | `boolean` | No | Whether a tag can be edited after creation, by pressing `Enter` or double clicking. |
| `form` | `string` | No | The associate form of the underlying input element. |
| `ids` | `Partial<{
  root: string
  input: string
  hiddenInput: string
  clearBtn: string
  label: string
  control: string
  item: (opts: ItemProps) => string
  itemDeleteTrigger: (opts: ItemProps) => string
  itemInput: (opts: ItemProps) => string
}>` | No | The ids of the elements in the tags input. Useful for composition. |
| `inputValue` | `string` | No | The controlled tag input's value |
| `invalid` | `boolean` | No | Whether the tags input is invalid |
| `max` | `number` | No | The max number of tags |
| `maxLength` | `number` | No | The max length of the input. |
| `name` | `string` | No | The name attribute for the input. Useful for form submissions |
| `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component |
| `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Callback fired when a tag is highlighted by pointer or keyboard navigation |
| `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Callback fired when the input value is updated |
| `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component |
| `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component |
| `onValueChange` | `(details: ValueChangeDetails) => void` | No | Callback fired when the tag values is updated |
| `onValueInvalid` | `(details: ValidityChangeDetails) => void` | No | Callback fired when the max tag count is reached or the `validateTag` function returns `false` |
| `readOnly` | `boolean` | No | Whether the tags input should be read-only |
| `required` | `boolean` | No | Whether the tags input is required |
| `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states |
| `validate` | `(details: ValidateArgs) => boolean` | No | Returns a boolean that determines whether a tag can be added.
Useful for preventing duplicates or invalid tag values. |
| `value` | `string[]` | No | The controlled tag value |


**Root Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | root |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-disabled]` | Present when disabled |
| `[data-focus]` | Present when focused |
| `[data-empty]` | Present when the content is empty |


**ClearTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ClearTrigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | clear-trigger |
| `[data-readonly]` | Present when read-only |


**Control Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Control Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | control |
| `[data-disabled]` | Present when disabled |
| `[data-readonly]` | Present when read-only |
| `[data-invalid]` | Present when invalid |
| `[data-focus]` | Present when focused |


**HiddenInput Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Input Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Input Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | input |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-empty]` | Present when the content is empty |


**ItemDeleteTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemInput Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemPreview Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemPreview Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item-preview |
| `[data-value]` | The value of the item |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |


**Item Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `index` | `string | number` | Yes |  |
| `value` | `string` | Yes |  |
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `disabled` | `boolean` | No |  |


**Item Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item |
| `[data-value]` | The value of the item |
| `[data-disabled]` | Present when disabled |


**ItemText Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemText Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item-text |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |


**Label Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Label Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | label |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-required]` | Present when required |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UseTagsInputReturn` | Yes |  |
| `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


#### Vue

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `addOnPaste` | `boolean` | No | Whether to add a tag when you paste values into the tag input |
| `allowOverflow` | `boolean` | No | Whether to allow tags to exceed max. In this case,
we'll attach `data-invalid` to the root |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `autoFocus` | `boolean` | No | Whether the input should be auto-focused |
| `blurBehavior` | `'clear' | 'add'` | No | The behavior of the tags input when the input is blurred
- `"add"`: add the input value as a new tag
- `"clear"`: clear the input value |
| `defaultInputValue` | `string` | No | The initial tag input value when rendered.
Use when you don't need to control the tag input value. |
| `defaultValue` | `string[]` | No | The initial tag value when rendered.
Use when you don't need to control the tag value. |
| `delimiter` | `string | RegExp` | No | The character that serves has:
- event key to trigger the addition of a new tag
- character used to split tags when pasting into the input |
| `disabled` | `boolean` | No | Whether the tags input should be disabled |
| `editable` | `boolean` | No | Whether a tag can be edited after creation, by pressing `Enter` or double clicking. |
| `form` | `string` | No | The associate form of the underlying input element. |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{
  root: string
  input: string
  hiddenInput: string
  clearBtn: string
  label: string
  control: string
  item(opts: ItemProps): string
  itemDeleteTrigger(opts: ItemProps): string
  itemInput(opts: ItemProps): string
}>` | No | The ids of the elements in the tags input. Useful for composition. |
| `inputValue` | `string` | No | The controlled tag input's value |
| `invalid` | `boolean` | No | Whether the tags input is invalid |
| `max` | `number` | No | The max number of tags |
| `maxLength` | `number` | No | The max length of the input. |
| `modelValue` | `string[]` | No | The v-model value of the tags input |
| `name` | `string` | No | The name attribute for the input. Useful for form submissions |
| `readOnly` | `boolean` | No | Whether the tags input should be read-only |
| `required` | `boolean` | No | Whether the tags input is required |
| `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states |
| `validate` | `(details: ValidateArgs) => boolean` | No | Returns a boolean that determines whether a tag can be added.
Useful for preventing duplicates or invalid tag values. |


**Root Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | root |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-disabled]` | Present when disabled |
| `[data-focus]` | Present when focused |
| `[data-empty]` | Present when the content is empty |


**ClearTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ClearTrigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | clear-trigger |
| `[data-readonly]` | Present when read-only |


**Control Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Control Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | control |
| `[data-disabled]` | Present when disabled |
| `[data-readonly]` | Present when read-only |
| `[data-invalid]` | Present when invalid |
| `[data-focus]` | Present when focused |


**HiddenInput Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Input Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Input Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | input |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-empty]` | Present when the content is empty |


**ItemDeleteTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemInput Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemPreview Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemPreview Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item-preview |
| `[data-value]` | The value of the item |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |


**Item Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `index` | `string | number` | Yes |  |
| `value` | `string` | Yes |  |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `disabled` | `boolean` | No |  |


**Item Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item |
| `[data-value]` | The value of the item |
| `[data-disabled]` | Present when disabled |


**ItemText Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemText Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item-text |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |


**Label Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Label Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | label |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-required]` | Present when required |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `TagsInputApi<PropTypes>` | Yes |  |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


#### Svelte

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `addOnPaste` | `boolean` | No | Whether to add a tag when you paste values into the tag input |
| `allowOverflow` | `boolean` | No | Whether to allow tags to exceed max. In this case,
we'll attach `data-invalid` to the root |
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `autoFocus` | `boolean` | No | Whether the input should be auto-focused |
| `blurBehavior` | `'clear' | 'add'` | No | The behavior of the tags input when the input is blurred
- `"add"`: add the input value as a new tag
- `"clear"`: clear the input value |
| `defaultInputValue` | `string` | No | The initial tag input value when rendered.
Use when you don't need to control the tag input value. |
| `defaultValue` | `string[]` | No | The initial tag value when rendered.
Use when you don't need to control the tag value. |
| `delimiter` | `string | RegExp` | No | The character that serves has:
- event key to trigger the addition of a new tag
- character used to split tags when pasting into the input |
| `disabled` | `boolean` | No | Whether the tags input should be disabled |
| `editable` | `boolean` | No | Whether a tag can be edited after creation, by pressing `Enter` or double clicking. |
| `form` | `string` | No | The associate form of the underlying input element. |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{
  root: string
  input: string
  hiddenInput: string
  clearBtn: string
  label: string
  control: string
  item: (opts: ItemProps) => string
  itemDeleteTrigger: (opts: ItemProps) => string
  itemInput: (opts: ItemProps) => string
}>` | No | The ids of the elements in the tags input. Useful for composition. |
| `inputValue` | `string` | No | The controlled tag input's value |
| `invalid` | `boolean` | No | Whether the tags input is invalid |
| `max` | `number` | No | The max number of tags |
| `maxLength` | `number` | No | The max length of the input. |
| `name` | `string` | No | The name attribute for the input. Useful for form submissions |
| `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component |
| `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Callback fired when a tag is highlighted by pointer or keyboard navigation |
| `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Callback fired when the input value is updated |
| `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component |
| `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component |
| `onValueChange` | `(details: ValueChangeDetails) => void` | No | Callback fired when the tag values is updated |
| `onValueInvalid` | `(details: ValidityChangeDetails) => void` | No | Callback fired when the max tag count is reached or the `validateTag` function returns `false` |
| `readOnly` | `boolean` | No | Whether the tags input should be read-only |
| `ref` | `Element` | No |  |
| `required` | `boolean` | No | Whether the tags input is required |
| `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states |
| `validate` | `(details: ValidateArgs) => boolean` | No | Returns a boolean that determines whether a tag can be added.
Useful for preventing duplicates or invalid tag values. |
| `value` | `string[]` | No | The controlled tag value |


**Root Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | root |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-disabled]` | Present when disabled |
| `[data-focus]` | Present when focused |
| `[data-empty]` | Present when the content is empty |


**ClearTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**ClearTrigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | clear-trigger |
| `[data-readonly]` | Present when read-only |


**Context Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `render` | `Snippet<[UseTagsInputReturn]>` | Yes |  |


**Control Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Control Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | control |
| `[data-disabled]` | Present when disabled |
| `[data-readonly]` | Present when read-only |
| `[data-invalid]` | Present when invalid |
| `[data-focus]` | Present when focused |


**HiddenInput Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Input Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Input Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | input |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-empty]` | Present when the content is empty |


**ItemContext Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `render` | `Snippet<[UseTagsInputItemContext]>` | Yes |  |


**ItemDeleteTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**ItemInput Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**ItemPreview Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**ItemPreview Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item-preview |
| `[data-value]` | The value of the item |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |


**Item Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `index` | `number` | Yes |  |
| `value` | `string` | Yes |  |
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `disabled` | `boolean` | No |  |
| `ref` | `Element` | No |  |


**Item Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item |
| `[data-value]` | The value of the item |
| `[data-disabled]` | Present when disabled |


**ItemText Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**ItemText Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | item-text |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |


**Label Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Label Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | tags-input |
| `[data-part]` | label |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-required]` | Present when required |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UseTagsInputReturn` | Yes |  |
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


### Context

These are the properties available when using `TagsInput.Context`, `useTagsInputContext` hook or `useTagsInput` hook.

**API:**

| Property | Type | Description |
|----------|------|-------------|
| `empty` | `boolean` | Whether the tags are empty |
| `inputValue` | `string` | The value of the tags entry input. |
| `value` | `string[]` | The value of the tags as an array of strings. |
| `valueAsString` | `string` | The value of the tags as a string. |
| `count` | `number` | The number of the tags. |
| `atMax` | `boolean` | Whether the tags have reached the max limit. |
| `setValue` | `(value: string[]) => void` | Function to set the value of the tags. |
| `clearValue` | `(id?: string) => void` | Function to clear the value of the tags. |
| `addValue` | `(value: string) => void` | Function to add a tag to the tags. |
| `setValueAtIndex` | `(index: number, value: string) => void` | Function to set the value of a tag at the given index. |
| `setInputValue` | `(value: string) => void` | Function to set the value of the tags entry input. |
| `clearInputValue` | `VoidFunction` | Function to clear the value of the tags entry input. |
| `focus` | `VoidFunction` | Function to focus the tags entry input. |
| `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of a tag |


## Accessibility

### Keyboard Support

<KeyBindingsTable id="tags-input" />