SvTagsInput

An editable token / chips input - type to add, click x or Backspace to remove.

SvTagsInput edits a string[] as a row of removable chips: type and press Enter or comma to add a tag, Backspace on an empty draft removes the last, and each chip has an x button. It can reject duplicates and cap the count. It is the styled renderer over the headless createTagsInput core, so add / remove and keyboard handling live in one place. Its label / hint / error chrome comes from SvField.

Related: SvTextInput · SvColorInput · Inputs overview

Installation

Add it with the CLI - this drops a ready-to-edit SvTagsInput starter into your app:

Prefer to see it first? npx @svgrid/ui try tags-input opens it in a throwaway sandbox - no project needed.

Or install the package and import it directly. SvTagsInput ships free in @svgrid/grid and is part of the grid's editor kit - the same control SvGrid mounts when you edit a matching cell:

The examples on this page import from @svgrid/grid:

<script lang="ts">
  import { SvTagsInput } from '@svgrid/grid'

  // The bound value behind each example below.
  let recipients = $state<string[]>([])
  let labels = $state<string[]>([])
</script>
import { SvTagsInput } from '@svgrid/grid'

Example

Open the live example: Tags input (Selection)

<script lang="ts">
  import { SvTagsInput } from '@svgrid/grid'
  let skills = $state(['Svelte', 'TypeScript'])
</script>

<SvTagsInput label="Skills" bind:value={skills} placeholder="Add a skill…" />

Props

SvTagsInput extends the shared SvEditorProps (disabled, required, invalid, error, label, hint, dir, name, id, ariaLabel) and adds:

Prop Type Default Description
value string[] [] The tags. Bindable with bind:value.
onChange (tags: string[]) => void - Fires whenever the tag set changes.
placeholder string Add tag… Shown only while there are no tags.
unique boolean true Reject duplicate tags.
max number Infinity Maximum number of tags.
messages Partial<TagsMessages> - Override the add / remove aria-labels.

TagsMessages is { add; remove }.

Examples

Cap and de-duplicate

Combine max with the default unique to keep a bounded, clean set - useful for recipients or a small skill list:

<SvTagsInput label="To" bind:value={recipients} max={5} />

React to changes

Use onChange to persist or validate as tags come and go:

<SvTagsInput bind:value={labels} onChange={(t) => save(t)} />

Required set with a minimum count

Since the value is a string[], validation is just its length. Combine required with a $derived floor and cap the total with max:

<script lang="ts">
  import { SvTagsInput } from '@svgrid/grid'
  let topics = $state<string[]>([])
  const tooFew = $derived(topics.length > 0 && topics.length < 3)
</script>

<SvTagsInput
  label="Interests"
  required
  max={8}
  bind:value={topics}
  placeholder="Add an interest…"
  invalid={topics.length === 0 || tooFew}
  error={topics.length === 0
    ? 'Add at least one interest'
    : tooFew ? 'Pick at least three' : undefined}
  hint="Up to 8 tags"
/>

Tip: unique is on by default, so duplicate entries are silently rejected - value only ever holds distinct tags, which keeps the length checks honest.

Accessibility

More examples

Tags input - headless

createTagsInput drives SvTagsInput and a custom chip-cloud render, both editing one string array.

Open the live example: Tags input - headless (Headless Editors)

Sizes

Every control takes the same three sizes, so a dense toolbar and a roomy form can share components.

<script lang="ts">
  import { SvTagsInput } from '@svgrid/grid'

  let skills = $state<string[]>([])
</script>

<SvTagsInput bind:value={skills} size="sm" />
<SvTagsInput bind:value={skills} size="md" />
<SvTagsInput bind:value={skills} size="lg" />

In a form

The shared field props behave the same on every editor: label names it, hint explains it, and error plus invalid mark it - which is why a validated form does not need per-component handling.

<script lang="ts">
  import { SvTagsInput } from '@svgrid/grid'

  let skills = $state<string[]>([])
</script>

<SvTagsInput
  bind:value={skills}
  label="Label"
  hint="A short hint"
  required
/>

<SvTagsInput
  bind:value={skills}
  label="Label"
  error="Something is wrong"
  invalid
/>

See also

Live examples

  • Tags input - SvTagsInput: a token editor (Enter / comma to add, Backspace / x to remove) with unique + max enforced - skills and email recipients with validation.
  • Tags input - headless - createTagsInput drives SvTagsInput and a custom chip-cloud render, both editing one string array.