Tags Input
Render tags inside an input, followed by an actual text input.
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. |
On This Page