---
title: Tag
description: A compact label for categories, filters, and states.
category: Basic
status: beta
since: 0.3.4
tags: [tag, label, badge]
syncStatus: reviewed
verified: true
---

## Usage

### Colors and Sizes
`color` sets the text color and derives the background and border.
:::TuffDemoWrapper{demo="TagTagsDemo" code-lang="vue"}
---
code: |
  <template>
    <TxTag label="Default" size="sm" />
    <TxTag label="Success" size="md" color="var(--tx-color-success)" />
    <TxTag label="Warning" size="sm" color="var(--tx-color-warning)" />
    <TxTag label="Danger" size="md" color="var(--tx-color-danger)" />
  </template>
---
:::

### Closable
`closable` renders a close button; `close` only signals intent, and the host updates the data.
:::TuffDemoWrapper{demo="TagClosableDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import { ref } from 'vue'

  const tags = ref(['Design', 'Docs', 'Pending'])
  function removeTag(tag: string) {
    tags.value = tags.value.filter(item => item !== tag)
  }
  </script>

  <template>
    <TxTag v-for="tag in tags" :key="tag" :label="tag" closable @close="removeTag(tag)" />
  </template>
---
:::

### Icon and Custom Color
`background` and `border` override the colors derived from `color`.
:::TuffDemoWrapper{demo="TagIconDemo" code-lang="vue"}
---
code: |
  <template>
    <TxTag label="AI Pick" icon="i-carbon-ai" color="#8b5cf6" />
    <TxTag label="Synced" icon="i-carbon-checkmark-filled" color="var(--tx-color-success)" />
    <TxTag label="Protected" icon="i-carbon-locked" color="#f59e0b" background="rgba(245, 158, 11, 0.14)" border="rgba(245, 158, 11, 0.36)" />
  </template>
---
:::

### Interaction and Disabled
With `@click` bound, the tag becomes a focusable button; `disabled` blocks `click` and `close`.
:::TuffDemoWrapper{demo="TagStateDemo" code-lang="vue"}
---
code: |
  <template>
    <TxTag
      :label="active ? 'Selected' : 'Clickable'"
      :color="active ? 'var(--tx-color-success)' : 'var(--tx-color-primary)'"
      @click="active = !active"
    />
    <TxTag label="Disabled" disabled />
  </template>
---
:::

### Tag + Button
:::TuffDemoWrapper{demo="TagTagButtonDemo" code-lang="vue"}
---
code: |
  <template>
    <TxTag label="Beta" size="md" />
    <TxButton size="sm">Upgrade</TxButton>
  </template>
---
:::

### Best Practices

- Use tags for metadata and state hints, not as a replacement for primary buttons.
- Keep `label` short and readable without relying on color.
- Use `closable` for removable filters, user labels, and temporary scopes.
- Pass explicit `background` / `border` when a raw custom color lacks contrast.
- Confirm removal in the host; `TxTag` only emits intent.

## API Reference

### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `label` | `string \| null` | `''` | Text shown when there is no default slot; `null` counts as empty. |
| `icon` | `string` | `''` | Leading icon class. |
| `color` | `string` | `'var(--tx-color-primary)'` | Text and icon color; the base for the derived background and border. |
| `background` | `string` | `''` | Custom background; defaults to a translucent mix of `color`. |
| `border` | `string` | `''` | Custom border; defaults to a translucent mix of `color`. |
| `size` | `'sm' \| 'md'` | `'sm'` | Tag density. |
| `closable` | `boolean` | `false` | Renders the close button. |
| `closeAriaLabel` | `string` | `'Remove tag'` | `aria-label` of the close button; pass localized text. |
| `disabled` | `boolean` | `false` | Disables click and close. |
| `pill` | `boolean` | `false` | Fully rounded pill shape, for filter chips that must differ from square tags. |
| `variant` | `'outline' \| 'soft' \| 'plain'` | `'outline'` | Fill recipe; see the table below. |
| `dot` | `string` | - | Leading dot color; no dot when omitted. |
| `dotSize` | `number` | `6` | Dot diameter in px. |
| `count` | `number` | - | Trailing count; `0` renders, omitting it renders nothing. |

| `variant` | Fill | Hairline | Text | Use |
|------|------|------|------|------|
| `outline` | 12% | 32% | Full-strength hue | Default |
| `soft` | 20% | 34% | 92% hue mixed toward ink | 11px text on a colored fill |
| `plain` | Neutral fill | Neutral hairline | Secondary ink | Ignores `color`; for overflow counters like `+3` and secondary metadata |

An explicit `background` / `border` overrides any `variant`.

### Events

| Event | Payload | Description |
|------|---------|-------------|
| `click` | `MouseEvent` | Fires on click unless disabled; with a listener bound, Enter / Space fire it too. |
| `close` | - | Fires when the close button is clicked, unless disabled. |

### Slots

| Slot | Props | Description |
|------|------|-------------|
| `default` | - | Replaces the `label` text, keeping the icon and close button. |

## Overview

- Without `@click`, the root is static metadata with no role; with it, the root is a focusable `role="button"` that carries `aria-disabled` when disabled.
- The close button is a native `button type="button"` whose `aria-label` comes from `closeAriaLabel`.
- Close clicks stop propagating, so `close` never also fires `click`.
- `disabled` lowers opacity, disables the close button, and blocks `click` and `close`.

## Technologies

- Source: `packages/tuffex/packages/components/src/tag/`.

<TuffDocSourceLink />
