Cloud|

@k2b/ui

Tag editing

Reusable tag presentation, entity management, and assignment composition.

Tag@k2b/uiTagEditor@k2b/uiMultiSelectInput@k2b/ui

Tag owns compact presentation; TagEditor owns accessible create/edit/delete interaction while the application owns persistence and confirmation. MultiSelectInput assigns existing tags and accepts custom option/value rendering.

PlatformDesignNeutralSelected
  • Platform
  • Design
Assigned tags

TSX

Copy
const [tags, setTags] = createSignal<TagEditorItem[]>(initialTags);
<Tag color="#0891b2">Platform</Tag>
<Tag color="#8b5cf6" icon="ti ti-palette">Design</Tag>
<Tag size="sm">Neutral</Tag>
<Tag color="#2563eb" icon="ti ti-point" selected size="lg">Selected</Tag>
<TagEditor
items={tags()}
onCreate={async (value) => setTags((items) => [...items, { id: crypto.randomUUID(), ...value }])}
onUpdate={async (tag, value) => setTags((items) => items.map((item) => item.id === tag.id ? { ...item, ...value } : item))}
onDelete={async (tag) => setTags((items) => items.filter((item) => item.id !== tag.id))}
/>
<MultiSelectInput
label="Assigned tags"
value={selected}
onValueChange={setSelected}
options={tags().map((tag) => ({ value: tag.id, label: tag.name, color: tag.color }))}
renderValue={(option) => <strong>{option.label}</strong>}
renderOption={(option) => <TagOption option={option} />}
searchPlaceholder="Search tags..."
emptyLabel="No tags available"
noResultsLabel="No matching tags"
clearable
/>

Tag, TagEditor, and MultiSelectInput separate presentation, entity management, and assignment.

Use tag editing

Use TagEditor for managed tag entities with stable ids. Use MultiSelectInput to assign existing ids. Keep TagsInput for a freeform comma-separated string list.

Import

tsx
import { MultiSelectInput, Tag, TagEditor, type TagEditorItem } from "@k2b/ui";

Ownership

Tag owns compact passive and selected presentation. Set selected when the surrounding control represents the current value; the selected treatment uses a stronger surface, label weight, and a check, so it does not depend on color alone. Passing either true or false reserves the same icon slot and keeps the tag geometry stable while selection changes. Tag remains presentation-only: the surrounding link or button owns href, activation, aria-current, or aria-pressed.

TagEditor is controlled and backend-free. It owns create/edit/delete interaction, busy state, focus, and inline errors. The application owns persistence, authorization, uniqueness, confirmation, toasts, sorting, and reconciliation. A rejected async callback keeps the editor open. A missing callback hides that capability.

Use onDirtyChange when a surrounding settings surface guards navigation or closing. It reports whether the currently open create or edit form differs from its initial value and returns to false after save, cancel, or cleanup. It does not report pending persistence or compare the controlled items collection.

MultiSelectInput accepts renderOption and renderValue for richer labels while retaining the package-owned selection and removal semantics.

Accessibility

Edit and delete buttons name the affected tag. Forms use the common field contract and announce errors. Do not rely on tag color alone; keep a readable name.

Runtime

Interactive editing and selection require hydration. The initial list and tags render on the server.

Example

tsx
<Tag color="#2563eb" icon="ti ti-point" selected size="lg">
  Platform
</Tag>

<TagEditor
  items={tags()}
  onCreate={createTag}
  onUpdate={updateTag}
  onDelete={async (tag) => {
    if (await confirmDelete(tag)) await deleteTag(tag);
  }}
  onDirtyChange={setTagEditorDirty}
/>

<MultiSelectInput
  label="Assigned tags"
  value={tagIds}
  onValueChange={setTagIds}
  options={tags().map((tag) => ({ value: tag.id, label: tag.name, color: tag.color }))}
/>

Connect a coding agent

The Cloud skill provides compact working instructions. MCP supplies exact current documentation when details matter.

CLI command
bunx skills add https://docs.example.com

This command installs the working instructions published by this website in the selected coding agent.

For exact, current details, also connect the MCP server through one of the agent tabs.

Installation uses the open-source Vercel Skills CLI.

The skill and MCP complement each other: the skill describes workflows, while MCP supplies current documentation.