Tag Editor
An interactive input that manages a list of string tags. Type and press Enter to add a tag; remove them with the × button or Backspace. Supports static and async autocomplete suggestions, drag-and-drop reordering, and custom renderers.
Import
import {TagEditor} from '@atom-forge/ui';
Basic usage
<script lang="ts">
let tags = $state(['svelte', 'typescript']);
</script>
<TagEditor bind:value={tags} placeholder="Add tag…" />
Props
| Prop |
Type |
Default |
Description |
value |
string[] |
[] |
Bindable list of tags. |
placeholder |
string |
'Add tags...' |
Shown when no tags are present. |
disabled |
boolean |
false |
Disables all interaction. |
clearable |
boolean |
false |
Shows a clear-all button when tags are present. |
allowNew |
boolean |
true |
When false, only values from options can be added. |
sortable |
boolean |
false |
Enables drag-and-drop reordering. |
uppercase |
boolean |
— |
Normalizes every tag to uppercase. Mutually exclusive with lowercase. |
lowercase |
boolean |
— |
Normalizes every tag to lowercase. Mutually exclusive with uppercase. |
primary |
boolean |
true |
Primary default chip color. Mutually exclusive with other chip colors. |
secondary |
boolean |
— |
Secondary default chip color. Mutually exclusive with other chip colors. |
danger |
boolean |
— |
Danger default chip color. Mutually exclusive with other chip colors. |
accent |
boolean |
— |
Accent default chip color. Mutually exclusive with other chip colors. |
compact |
boolean |
— |
Compact size. Mutually exclusive with small. |
small |
boolean |
— |
Small size. Mutually exclusive with compact. |
class |
string |
— |
Extra classes forwarded to the wrapper element. |
Chip color
The built-in chip renderer uses the primary color by default. Use one chip color prop at a time:
<TagEditor bind:value={tags} />
<TagEditor bind:value={tags} secondary />
<TagEditor bind:value={tags} danger />
<TagEditor bind:value={tags} accent />
When a custom chip snippet is provided, these color props do not affect the custom chip.
Options
| Prop |
Type |
Default |
Description |
options |
string[] | ((query: string) => Promise<string[]>) |
— |
Static list or async function. Static arrays are filtered client-side; async results are debounced at 200 ms. |
When allowNew is true (default), a "Add '…'" entry appears at the top of the dropdown for new values. Set allowNew={false} to restrict to listed values only.
Snippets
chip — custom chip renderer
{#snippet chip(tag, remove)}
<span>{tag} <button onclick={remove}>×</button></span>
{/snippet}
Receives (tag: string, remove: () => void).
option — custom dropdown item renderer
{#snippet option(item, isHighlighted)}
<div class={isHighlighted ? 'bg-accent' : ''}>
{item}
</div>
{/snippet}
Receives (item: string, isHighlighted: boolean).
Keyboard
| Key |
Action |
Enter |
Confirm current input as a tag, or select the highlighted option |
ArrowDown / Up |
Navigate the options dropdown |
Escape |
Close the options dropdown |
Backspace |
Remove the last tag (when input is empty) |
Notes
- Tags are normalized (trimmed, and optionally uppercased/lowercased) before being added.
- The dropdown uses
onmousedown so clicking a suggestion does not cause the input to lose focus before the tag is added.
- When
sortable is enabled, the value binding is kept in sync with the drag order.
When to use
Use for editable string tags, with optional suggestions and free-form additions.
Alternatives
Use MultiSelect when stored IDs differ from display labels, or Chip for non-editable labels.
Setup and behavior
Render below Root: popup context is read even without suggestions. Bind string[]; additions trim, normalize, and skip empty/duplicate values, but externally supplied values are not normalized. allowNew={false} requires an options source to make additions possible; it does not validate external values. Async suggestions are delayed 200 ms but requests are not cancelled or guarded against stale results. Handle errors and request ordering in the source. Sortable items are initialized from the initial value and then write order back through an effect; later external replacements are not rebuilt into the sortable list. There is no public change event. Disabled styling does not suppress every chip removal/reorder path, so enforce read-only state at the application boundary when required.
Tag Editor
An interactive input that manages a list of string tags. Type and press
Enterto add a tag; remove them with the×button orBackspace. Supports static and async autocomplete suggestions, drag-and-drop reordering, and custom renderers.Import
import {TagEditor} from '@atom-forge/ui';Basic usage
<script lang="ts"> let tags = $state(['svelte', 'typescript']); </script> <TagEditor bind:value={tags} placeholder="Add tag…" />Props
valuestring[][]placeholderstring'Add tags...'disabledbooleanfalseclearablebooleanfalseallowNewbooleantruefalse, only values fromoptionscan be added.sortablebooleanfalseuppercasebooleanlowercase.lowercasebooleanuppercase.primarybooleantruesecondarybooleandangerbooleanaccentbooleancompactbooleansmall.smallbooleancompact.classstringChip color
The built-in chip renderer uses the primary color by default. Use one chip color prop at a time:
<TagEditor bind:value={tags} /> <TagEditor bind:value={tags} secondary /> <TagEditor bind:value={tags} danger /> <TagEditor bind:value={tags} accent />When a custom
chipsnippet is provided, these color props do not affect the custom chip.Options
optionsstring[] | ((query: string) => Promise<string[]>)When
allowNewistrue(default), a "Add '…'" entry appears at the top of the dropdown for new values. SetallowNew={false}to restrict to listed values only.Snippets
chip— custom chip renderer{#snippet chip(tag, remove)} <span>{tag} <button onclick={remove}>×</button></span> {/snippet}Receives
(tag: string, remove: () => void).option— custom dropdown item renderer{#snippet option(item, isHighlighted)} <div class={isHighlighted ? 'bg-accent' : ''}> {item} </div> {/snippet}Receives
(item: string, isHighlighted: boolean).Keyboard
EnterArrowDown / UpEscapeBackspaceNotes
onmousedownso clicking a suggestion does not cause the input to lose focus before the tag is added.sortableis enabled, thevaluebinding is kept in sync with the drag order.When to use
Use for editable string tags, with optional suggestions and free-form additions.
Alternatives
Use MultiSelect when stored IDs differ from display labels, or Chip for non-editable labels.
Setup and behavior
Render below
Root: popup context is read even without suggestions. Bindstring[]; additions trim, normalize, and skip empty/duplicate values, but externally supplied values are not normalized.allowNew={false}requires an options source to make additions possible; it does not validate external values. Async suggestions are delayed 200 ms but requests are not cancelled or guarded against stale results. Handle errors and request ordering in the source. Sortable items are initialized from the initial value and then write order back through an effect; later external replacements are not rebuilt into the sortable list. There is no public change event. Disabled styling does not suppress every chip removal/reorder path, so enforce read-only state at the application boundary when required.