shadcn, restyled · @jengacore/badge
Badge
Tones success, warning, danger, info, neutral, outline and brand. Accepts the shadcn `variant` names too.
SettledPendingRejectedIn reviewDraftGoods not receivedIn progress
Install
terminal
npx shadcn@latest add @jengacore/badgeWithout the namespace configured: npx shadcn@latest add https://ui.jengacore.com/r/<new-york-v4|base-nova>/badge.json
Registry dependencies
npm packages
class-variance-authority
Source
components/ui/badge.tsx
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
/**
* jengacore Badge. Status is always icon + word (use StatusBadge for domain statuses);
* colour is never the only signal. `variant` keeps the shadcn API, `tone` is the jengacore one.
*/
const badgeVariants = cva(
"inline-flex h-[22px] w-fit shrink-0 items-center gap-[5px] overflow-hidden rounded-sm px-[7px] text-xs font-medium whitespace-nowrap [&>svg]:pointer-events-none [&>svg]:size-3 [&>svg]:stroke-2",
{
variants: {
tone: {
neutral: "bg-muted text-foreground/85",
success: "bg-success-subtle text-success",
warning: "bg-warning-subtle text-warning",
danger: "bg-destructive-subtle text-destructive",
info: "bg-info-subtle text-info",
/** Brand label that is not a status (a role, a module, "Recommended"). */
primary: "bg-secondary text-secondary-foreground",
outline: "border border-border text-muted-foreground contrast:border-input",
ghost: "text-muted-foreground",
link: "text-primary underline-offset-4 hover:underline",
/** Deck and marketing tag ("IN PROGRESS"). Not for system status. */
brand: "bg-forest-900 px-2 text-[11px] font-semibold tracking-[0.06em] text-white uppercase",
},
},
defaultVariants: { tone: "neutral" },
}
)
type Tone = NonNullable<VariantProps<typeof badgeVariants>["tone"]>
/** The tone names, for status dictionaries that map a word to a tone. */
export type BadgeTone = Tone
/** shadcn variant names, mapped onto jengacore tones. */
const VARIANT_TONE: Record<string, Tone> = {
default: "neutral",
secondary: "neutral",
destructive: "danger",
outline: "outline",
ghost: "ghost",
link: "link",
}
function Badge({
className,
tone,
variant,
...props
}: React.ComponentProps<"span"> &
VariantProps<typeof badgeVariants> & {
variant?: "default" | "secondary" | "destructive" | "outline" | "ghost" | "link" | null
}) {
const resolved = tone ?? (variant ? VARIANT_TONE[variant] : undefined)
return (
<span
data-slot="badge"
data-tone={resolved ?? "neutral"}
className={cn(badgeVariants({ tone: resolved }), className)}
{...props}
/>
)
}
export { Badge, badgeVariants }