Markdown:
Components

TagsInput

An input component for adding, removing, and managing multiple tags or labels.

tags input value

Usage

Use standalone, or inside TagsInputField.

Svelte
<TagsInput {...props} />

Anatomy

The class attribute values represent part names, and conditional indicates elements that are rendered conditionally. Other attributes represent their corresponding props.

Svelte
<div class="whole">
  <span class="aux" conditional>
    {#each values as text, i}
      <span class="label">
        {#if label}
          {label}
        {:else}
          {text}
        {/if}
        <button class="extra" type="button" aria-label={removeAriaLabel(text)}>
          {#if extra}
            {extra}
          {:else}
            <svg aria-hidden="true" focusable="false">Default Icon</svg>
          {/if}
        </button>
      </span>
    {/each}
  </span>
  <input class="main" {...rest} type="text" aria-invalid aria-errormessage bind:value bind:this={element} />
</div>

Props

NameTypeDefaultDescription
labelSnippet-Tag label content; receives value and variant
extraSnippet-Remove-button content; receives value and variant
valuesstring[]-Bindable tag values
valuestring-Bindable current input value
side<enum>"left"When set to "right", swaps the positions of the tags and the input element
removeAriaLabelfunction-Function that creates the accessible label for each remove button; defaults to Remove ${text}
separatorstring[][",", "\n"]Characters that split input into tags
pastebooleantrueWhen true, pasted text containing separators is split into multiple tags
trimbooleantrueTrims whitespace from tag text when adding
uniquebooleantrueWhen true, duplicate values are ignored
ariaErrMsgIdstring-Error-message element ID for aria-errormessage
eventsTagsInputEvents-Functions that can filter which added or removed tags are committed
attachAttachment-Svelte attachment on the input
elementHTMLInputElement-Bindable input element
stylingSVSClass-Styling override
variantSVSVariantNEUTRALVariant

Other HTMLInputAttributes are passed to <input> via rest props; class is merged onto the control.

Input attributes such as placeholder and maxlength are passed at the top level.

Styling

To learn more, see Styling.

Variant Management

No automatic switching.

Default Class Name

svs-tags-input

Behavior

Typing a separator commits the segment before it; Enter commits the current input after splitting on separators; pasting text containing a separator commits every segment of the post-paste value and clears the input. With paste:false, pasted text is inserted natively and not split. trim and unique apply per segment, empty segments are dropped, and onadd fires once per commit with the full batch. Default separators are "," and "\n"; Windows \r\n pastes keep \r only when trim:false.

Accessibility

Keyboard Interactions

KeyDescription
EnterCommits the current input after splitting it on the configured separators

Typing a configured separator commits the segment before it. IME composition is ignored for both Enter handling and separator-based input splitting.

ARIA Roles and Attributes

The component applies these automatically:

  • Input (main): aria-describedby, aria-invalid, and aria-errormessage from the surrounding TagsInputField context or passed attributes.
  • Remove button (extra): aria-label from removeAriaLabel, defaulting to Remove ${text}.
  • Default remove icon: aria-hidden="true" and focusable="false".

Provide an accessible name for the input yourself because there is no built-in visible label. Pass aria-label or aria-labelledby through the rest props, or use TagsInput inside a labelled TagsInputField.

Exports

Types

TypeScript
interface TagsInputEvents extends CollectionEvents<string> {}
interface CollectionEvents<T> {
  // Return the subset to commit: undefined => all, [] => none.
  onadd?: (detail: { values: T[]; added: T[] }) => T[] | void;
  onremove?: (detail: { values: T[]; removed: T[] }) => T[] | void;
}
interface TagsInputProps extends Omit<HTMLInputAttributes, "type" | "value"> {
  label?: Snippet<[string, string]>; // Snippet<[value,variant]>
  extra?: Snippet<[string, string]>; // Snippet<[value,variant]>
  values?: string[]; // bindable
  value?: string; // bindable
  side?: "left" | "right"; // ("left")
  removeAriaLabel?: (text: string) => string; // ((text) => `Remove ${text}`)
  separator?: string | string[]; // ([",", "\n"]) - characters that split input into tags
  paste?: boolean; // (true) - split pasted text on separators into multiple tags
  trim?: boolean; // (true)
  unique?: boolean; // (true)
  ariaErrMsgId?: string;
  events?: TagsInputEvents;
  attach?: Attachment<HTMLInputElement>;
  element?: HTMLInputElement; // bindable
  styling?: SVSClass;
  variant?: SVSVariant; // (VARIANT.NEUTRAL)
  // class & other HTMLInputAttributes are passed to <input> via ...rest (class is merged onto the control)
}
type TagsInputReqdProps = never;
type TagsInputBindProps = "values" | "value" | "element";

Others

No additional exports are available.

Examples

The example code uses Tailwind CSS along with SVSClass.

Basic

tags input value

With Interactive Variant

Preset for Demo
Enter variant as you like
apple orange