Tag
A status pill where the state is always a word; the dot only supports it.
LiveNewPayment failed2026
Installation
$ pnpm dlx shadcn@latest add @ssntl/tagUsage
import { Tag } from "@/components/ui/tag"
<Tag tone="live">Live</Tag>
<Tag tone="danger">Payment failed</Tag>- State always carries a word: the dot only supports it, so it reads without color.
- live for available or done, accent for New, danger for errors; plain for years and counts.
- Don't use tags for ordinary metadata that reads fine as text.
Code
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
// Essential Design `es-tag`: a 28px pill on `secondary`. State always carries a
// word, never color alone: the dot is decorative, the text is the signal.
const tagVariants = cva(
"inline-flex h-7 shrink-0 items-center gap-2 rounded-full bg-secondary px-3 text-caption font-medium whitespace-nowrap",
{
variants: {
tone: {
neutral: "text-muted-foreground",
live: "text-green-600 dark:text-green-400 [&_[data-dot]]:bg-green-400",
accent: "text-foreground [&_[data-dot]]:bg-blue-600",
danger: "text-destructive [&_[data-dot]]:bg-destructive",
},
},
defaultVariants: { tone: "neutral" },
}
)
function Tag({
tone,
dot = tone !== "neutral" && tone !== undefined,
className,
children,
...props
}: React.ComponentProps<"span"> &
VariantProps<typeof tagVariants> & {
/** A 7px dot before the word. On by default for live, accent and danger. */
dot?: boolean
}) {
return (
<span
data-slot="tag"
className={cn(tagVariants({ tone, className }))}
{...props}
>
{dot && (
<span
aria-hidden
data-dot
className="size-1.5 shrink-0 rounded-full bg-current"
/>
)}
{children}
</span>
)
}
export { Tag, tagVariants }