Tags Input

Render tags inside an input, followed by an actual text input.

one
two

Features

  • Type in the input and press enter to add tags
  • Delete tags
  • Disable everything or disable specific tags
  • Option to only allow unique tags
  • Keyboard navigation

Anatomy

  • Root: The root container for the tags input
  • Tag: The tag container for an individual tag
  • Delete Trigger: The button container, to delete an individual tag
  • Edit: An edit container, to edit an individual tag
  • Input: The input textbox for adding new tags

Usage

Use the createTagsInput builder function.

See API Reference > createTagsInput for all available props.

    <script lang="ts">
  import { createTagsInput } from '@melt-ui/svelte'
  const {
    root,
    input,
    tag,
    deleteTrigger,
    edit,
    options,
    tags,
    selected,
    inputValue,
    inputInvalid,
    isSelected
  } = createTagsInput()
</script>

Use the return values to construct a tags-input.

    <script lang="ts">
  import { createTagsInput } from '@melt-ui/svelte'
 
  // This is a subset of return values
  const { root, input, tags, tag, deleteTrigger, edit } = createTagsInput()
</script>
 
<div {...$root}>
  {#each $tags as t}
    <div {...$tag(t)} use:tag>
      <span>{t.value}</span>
      <button {...$deleteTrigger(t)} use:deleteTrigger>x</button>
    </div>
    <div {...$edit(t)} use:edit>{t.value}</div>
  {/each}
  <input {...$input} use:input type="text" />
</div>

Adding a tag

An asynchronous add function may be passed into the builder. It is called prior to adding the tag to the $tags store.

It provides you the ability to validate the input value, set a custom id, for example from a backend or 3rd-party API, or update the value to always be uppercase, lowercase, etc.

The function definition is:

    fn: (tag: string) => Promise<Tag | undefined>

whereby tag is the input value.

A tag is an object that consists of an id and value

On resolve, if a string is returned, an id will be internally generated. The same happens when a Tag without an id is returned.

On reject or error, the input is invalidated and not added to the store.

The following example sets the id via a third-party API call and forces the tag to always be uppercase.

    <script lang="ts">
  import { createTagsInput } from '@melt-ui/svelte'
 
  const { root, input, tag, deleteTrigger } = createTagsInput({
    add: async (v: string) => {
      const response = await fetch('https://www.uuidtools.com/api/generate/v1')
 
      if (!response.ok) throw new Error('HTTP error ' + response.status)
 
      const data = await response.json()
      if (!Array.isArray(data) || data.length < 1) {
        throw new Error('Failed to get id')
      }
 
      return { id: data[0], value: v.toUpperCase() }
    }
  })
</script>

Updating a tag

An asynchronous update function may be passed into the builder. It is called prior to updating a tag in $tags store, following an edit.

It provides the ability do something before a tag is updated, such as updating the value in a backend database, setting a new id, or simply manipulating the value to be added.

The function definition is:

    fn: (tag: Tag) => Promise<Tag>.

A tag is an object that consists of an id and value

tag.value will be the new (edited) value, while tag.id will be the existing id.

On reject or error the tag is not updated.

The following example uses the existing id and sets the value to uppercase

    <script lang="ts">
  import { createTagsInput, type Tag } from '@melt-ui/svelte'
 
  const { root, input, tag, deleteTrigger, edit } = createTagsInput({
    update: async (tag: Tag) => {
      return { id: tag.id, value: tag.value.toUpperCase() }
    }
  })
</script>

Removing a tag

An asynchronous remove function may be passed into the builder. It is called prior to removing the tag from the $tags store.

It provides the ability do something before the tag is removed from $tags store, such as deleting the tag from a backend database.

The function definition is:

    fn: (tag: Tag) => Promise<boolean>

whereby tag is the tag to be removed from the $tags store.

A tag is an object that consists of an id and value

On reject, error or false, the tag is not removed from the store.

The following example disallows a tag with the value one to be deleted.

    <script lang="ts">
  import { createTagsInput, type Tag } from '@melt-ui/svelte'
 
  const { root, input, tag, deleteTrigger } = createTagsInput({
    tags: ['one', 'two'],
    remove: async (t: Tag) => {
      if (t.value === 'one') return false
      return true
    }
  })
</script>

API Reference

createTags

Props

Prop Default Type / Description
placeholder -
string

The placeholder text for the input element.

disabled false
boolean

Whether or not the tags input is disabled.

selectedTag -
{id: string, value: string}

The selected tag.

tags []
string[] | {id: string, value: string}[]

The tag items.

unique false
boolean

Whether or not the tags input should only allow unique tags.

Returned Props

Returned Prop Type Description
options
Writable<CreateTagsInputProps>

A writable store that contains the props used to create the tags input.

tags
Writable<Tag[]>

A writable store that controls the tags.

selected
Writable<Tag | null>

A writable store that controls the selected tag.

isSelected
Readable<(tag: Tag) => boolean>

A derived store that returns a function that checks if a tag is selected.

inputValue
Readable<string>

A derived store that returns the value of the input element.

inputInvalid
Readable<boolean>

A derived store that returns whether or not the input element is invalid.

root
-

The builder store used to create the tags input root.

input
-

The builder store used to create the tags input input.

tag
-

The builder store used to create the tags input tag.

deleteTrigger
-

The builder store used to create the tags input delete trigger.

edit
-

The builder store used to create the tags input edit.

root

Data Attributes

Data Attribute Value
[data-disabled]

Present when the tags input is disabled.

[data-focus]

Present if the tags input is focused.

[data-invalid]

Present if the tags input is invalid.

[data-invalid-edit]

Present if the tags input is invalid while editing a tag.

[data-melt-tags-input]

Present on all tags input elements.

tag

Props

Prop Default Type / Description
id * -
string

A unique ID for the tag

value * -
string

The tag's value

disabled false
boolean

Whether or not the tag is disabled.

Data Attributes

Data Attribute Value
[data-tag-id]

The unique ID of the tag

[data-tag-value]

The value of the tag

[data-disabled]

Present when the tag is disabled.

[data-editing]

Present if the tag is being edited.

[data-selected]

Present when the tag is selected.

[data-melt-tags-input-tag]

Present on all tag elements.

deleteTrigger

Props

Prop Default Type / Description
id * -
string

The tag ID the delete trigger will delete.

value * -
string

The tag value the delete trigger will delete.

disabled false
boolean

Whether or not the delete trigger is disabled.

Data Attributes

Data Attribute Value
[data-tag-id]

The unique ID of the tag associated with the delete trigger

[data-tag-value]

The value of the tag associated with the delete trigger.

[data-disabled]

Present when the delete trigger is disabled.

[data-selected]

Present when the delete trigger is selected.

[data-editing]

Present if the tag is being edited.

[data-melt-tags-input-delete-trigger]

Present on all delete trigger elements.

edit

Props

Prop Default Type / Description
id * -
string

The tag ID the edit trigger will edit.

value * -
string

The tag value the edit trigger will edit.

Data Attributes

Data Attribute Value
[data-tag-id]

The unique ID of the tag associated with the edit component

[data-tag-value]

The value of the tag associated with the edit component.

[data-melt-tags-input-edit]

Present on all edit elements.

input

Data Attributes

Data Attribute Value
[data-disabled]

Present when the input is disabled.

[data-focus]

Present if the input is focused.

[data-invalid]

Present if the input is invalid.

[data-melt-tags-input-input]

Present on all input elements.

Accessibility

Key Behavior
tab

Moves focus between tags and the input.

Delete

When focused on a tag, deletes it and moves focus to the right.

Backspace

When focused on a tag, deletes it and moves focus to the left. If there are no tags to the left, either the next tags gets focus, or the input.

ArrowRight

Moves focus to the next tag or input.

ArrowLeft

Moves focus to the previous tag.