Feedback

State Badge

Semantic status labels with a lightweight indicator.

State Badge

Semantic status labels with a lightweight indicator.

Feedback
ReadyPendingFailed

Install

Install
npx shadcn@latest add http://localhost:3000/r/state-badge.json

Dependencies: badge

Usage

state-badge-example.tsx
"use client"

import { StateBadge } from "@/components/ui/state-badge"

export function Example() {
  return <div className="flex gap-2"><StateBadge state="Ready" /><StateBadge state="Pending" /><StateBadge state="Failed" /></div>
}

API

StateBadge
TypeScript
type StateBadgeProps = React.ComponentProps<typeof Badge> & {
  state: string
  dot?: boolean
  labels?: Record<string, React.ReactNode>
}

function StateBadge(props: StateBadgeProps)
Source code +
components/ui/state-badge.tsx
import * as React from "react"

import { Badge, badgeVariants } from "@/components/ui/badge"
import { cn } from "cn"
import type { VariantProps } from "class-variance-authority"

type StateBadgeProps = React.ComponentProps<typeof Badge> & {
  state: string
  dot?: boolean
  labels?: Record<string, React.ReactNode>
}

function StateBadge({ state, labels, dot = true, className, ...props }: StateBadgeProps) {
  const normalized = state.toLowerCase()
  const variant: VariantProps<typeof badgeVariants>["variant"] =
    normalized.includes("error") || normalized.includes("fail") || normalized.includes("danger")
      ? "destructive"
      : normalized.includes("success") || normalized.includes("ready") || normalized.includes("active")
        ? "secondary"
        : normalized.includes("warn") || normalized.includes("pending")
          ? "outline"
          : "ghost"

  return (
    <Badge variant={variant} className={cn("gap-1.5", className)} {...props}>
      {dot && <span aria-hidden="true" className="size-1.5 rounded-full bg-current opacity-70" />}
      {labels?.[state] ?? state}
    </Badge>
  )
}

export { StateBadge }

Registry JSON ↗