# Tag

> Un dato que puso el usuario y puede sacar: un filtro, una etiqueta, un destinatario.

```tsx
import { Tag } from "sebs7n-ui/tag"
```

Sin `"use client"`: sirve en un Server Component.

## Ejemplos

### Filtros aplicados

Un dato que puso el usuario: por eso se puede sacar.

```tsx
import { Button } from "sebs7n-ui/button"
import { Tag } from "sebs7n-ui/tag"
import { useState } from "react"

function Filtros() {
  const [filtros, setFiltros] = useState(["Pendientes", "Acme S.A.", "Septiembre"])
  return (
    <div className="flex w-full flex-col items-start gap-3">
      <div aria-live="polite" className="flex min-h-6 flex-wrap items-center gap-2">
        {filtros.map((filtro) => (
          <Tag key={filtro} onRemove={() => setFiltros((previos) => previos.filter((otro) => otro !== filtro))}>
            {filtro}
          </Tag>
        ))}
        {filtros.length === 0 && <span className="text-callout text-label-secondary">Sin filtros</span>}
      </div>
      <Button disabled={filtros.length === 3} onClick={() => setFiltros(["Pendientes", "Acme S.A.", "Septiembre"])} size="sm" variant="secondary">
        Restaurar
      </Button>
    </div>
  )
}
```

### Colores y tamaños

La misma paleta del Badge: el sistema tiene una sola forma de etiqueta.

```tsx
import { Tag } from "sebs7n-ui/tag"

function ColoresYTamanos() {
  return (
    <div className="flex flex-col gap-3">
      <div className="flex flex-wrap items-center gap-2">
        <Tag onRemove={() => {}}>Sin color</Tag>
        <Tag color="brand" onRemove={() => {}}>
          Marca
        </Tag>
        <Tag color="green" onRemove={() => {}}>
          Cobrado
        </Tag>
        <Tag color="purple" onRemove={() => {}}>
          Diseño
        </Tag>
      </div>
      <div className="flex flex-wrap items-center gap-2">
        <Tag onRemove={() => {}} size="sm">
          Chico
        </Tag>
        <Tag size="sm">Sin quitar</Tag>
      </div>
    </div>
  )
}
```

### Badge o Tag

El estado lo calculó el sistema y no se saca: Badge. El filtro lo puso el usuario: Tag.

```tsx
import { Badge } from "sebs7n-ui/badge"
import { Tag } from "sebs7n-ui/tag"

function BadgeOTag() {
  return (
    <div className="flex flex-col gap-3 text-callout text-label-secondary">
      <div className="flex flex-wrap items-center gap-2">
        <span className="w-28">Estado:</span>
        <Badge color="green">Pagada</Badge>
        <Badge color="amber">Pendiente</Badge>
      </div>
      <div className="flex flex-wrap items-center gap-2">
        <span className="w-28">Filtros:</span>
        <Tag color="green" onRemove={() => {}}>
          Pagadas
        </Tag>
        <Tag onRemove={() => {}}>Últimos 30 días</Tag>
      </div>
    </div>
  )
}
```

## Props

### Tag

Hereda las props de `<span>`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `color` | `"brand" \| "gray" \| "red" \| "amber" \| "green" \| "blue" \| "teal" \| "purple" \| "pink"` | `"gray"` | Los mismos nueve tonos del Badge. |
| `onRemove` | `() => void` | — | Qué hacer al quitar. Sin esto no aparece el botón — y sin botón, probablemente sea un `Badge`. |
| `removeLabel` | `string \| ((name: string) => string)` | `"Quitar"` | Nombre del botón de quitar. Un string es el prefijo del dato («Quitar» → «Quitar Chile»); una función recibe el dato y devuelve la frase entera, que es lo único que sirve donde el verbo no va adelante: `(name) => name + " entfernen"`. |
| `size` | `"sm" \| "md"` | `"md"` | Las dos alturas del `Badge`: `sm` 16px · `md` 20px. El botón de quitar mide 12 y 16, con área de 24. |
| `textValue` | `string` | — | El texto del tag para el nombre del botón, cuando `children` no es texto. |
| `className` | `string` | — | Se fusiona con las clases del componente vía `cn()` (tailwind-merge): lo que pongas gana. |

## Teclado

| Tecla | Qué hace |
|---|---|
| Tab | Entra al botón de quitar. El cuerpo del tag no es interactivo. |
| Enter · Espacio | Quita el tag. |

## Accesibilidad

- El botón de quitar siempre tiene nombre accesible: «Quitar Chile», armado con el texto del tag. Si `children` no es texto, pasale `textValue`; si el idioma no pone el verbo adelante, `removeLabel` acepta una función y arma la frase entera.
- El cuerpo es un `<span>`: lo único enfocable es el botón, así que una lista de diez tags son diez paradas de tabulación, no veinte.
- Quitar un tag saca el foco de la página. Devolvelo al contenedor de la lista o al control que los genera, y anunciá el cambio con una región `aria-live` si la lista es lo único que cambió.
- El color no puede ser la única señal de nada: el texto del tag es el dato.
- Sin `"use client"`: sirve en un Server Component (aunque `onRemove` lo pasa, por definición, un componente cliente).

## Reglas de uso

- **Badge informa, Tag es un dato.** El `Badge` cuenta un estado que calculó el sistema y que el usuario no eligió ni puede sacar («Pagada», «Vencida», «Admin»). El `Tag` es algo que el usuario puso —un filtro aplicado, una etiqueta, un destinatario— y por eso se puede quitar. **Si tiene ×, es Tag; si no se puede sacar, es Badge.**
- Comparte forma y paleta con `Badge` a propósito —sólido, sin borde, 4 px de radio—: el sistema tiene una sola forma de etiqueta. Lo que cambia es qué significa, no el radio.
- Dentro de un `Combobox` múltiple ya está `ComboboxChip`, conectado al estado del combobox: ahí no va `Tag`.
- `size="sm"` dentro de una fila de tabla; `md` suelto, arriba de una lista de resultados.
- Si la etiqueta además filtra al hacer click en el cuerpo, eso es un `Toggle`, no un Tag con `onClick`.

## Relacionados

[badge](/docs/components/badge.md) · [combobox](/docs/components/combobox.md) · [toggle](/docs/components/toggle.md)
