# 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

<Anatomy id="tags-input" />

```tsx
<TagsInput.Root>
  <TagsInput.Label />
  <TagsInput.Control>
    <TagsInput.Item>
      <TagsInput.ItemPreview>
        <TagsInput.ItemText />
        <TagsInput.ItemDeleteTrigger />
      </TagsInput.ItemPreview>
      <TagsInput.ItemInput />
    </TagsInput.Item>
    <TagsInput.Input />
    <TagsInput.ClearTrigger />
  </TagsInput.Control>
  <TagsInput.HiddenInput />
</TagsInput.Root>
```

## Examples

**Example: basic**

#### React

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

export const Basic = () => {
  return (
    <TagsInput.Root className={styles.Root}>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const Basic = () => {
  return (
    <TagsInput.Root class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

<TagsInput.Root class={styles.Root}>
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
      <TagsInput.Control class={styles.Control}>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value} class={styles.Item}>
            <TagsInput.ItemPreview class={styles.ItemPreview}>
              <TagsInput.ItemText class={styles.ItemText}>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                <XIcon />
              </TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput class={styles.ItemInput} />
          </TagsInput.Item>
        {/each}
        <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
        <TagsInput.ClearTrigger class={styles.ClearTrigger}>
          <XIcon />
        </TagsInput.ClearTrigger>
      </TagsInput.Control>
    {/snippet}
  </TagsInput.Context>
  <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 { XIcon } from 'lucide-react'
import { useState } from 'react'
import styles from 'styles/tags-input.module.css'

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

  return (
    <TagsInput.Root className={styles.Root} value={value} onValueChange={(details) => setValue(details.value)}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {api.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

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

  return (
    <TagsInput.Root value={value()} onValueChange={(details) => setValue(details.value)} class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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'
import styles from 'styles/tags-input.module.css'

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

<template>
  <TagsInput.Root v-model="value" :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'

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

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

```

### 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 { XIcon } from 'lucide-react'
import { useState } from 'react'
import button from 'styles/button.module.css'
import styles from 'styles/tags-input.module.css'

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

  return (
    <div className="stack">
      <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
        <button className={button.Root} type="button" onClick={() => setInputValue('React')}>
          Set to "React"
        </button>
        <button className={button.Root} type="button" onClick={() => setInputValue('')}>
          Clear Input
        </button>
        <span style={{ fontSize: '14px' }}>Current: "{inputValue}"</span>
      </div>

      <TagsInput.Root
        className={styles.Root}
        inputValue={inputValue}
        onInputValueChange={(details) => setInputValue(details.inputValue)}
      >
        <TagsInput.Context>
          {(tagsInput) => (
            <>
              <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
              <TagsInput.Control className={styles.Control}>
                {tagsInput.value.map((value, index) => (
                  <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                    <TagsInput.ItemPreview className={styles.ItemPreview}>
                      <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput className={styles.ItemInput} />
                  </TagsInput.Item>
                ))}
                <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
                <TagsInput.ClearTrigger className={styles.ClearTrigger}>
                  <XIcon />
                </TagsInput.ClearTrigger>
              </TagsInput.Control>
            </>
          )}
        </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'
import styles from 'styles/tags-input.module.css'

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

  return (
    <TagsInput.Root
      inputValue={inputValue()}
      onInputValueChange={(details) => setInputValue(details.inputValue)}
      class={styles.Root}
    >
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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'
import styles from 'styles/tags-input.module.css'

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

<template>
  <TagsInput.Root
    :input-value="inputValue"
    :class="styles.Root"
    @input-value-change="(details) => (inputValue = details.inputValue)"
  >
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'

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

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

```

### Root Provider

An alternative way to control the tags input is to use the `RootProvider` component and the `useTagsInput` hook. This
way you can access the state and methods from outside the component.

**Example: root-provider**

#### React

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

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

      <output>values: {JSON.stringify(tagsInput.value)}</output>
    </div>
  )
}

```

#### Solid

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

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

  return (
    <div class="stack">
      <button class={button.Root} onClick={() => tagsInput().focus()}>
        Focus
      </button>

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

```

#### Vue

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

const tagsInput = useTagsInput()
</script>

<template>
  <div class="stack">
    <button :class="button.Root" @click="tagsInput.focus()">Focus</button>

    <TagsInput.RootProvider :value="tagsInput" :class="styles.Root">
      <TagsInput.Context v-slot="tagsInput">
        <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
        <TagsInput.Control :class="styles.Control">
          <TagsInput.Item
            v-for="(value, index) in tagsInput.value"
            :key="index"
            :index="index"
            :value="value"
            :class="styles.Item"
          >
            <TagsInput.ItemPreview :class="styles.ItemPreview">
              <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
                <XIcon />
              </TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput :class="styles.ItemInput" />
          </TagsInput.Item>
          <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
          <TagsInput.ClearTrigger :class="styles.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'
  import button from 'styles/button.module.css'
  import styles from 'styles/tags-input.module.css'

  const id = $props.id()

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

<div class="stack">
  <button class={button.Root} onclick={() => tagsInput().addValue('Vue')}>Add Vue</button>
  <button class={button.Root} onclick={() => tagsInput().clearValue()}>Clear All</button>

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

  <output>values: {JSON.stringify(tagsInput().value)}</output>
</div>

```

### Field

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'
import field from 'styles/field.module.css'
import styles from 'styles/tags-input.module.css'

export const WithField = () => {
  return (
    <Field.Root className={field.Root}>
      <TagsInput.Root className={styles.Root}>
        <TagsInput.Context>
          {(tagsInput) => (
            <>
              <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
              <TagsInput.Control className={styles.Control}>
                {tagsInput.value.map((value, index) => (
                  <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                    <TagsInput.ItemPreview className={styles.ItemPreview}>
                      <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput className={styles.ItemInput} />
                  </TagsInput.Item>
                ))}
                <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
                <TagsInput.ClearTrigger className={styles.ClearTrigger}>
                  <XIcon />
                </TagsInput.ClearTrigger>
              </TagsInput.Control>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.Root>
      <Field.HelperText className={field.HelperText}>Additional Info</Field.HelperText>
      <Field.ErrorText className={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'
import field from 'styles/field.module.css'
import styles from 'styles/tags-input.module.css'

export const WithField = () => {
  return (
    <Field.Root class={field.Root}>
      <TagsInput.Root class={styles.Root}>
        <TagsInput.Context>
          {(api) => (
            <>
              <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
              <TagsInput.Control class={styles.Control}>
                <Index each={api().value}>
                  {(value, index) => (
                    <TagsInput.Item index={index} value={value()} class={styles.Item}>
                      <TagsInput.ItemPreview class={styles.ItemPreview}>
                        <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                        <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                          <XIcon />
                        </TagsInput.ItemDeleteTrigger>
                      </TagsInput.ItemPreview>
                      <TagsInput.ItemInput class={styles.ItemInput} />
                    </TagsInput.Item>
                  )}
                </Index>
                <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
                <TagsInput.ClearTrigger class={styles.ClearTrigger}>
                  <XIcon />
                </TagsInput.ClearTrigger>
              </TagsInput.Control>
            </>
          )}
        </TagsInput.Context>
        <TagsInput.HiddenInput />
      </TagsInput.Root>
      <Field.HelperText class={field.HelperText}>Additional Info</Field.HelperText>
      <Field.ErrorText class={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'
import styles from 'styles/tags-input.module.css'
import field from 'styles/field.module.css'

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

<template>
  <Field.Root v-bind="props" :class="field.Root">
    <TagsInput.Root :class="styles.Root">
      <TagsInput.Context v-slot="tagsInput">
        <TagsInput.Label :class="styles.Label">Label</TagsInput.Label>
        <TagsInput.Control :class="styles.Control">
          <TagsInput.Item
            v-for="(value, index) in tagsInput.value"
            :key="index"
            :index="index"
            :value="value"
            :class="styles.Item"
          >
            <TagsInput.ItemPreview :class="styles.ItemPreview">
              <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
                <XIcon />
              </TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput :class="styles.ItemInput" />
          </TagsInput.Item>
          <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
          <TagsInput.ClearTrigger :class="styles.ClearTrigger">
            <XIcon />
          </TagsInput.ClearTrigger>
        </TagsInput.Control>
      </TagsInput.Context>
      <TagsInput.HiddenInput />
    </TagsInput.Root>
    <Field.HelperText :class="field.HelperText">Additional Info</Field.HelperText>
    <Field.ErrorText :class="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'
  import field from 'styles/field.module.css'
  import styles from 'styles/tags-input.module.css'
</script>

<Field.Root class={field.Root}>
  <TagsInput.Root class={styles.Root}>
    <TagsInput.Context>
      {#snippet render(tagsInput)}
        <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
        <TagsInput.Control class={styles.Control}>
          {#each tagsInput().value as value, index (index)}
            <TagsInput.Item {index} {value} class={styles.Item}>
              <TagsInput.ItemPreview class={styles.ItemPreview}>
                <TagsInput.ItemText class={styles.ItemText}>{value}</TagsInput.ItemText>
                <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                  <XIcon />
                </TagsInput.ItemDeleteTrigger>
              </TagsInput.ItemPreview>
              <TagsInput.ItemInput class={styles.ItemInput} />
            </TagsInput.Item>
          {/each}
          <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
          <TagsInput.ClearTrigger class={styles.ClearTrigger}>
            <XIcon />
          </TagsInput.ClearTrigger>
        </TagsInput.Control>
      {/snippet}
    </TagsInput.Context>
    <TagsInput.HiddenInput />
  </TagsInput.Root>
  <Field.HelperText class={field.HelperText}>Additional Info</Field.HelperText>
  <Field.ErrorText class={field.ErrorText}>Error Info</Field.ErrorText>
</Field.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'
import styles from 'styles/tags-input.module.css'

export const MaxWithOverflow = () => {
  return (
    <TagsInput.Root className={styles.Root} max={3} allowOverflow>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const MaxWithOverflow = () => {
  return (
    <TagsInput.Root max={3} allowOverflow class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root :max="3" allowOverflow :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

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

```

### 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'
import styles from 'styles/tags-input.module.css'

const DELIMITER_PATTERN = /[,;\s]/

export const Delimiter = () => {
  return (
    <TagsInput.Root className={styles.Root} delimiter={DELIMITER_PATTERN}>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks (add with comma, semicolon, or space)</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add tag" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const Delimiter = () => {
  return (
    <TagsInput.Root delimiter="," class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root delimiter="," :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

<TagsInput.Root delimiter="," class={styles.Root}>
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
      <TagsInput.Control class={styles.Control}>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value} class={styles.Item}>
            <TagsInput.ItemPreview class={styles.ItemPreview}>
              <TagsInput.ItemText class={styles.ItemText}>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                <XIcon />
              </TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput class={styles.ItemInput} />
          </TagsInput.Item>
        {/each}
        <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
        <TagsInput.ClearTrigger class={styles.ClearTrigger}>
          <XIcon />
        </TagsInput.ClearTrigger>
      </TagsInput.Control>
    {/snippet}
  </TagsInput.Context>
  <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'
import styles from 'styles/tags-input.module.css'

export const Disabled = () => {
  return (
    <TagsInput.Root className={styles.Root} defaultValue={['React', 'Solid', 'Vue']} disabled>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const Disabled = () => {
  return (
    <TagsInput.Root defaultValue={['React', 'Solid', 'Vue']} disabled class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root :default-value="['React', 'Solid', 'Vue']" disabled :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

<TagsInput.Root defaultValue={['React', 'Solid', 'Vue']} disabled class={styles.Root}>
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
      <TagsInput.Control class={styles.Control}>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value} class={styles.Item}>
            <TagsInput.ItemPreview class={styles.ItemPreview}>
              <TagsInput.ItemText class={styles.ItemText}>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                <XIcon />
              </TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput class={styles.ItemInput} />
          </TagsInput.Item>
        {/each}
        <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
        <TagsInput.ClearTrigger class={styles.ClearTrigger}>
          <XIcon />
        </TagsInput.ClearTrigger>
      </TagsInput.Control>
    {/snippet}
  </TagsInput.Context>
  <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'
import styles from 'styles/tags-input.module.css'

export const Invalid = () => {
  return (
    <TagsInput.Root className={styles.Root} invalid>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const Invalid = () => {
  return (
    <TagsInput.Root invalid class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root invalid :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

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

```

### Max 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'
import styles from 'styles/tags-input.module.css'

export const MaxTagLength = () => {
  return (
    <TagsInput.Root className={styles.Root} maxLength={10}>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks (Max 10 characters)</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const MaxTagLength = () => {
  return (
    <TagsInput.Root maxLength={10} class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root :max-length="10" :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

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

```

### 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'
import styles from 'styles/tags-input.module.css'

export const Readonly = () => {
  return (
    <TagsInput.Root className={styles.Root} defaultValue={['React', 'Solid', 'Vue']} readOnly>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const Readonly = () => {
  return (
    <TagsInput.Root defaultValue={['React', 'Solid', 'Vue']} readOnly class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root :default-value="['React', 'Solid', 'Vue']" read-only :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

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

```

### Validation

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'
import styles from 'styles/tags-input.module.css'

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

const validateTag = ({ value, inputValue }: { value: string[]; inputValue: string }) =>
  !!inputValue?.trim() && !value.includes(inputValue) && inputValue.length >= 3 && TAG_PATTERN.test(inputValue)

export const Validation = () => {
  return (
    <TagsInput.Root className={styles.Root} validate={validateTag}>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks (Min 3 chars, alphanumeric)</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const Validation = () => {
  return (
    <TagsInput.Root
      validate={(details) => {
        return !details.value.includes(details.inputValue)
      }}
      class={styles.Root}
    >
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root
    :validate="
      (details) => {
        return !details.value.includes(details.inputValue)
      }
    "
    :class="styles.Root"
  >
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

<TagsInput.Root
  validate={(details) => {
    return !details.value.includes(details.inputValue)
  }}
  class={styles.Root}
>
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
      <TagsInput.Control class={styles.Control}>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value} class={styles.Item}>
            <TagsInput.ItemPreview class={styles.ItemPreview}>
              <TagsInput.ItemText class={styles.ItemText}>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                <XIcon />
              </TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput class={styles.ItemInput} />
          </TagsInput.Item>
        {/each}
        <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
        <TagsInput.ClearTrigger class={styles.ClearTrigger}>
          <XIcon />
        </TagsInput.ClearTrigger>
      </TagsInput.Control>
    {/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'
import styles from 'styles/tags-input.module.css'

export const BlurBehavior = () => {
  return (
    <TagsInput.Root className={styles.Root} blurBehavior="add">
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const BlurBehavior = () => {
  return (
    <TagsInput.Root blurBehavior="add" class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root blurBehavior="add" :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

<TagsInput.Root blurBehavior="add" class={styles.Root}>
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
      <TagsInput.Control class={styles.Control}>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value} class={styles.Item}>
            <TagsInput.ItemPreview class={styles.ItemPreview}>
              <TagsInput.ItemText class={styles.ItemText}>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                <XIcon />
              </TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput class={styles.ItemInput} />
          </TagsInput.Item>
        {/each}
        <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
        <TagsInput.ClearTrigger class={styles.ClearTrigger}>
          <XIcon />
        </TagsInput.ClearTrigger>
      </TagsInput.Control>
    {/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'
import styles from 'styles/tags-input.module.css'

export const PasteBehavior = () => {
  return (
    <TagsInput.Root className={styles.Root} addOnPaste delimiter=",">
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const PasteBehavior = () => {
  return (
    <TagsInput.Root addOnPaste delimiter="," class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root addOnPaste delimiter="," :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

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

```

### Disable 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'
import styles from 'styles/tags-input.module.css'

export const DisabledEditing = () => {
  return (
    <TagsInput.Root className={styles.Root} editable={false}>
      <TagsInput.Context>
        {(tagsInput) => (
          <>
            <TagsInput.Label className={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control className={styles.Control}>
              {tagsInput.value.map((value, index) => (
                <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                  <TagsInput.ItemPreview className={styles.ItemPreview}>
                    <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput className={styles.ItemInput} />
                </TagsInput.Item>
              ))}
              <TagsInput.Input placeholder="Add Framework" className={styles.Input} />
              <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const DisabledEditing = () => {
  return (
    <TagsInput.Root editable={false} class={styles.Root}>
      <TagsInput.Context>
        {(api) => (
          <>
            <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
            <TagsInput.Control class={styles.Control}>
              <Index each={api().value}>
                {(value, index) => (
                  <TagsInput.Item index={index} value={value()} class={styles.Item}>
                    <TagsInput.ItemPreview class={styles.ItemPreview}>
                      <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                      <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                        <XIcon />
                      </TagsInput.ItemDeleteTrigger>
                    </TagsInput.ItemPreview>
                    <TagsInput.ItemInput class={styles.ItemInput} />
                  </TagsInput.Item>
                )}
              </Index>
              <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
              <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'
</script>

<template>
  <TagsInput.Root :allowEditTag="false" :class="styles.Root">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

<TagsInput.Root defaultValue={['React', 'Svelte', 'Vue']} editable={false} class={styles.Root}>
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
      <TagsInput.Control class={styles.Control}>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value} class={styles.Item}>
            <TagsInput.ItemPreview class={styles.ItemPreview}>
              <TagsInput.ItemText class={styles.ItemText}>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                <XIcon />
              </TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput class={styles.ItemInput} />
          </TagsInput.Item>
        {/each}
        <TagsInput.Input placeholder="Add Framework" class={styles.Input} />
        <TagsInput.ClearTrigger class={styles.ClearTrigger}>
          <XIcon />
        </TagsInput.ClearTrigger>
      </TagsInput.Control>
    {/snippet}
  </TagsInput.Context>
  <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'
import button from 'styles/button.module.css'
import styles from 'styles/tags-input.module.css'

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

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

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

```

#### Solid

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

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

  return (
    <div class="stack">
      <div>
        <button type="button" class={button.Root} onClick={() => tagsInput().addValue('React')}>
          Add React
        </button>
        <button type="button" class={button.Root} onClick={() => tagsInput().addValue('Solid')}>
          Add Solid
        </button>
        <button type="button" class={button.Root} onClick={() => tagsInput().setValue(['Vue', 'Svelte'])}>
          Set to Vue & Svelte
        </button>
        <button type="button" class={button.Root} onClick={() => tagsInput().clearValue()}>
          Clear All
        </button>
      </div>

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

```

#### Vue

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

const tagsInput = useTagsInput()
</script>

<template>
  <div class="stack">
    <div>
      <button :class="button.Root" type="button" @click="tagsInput.addValue('React')">Add React</button>
      <button :class="button.Root" type="button" @click="tagsInput.addValue('Solid')">Add Solid</button>
      <button :class="button.Root" type="button" @click="tagsInput.setValue(['Vue', 'Svelte'])">
        Set to Vue & Svelte
      </button>
      <button :class="button.Root" type="button" @click="tagsInput.clearValue()">Clear All</button>
    </div>

    <TagsInput.RootProvider :value="tagsInput" :class="styles.Root">
      <TagsInput.Context v-slot="api">
        <TagsInput.Label :class="styles.Label">Frameworks</TagsInput.Label>
        <TagsInput.Control :class="styles.Control">
          <TagsInput.Item
            v-for="(value, index) in api.value"
            :key="index"
            :index="index"
            :value="value"
            :class="styles.Item"
          >
            <TagsInput.ItemPreview :class="styles.ItemPreview">
              <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
                <XIcon />
              </TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput :class="styles.ItemInput" />
          </TagsInput.Item>
          <TagsInput.Input placeholder="Add Framework" :class="styles.Input" />
          <TagsInput.ClearTrigger :class="styles.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'
  import button from 'styles/button.module.css'
  import styles from 'styles/tags-input.module.css'

  const tagsInput = useTagsInput()
</script>

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

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

```

### Sanitize Value

Use the `sanitizeValue` prop to normalize tag values before they're added. This runs on every new tag — useful for
trimming whitespace, converting to lowercase, or any other formatting you need.

**Example: sanitize-value**

#### React

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

export const SanitizeValue = () => (
  <TagsInput.Root className={styles.Root} sanitizeValue={(value) => value.trim().toLowerCase()}>
    <TagsInput.Context>
      {(tagsInput) => (
        <>
          <TagsInput.Label className={styles.Label}>Email Addresses</TagsInput.Label>
          <TagsInput.Control className={styles.Control}>
            {tagsInput.value.map((value, index) => (
              <TagsInput.Item key={index} index={index} value={value} className={styles.Item}>
                <TagsInput.ItemPreview className={styles.ItemPreview}>
                  <TagsInput.ItemText className={styles.ItemText}>{value}</TagsInput.ItemText>
                  <TagsInput.ItemDeleteTrigger className={styles.ItemDeleteTrigger}>
                    <XIcon />
                  </TagsInput.ItemDeleteTrigger>
                </TagsInput.ItemPreview>
                <TagsInput.ItemInput className={styles.ItemInput} />
              </TagsInput.Item>
            ))}
            <TagsInput.Input placeholder="Add email" className={styles.Input} />
            <TagsInput.ClearTrigger className={styles.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'
import styles from 'styles/tags-input.module.css'

export const SanitizeValue = () => (
  <TagsInput.Root class={styles.Root} sanitizeValue={(value) => value.trim().toLowerCase()}>
    <TagsInput.Context>
      {(api) => (
        <>
          <TagsInput.Label class={styles.Label}>Email Addresses</TagsInput.Label>
          <TagsInput.Control class={styles.Control}>
            <Index each={api().value}>
              {(value, index) => (
                <TagsInput.Item index={index} value={value()} class={styles.Item}>
                  <TagsInput.ItemPreview class={styles.ItemPreview}>
                    <TagsInput.ItemText class={styles.ItemText}>{value()}</TagsInput.ItemText>
                    <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                      <XIcon />
                    </TagsInput.ItemDeleteTrigger>
                  </TagsInput.ItemPreview>
                  <TagsInput.ItemInput class={styles.ItemInput} />
                </TagsInput.Item>
              )}
            </Index>
            <TagsInput.Input placeholder="Add email" class={styles.Input} />
            <TagsInput.ClearTrigger class={styles.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 styles from 'styles/tags-input.module.css'

const sanitizeValue = (value: string) => value.trim().toLowerCase()
</script>

<template>
  <TagsInput.Root :class="styles.Root" :sanitize-value="sanitizeValue">
    <TagsInput.Context v-slot="tagsInput">
      <TagsInput.Label :class="styles.Label">Email Addresses</TagsInput.Label>
      <TagsInput.Control :class="styles.Control">
        <TagsInput.Item
          v-for="(value, index) in tagsInput.value"
          :key="index"
          :index="index"
          :value="value"
          :class="styles.Item"
        >
          <TagsInput.ItemPreview :class="styles.ItemPreview">
            <TagsInput.ItemText :class="styles.ItemText">{{ value }}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger :class="styles.ItemDeleteTrigger">
              <XIcon />
            </TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput :class="styles.ItemInput" />
        </TagsInput.Item>
        <TagsInput.Input placeholder="Add email" :class="styles.Input" />
        <TagsInput.ClearTrigger :class="styles.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'
  import styles from 'styles/tags-input.module.css'
</script>

<TagsInput.Root class={styles.Root} sanitizeValue={(value) => value.trim().toLowerCase()}>
  <TagsInput.Context>
    {#snippet render(tagsInput)}
      <TagsInput.Label class={styles.Label}>Email Addresses</TagsInput.Label>
      <TagsInput.Control class={styles.Control}>
        {#each tagsInput().value as value, index (index)}
          <TagsInput.Item {index} {value} class={styles.Item}>
            <TagsInput.ItemPreview class={styles.ItemPreview}>
              <TagsInput.ItemText class={styles.ItemText}>{value}</TagsInput.ItemText>
              <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                <XIcon />
              </TagsInput.ItemDeleteTrigger>
            </TagsInput.ItemPreview>
            <TagsInput.ItemInput class={styles.ItemInput} />
          </TagsInput.Item>
        {/each}
        <TagsInput.Input placeholder="Add email" class={styles.Input} />
        <TagsInput.ClearTrigger class={styles.ClearTrigger}>
          <XIcon />
        </TagsInput.ClearTrigger>
      </TagsInput.Control>
    {/snippet}
  </TagsInput.Context>
  <TagsInput.HiddenInput />
</TagsInput.Root>

```

### Combobox

Combine TagsInput with Combobox to create an autocomplete tags input. This pattern uses shared IDs between both
components and the `asChild` prop to compose the inputs together.

**Example: with-combobox**

#### React

```tsx
import { Combobox, useCombobox, useListCollection } from '@ark-ui/react/combobox'
import { useFilter } from '@ark-ui/react/locale'
import { Portal } from '@ark-ui/react/portal'
import { TagsInput, useTagsInput } from '@ark-ui/react/tags-input'
import { CheckIcon, XIcon } from 'lucide-react'
import { useId } from 'react'
import combobox from 'styles/combobox.module.css'
import styles from 'styles/tags-input.module.css'

export const WithCombobox = () => {
  const { contains } = useFilter({ sensitivity: 'base' })

  const { collection, filter } = useListCollection({
    initialItems: ['React', 'Solid', 'Vue', 'Svelte', 'Angular', 'Preact', 'Next.js', 'Astro', 'Nuxt'],
    filter: contains,
  })

  const uid = useId()

  const tagsInput = useTagsInput({
    ids: { input: `input_${uid}`, control: `control_${uid}` },
  })

  const comboboxApi = useCombobox({
    ids: { input: `input_${uid}`, control: `control_${uid}` },
    collection,
    onInputValueChange(details) {
      filter(details.inputValue)
    },
    value: [],
    allowCustomValue: true,
    onValueChange: (details) => {
      if (details.value[0]) {
        tagsInput.addValue(details.value[0])
      }
    },
    selectionBehavior: 'clear',
  })

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

      <Portal>
        <Combobox.Positioner>
          <Combobox.Content className={combobox.Content}>
            <Combobox.Empty className={combobox.Item}>No frameworks found</Combobox.Empty>
            {collection.items.map((item) => (
              <Combobox.Item className={combobox.Item} key={item} item={item}>
                <Combobox.ItemText className={combobox.ItemText}>{item}</Combobox.ItemText>
                <Combobox.ItemIndicator className={combobox.ItemIndicator}>
                  <CheckIcon />
                </Combobox.ItemIndicator>
              </Combobox.Item>
            ))}
          </Combobox.Content>
        </Combobox.Positioner>
      </Portal>
    </Combobox.RootProvider>
  )
}

```

#### Solid

```tsx
import { Combobox, useCombobox, useListCollection } from '@ark-ui/solid/combobox'
import { useFilter } from '@ark-ui/solid/locale'
import { TagsInput, useTagsInput } from '@ark-ui/solid/tags-input'
import { CheckIcon, XIcon } from 'lucide-solid'
import { For, createUniqueId } from 'solid-js'
import { Portal } from 'solid-js/web'
import combobox from 'styles/combobox.module.css'
import styles from 'styles/tags-input.module.css'

export const WithCombobox = () => {
  const filterFn = useFilter({ sensitivity: 'base' })

  const { collection, filter } = useListCollection({
    initialItems: ['React', 'Solid', 'Vue', 'Svelte', 'Angular', 'Preact', 'Next.js', 'Astro', 'Nuxt'],
    filter: filterFn().contains,
  })

  const uid = createUniqueId()

  const tagsInput = useTagsInput({
    ids: { input: `input_${uid}`, control: `control_${uid}` },
  })

  const comboboxApi = useCombobox({
    ids: { input: `input_${uid}`, control: `control_${uid}` },
    collection: collection(),
    onInputValueChange(details) {
      filter(details.inputValue)
    },
    value: [],
    allowCustomValue: true,
    onValueChange: (details) => {
      if (details.value[0]) {
        tagsInput().addValue(details.value[0])
      }
    },
    selectionBehavior: 'clear',
  })

  return (
    <Combobox.RootProvider value={comboboxApi}>
      <TagsInput.RootProvider class={styles.Root} value={tagsInput}>
        <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
        <TagsInput.Control class={styles.Control}>
          <For each={tagsInput().value}>
            {(value, index) => (
              <TagsInput.Item index={index()} value={value} class={styles.Item}>
                <TagsInput.ItemPreview class={styles.ItemPreview}>
                  <TagsInput.ItemText class={styles.ItemText}>{value}</TagsInput.ItemText>
                  <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}>
                    <XIcon />
                  </TagsInput.ItemDeleteTrigger>
                </TagsInput.ItemPreview>
                <TagsInput.ItemInput class={styles.ItemInput} />
              </TagsInput.Item>
            )}
          </For>
          <Combobox.Input
            asChild={(props) => <TagsInput.Input placeholder="Add Framework" class={styles.Input} {...props()} />}
          />
          <TagsInput.ClearTrigger class={styles.ClearTrigger}>
            <XIcon />
          </TagsInput.ClearTrigger>
        </TagsInput.Control>
        <TagsInput.HiddenInput />
      </TagsInput.RootProvider>

      <Portal>
        <Combobox.Positioner>
          <Combobox.Content class={combobox.Content}>
            <Combobox.Empty class={combobox.Item}>No frameworks found</Combobox.Empty>
            <For each={collection().items}>
              {(item) => (
                <Combobox.Item class={combobox.Item} item={item}>
                  <Combobox.ItemText class={combobox.ItemText}>{item}</Combobox.ItemText>
                  <Combobox.ItemIndicator class={combobox.ItemIndicator}>
                    <CheckIcon />
                  </Combobox.ItemIndicator>
                </Combobox.Item>
              )}
            </For>
          </Combobox.Content>
        </Combobox.Positioner>
      </Portal>
    </Combobox.RootProvider>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { Combobox, useCombobox, useListCollection } from '@ark-ui/vue/combobox'
import { useFilter } from '@ark-ui/vue/locale'
import { TagsInput, useTagsInput } from '@ark-ui/vue/tags-input'
import { CheckIcon, XIcon } from 'lucide-vue-next'
import { useId } from 'vue'
import combobox from 'styles/combobox.module.css'
import styles from 'styles/tags-input.module.css'

const filters = useFilter({ sensitivity: 'base' })

const { collection, filter } = useListCollection({
  initialItems: ['React', 'Solid', 'Vue', 'Svelte', 'Angular', 'Preact', 'Next.js', 'Astro', 'Nuxt'],
  filter: filters.value.contains,
})

const uid = useId()

const tagsInput = useTagsInput({
  ids: { input: `input_${uid}`, control: `control_${uid}` },
})

const comboboxApi = useCombobox({
  ids: { input: `input_${uid}`, control: `control_${uid}` },
  get collection() {
    return collection.value
  },
  onInputValueChange(details) {
    filter(details.inputValue)
  },
  value: [],
  allowCustomValue: true,
  onValueChange: (details) => {
    if (details.value[0]) {
      tagsInput.value.addValue(details.value[0])
    }
  },
  selectionBehavior: 'clear',
})
</script>

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

    <Teleport to="body">
      <Combobox.Positioner>
        <Combobox.Content :class="combobox.Content">
          <Combobox.Empty :class="combobox.Item">No frameworks found</Combobox.Empty>
          <Combobox.Item v-for="item in collection.items" :key="item" :item="item" :class="combobox.Item">
            <Combobox.ItemText :class="combobox.ItemText">{{ item }}</Combobox.ItemText>
            <Combobox.ItemIndicator :class="combobox.ItemIndicator">
              <CheckIcon />
            </Combobox.ItemIndicator>
          </Combobox.Item>
        </Combobox.Content>
      </Combobox.Positioner>
    </Teleport>
  </Combobox.RootProvider>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Combobox, useCombobox, useListCollection } from '@ark-ui/svelte/combobox'
  import { useFilter } from '@ark-ui/svelte/locale'
  import { Portal } from '@ark-ui/svelte/portal'
  import { TagsInput, useTagsInput } from '@ark-ui/svelte/tags-input'
  import { CheckIcon, XIcon } from 'lucide-svelte'
  import combobox from 'styles/combobox.module.css'
  import styles from 'styles/tags-input.module.css'

  const filters = useFilter({ sensitivity: 'base' })

  const { collection, filter } = useListCollection({
    initialItems: ['React', 'Solid', 'Vue', 'Svelte', 'Angular', 'Preact', 'Next.js', 'Astro', 'Nuxt'],
    filter(itemString, filterText) {
      return filters().contains(itemString, filterText)
    },
  })

  const uid = $props.id()

  const tagsInput = useTagsInput({
    ids: { input: `input_${uid}`, control: `control_${uid}` },
  })

  const comboboxApi = useCombobox({
    ids: { input: `input_${uid}`, control: `control_${uid}` },
    get collection() {
      return collection()
    },
    onInputValueChange(details) {
      filter(details.inputValue)
    },
    value: [],
    allowCustomValue: true,
    onValueChange: (details) => {
      if (details.value[0]) {
        tagsInput().addValue(details.value[0])
      }
    },
    selectionBehavior: 'clear',
  })
</script>

<Combobox.RootProvider value={comboboxApi}>
  <TagsInput.RootProvider class={styles.Root} value={tagsInput}>
    <TagsInput.Label class={styles.Label}>Frameworks</TagsInput.Label>
    <TagsInput.Control class={styles.Control}>
      {#each tagsInput().value as value, index (index)}
        <TagsInput.Item {index} {value} class={styles.Item}>
          <TagsInput.ItemPreview class={styles.ItemPreview}>
            <TagsInput.ItemText class={styles.ItemText}>{value}</TagsInput.ItemText>
            <TagsInput.ItemDeleteTrigger class={styles.ItemDeleteTrigger}><XIcon /></TagsInput.ItemDeleteTrigger>
          </TagsInput.ItemPreview>
          <TagsInput.ItemInput class={styles.ItemInput} />
        </TagsInput.Item>
      {/each}
      <Combobox.Input>
        {#snippet asChild(inputProps)}
          <TagsInput.Input placeholder="Add Framework" class={styles.Input} {...inputProps()} />
        {/snippet}
      </Combobox.Input>
      <TagsInput.ClearTrigger class={styles.ClearTrigger}><XIcon /></TagsInput.ClearTrigger>
    </TagsInput.Control>
    <TagsInput.HiddenInput />
  </TagsInput.RootProvider>

  <Portal>
    <Combobox.Positioner>
      <Combobox.Content class={combobox.Content}>
        <Combobox.Empty class={combobox.Item}>No frameworks found</Combobox.Empty>
        {#each collection().items as item (item)}
          <Combobox.Item class={combobox.Item} {item}>
            <Combobox.ItemText class={combobox.ItemText}>{item}</Combobox.ItemText>
            <Combobox.ItemIndicator class={combobox.ItemIndicator}><CheckIcon /></Combobox.ItemIndicator>
          </Combobox.Item>
        {/each}
      </Combobox.Content>
    </Combobox.Positioner>
  </Portal>
</Combobox.RootProvider>

```

## Guides

### Navigation

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` |
| `placeholder` | `string` | No | The placeholder text for the input |
| `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. |


**ItemDeleteTrigger Data Attributes:**

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


**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` |
| `placeholder` | `string` | No | The placeholder text for the input |
| `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. |


**ItemDeleteTrigger Data Attributes:**

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


**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 |
| `placeholder` | `string` | No | The placeholder text for the input when there are no tags |
| `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. |


**ItemDeleteTrigger Data Attributes:**

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


**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` |
| `placeholder` | `string` | No | The placeholder text for the input |
| `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 |  |


**ItemDeleteTrigger Data Attributes:**

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


**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

**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" />