Tag
A label people added themselves, which they can often remove.
Preview
tsx
import { Tag } from '@kerf-js/veneer'export function Plain() { return ( <> <Tag>frontend</Tag> <Tag>eu-west</Tag> <Tag>needs review</Tag> </> )}Installation
npm install @kerf-js/veneerTry it
Change the controls: the preview and its code update together. The address keeps what you set, so you can link to it.
Live preview
Controls
Tone
Codeupdates as you change the controls
import { Tag } from '@kerf-js/veneer'<Tag onRemove={remove}>frontend</Tag>Usage
tsx
import { Tag } from '@kerf-js/veneer'<Tag onRemove={remove}>frontend</Tag>Tones
Use tone to colour a tag.
tsx
import { Tag } from '@kerf-js/veneer'export function Tones() { return ( <> {TONES.map((tone) => ( <Tag key={tone} tone={tone} > Label </Tag> ))} </> )}const TONES = [ 'neutral', 'accent', 'positive', 'caution', 'critical', 'info',] as constWith a swatch
swatch adds a dot of colour, for categories.
tsx
import { Tag } from '@kerf-js/veneer'export function Swatches() { return ( <> <Tag tone="accent" swatch > Web </Tag> <Tag tone="positive" swatch > Platform </Tag> <Tag tone="caution" swatch > Data </Tag> <Tag tone="info" swatch > Mobile </Tag> </> )}Removable
onRemove adds the cross. When the text is an expression, pass label to name it.
tsx
import { state } from '@kerf-js/core'import { Button, Tag } from '@kerf-js/veneer'export function Removable() { const tags = state([ 'frontend', 'eu-west', 'needs review', ]) return ( <> {tags.value.map((t) => ( <Tag key={t} label={t} onRemove={() => (tags.value = tags.value.filter( (x) => x !== t, )) } > {t} </Tag> ))} {!tags.value.length && ( <Button size="sm" emphasis="ghost" tone="neutral" onClick={() => (tags.value = [ 'frontend', 'eu-west', 'needs review', ]) } > Put them back </Button> )} </> )}Adding labels
Use onRemove to give each tag a button that takes it off.
tsx
import { state } from '@kerf-js/core'import { Input, Row, Stack, Tag } from '@kerf-js/veneer'export function AddToProject() { const tags = state(['frontend', 'checkout']) const draft = state('') const add = (e: Event) => { e.preventDefault() const name = draft.value.trim() if (name && !tags.value.includes(name)) tags.value = [...tags.value, name] draft.value = '' } return ( <Stack as="form" gap="related" onSubmit={add} > <Input label="Add a label" placeholder="Type and press Enter" value={draft.value} onInput={(e: Event) => (draft.value = ( e.target as HTMLInputElement ).value) } /> <Row gap="tight"> {tags.value.map((t) => ( <Tag key={t} label={t} onRemove={() => (tags.value = tags.value.filter( (x) => x !== t, )) } > {t} </Tag> ))} </Row> </Stack> )}When to use
Accessibility
- The remove button is named "Remove" plus the tag's text.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
tone | Tone | — | Its colour. |
swatch | boolean | false | A dot of colour before the text. |
label | string | — | Names the remove button, when children is an expression. |
children | unknown | — | What it contains. |
| Event | Type | Default | Description |
|---|---|---|---|
onRemove | (() => void) | — | Adds a remove button. You take the tag out of your list. |
Parts
Every element carries a stable name, so you can style it from your own CSS: [data-scope="tag"] [data-part="swatch"]
swatchremove