Skip to content
v1.0.3

Tag

A pill for filters, tokens, and multi-select chips. Can be static, selectable (filter active), or removable with an × button.

bash
jlds add tag

Usage

html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/tag.css">
<!-- behavior layer (optional): wires up the × remove button -->
<script src="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/js/core.js" defer></script>
<script src="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/js/tag.js" defer></script>

<span class="jl-tag">Design</span>
vue
<script setup lang="ts">
import { Tag } from "@/components/ui/tag"
</script>

<template>
  <Tag>Design</Tag>
</template>
tsx
import { Tag } from "@/components/ui/tag"

<Tag>Design</Tag>

Selectable

Add selected for the active-filter style. Pair with an onClick (React) / @click (Vue) to make it a toggle button — that also adds hover affordance.

html
<span class="jl-tag jl-tag--button">All</span>
<span class="jl-tag jl-tag--button jl-tag--selected">Active</span>
<span class="jl-tag jl-tag--button">Archived</span>
vue
<template>
  <Tag :selected="filter === 'all'" @click="filter = 'all'">All</Tag>
  <Tag :selected="filter === 'active'" @click="filter = 'active'">Active</Tag>
  <Tag :selected="filter === 'archived'" @click="filter = 'archived'">Archived</Tag>
</template>
tsx
<Tag selected={filter === "all"} onClick={() => setFilter("all")}>All</Tag>
<Tag selected={filter === "active"} onClick={() => setFilter("active")}>Active</Tag>
<Tag selected={filter === "archived"} onClick={() => setFilter("archived")}>Archived</Tag>

Removable

In React, pass onRemove to render the × button. In Vue, set removable and listen for the remove event. In HTML, include the jl-tag__remove button and load the behavior layer — clicking × removes the tag.

html
<span class="jl-tag">
  react
  <button type="button" class="jl-tag__remove" aria-label="Remove">
    <svg viewBox="0 0 12 12" width="12" height="12" fill="none" aria-hidden="true">
      <path d="M3 3l6 6M9 3l-6 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
    </svg>
  </button>
</span>
vue
<template>
  <Tag removable @remove="remove('react')">react</Tag>
  <Tag removable @remove="remove('vue')">vue</Tag>
</template>
tsx
<Tag onRemove={() => remove("react")}>react</Tag>
<Tag onRemove={() => remove("vue")}>vue</Tag>

Props

React

Tag extends React.HTMLAttributes<HTMLSpanElement> (so onClick, className, etc. pass through).

PropTypeDefaultDescription
selectedbooleanfalseActive-filter styling
onRemove(e: React.MouseEvent) => voidIf set, renders an × button
iconReact.ReactNodeLeading icon node

Vue

PropTypeDefaultDescription
selectedbooleanfalseActive-filter styling
removablebooleanfalseRender an × button that emits remove

Events: remove (when the × is clicked). Slots: default (label), icon (leading). A @click handler makes the tag interactive (adds the button hover style).

CSS classes (HTML)

ClassPurpose
.jl-tagBase pill — always required
.jl-tag--buttonInteractive (cursor + hover affordance)
.jl-tag--selectedActive-filter styling
.jl-tag__removeThe × remove button