Skip to content
kerfjsGitHub

Tag

A label people added themselves, which they can often remove.

SourcePackage @kerf-js/veneerTry it

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/veneer

Try 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 const

With 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

Use it for

  • Labels people choose or type
  • A list of values with a remove button

Reach for something else

  • Badge, when the app set the status
  • Chip, when it filters when pressed

Accessibility

  • The remove button is named "Remove" plus the tag's text.

API Reference

PropTypeDefaultDescription
toneTone—Its colour.
swatchbooleanfalseA dot of colour before the text.
labelstring—Names the remove button, when children is an expression.
childrenunknown—What it contains.
EventTypeDefaultDescription
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

RelatedBadgeChip