Feedbackui
Status indicator
Dot and label for deployment and service states.
ReadyBuildingQueuedErrorCanceledDegradedMaintenanceOffline
Installation
npx shadcn@latest add @particular/status-indicatornpm dependencies
- class-variance-authority@^0.7.1
- cn@^0.4.0
Source
import * as React from "react"
import { cva } from "class-variance-authority"
import { cn } from "cn"
const statuses = {
ready: "Ready",
building: "Building",
queued: "Queued",
error: "Error",
canceled: "Canceled",
degraded: "Degraded",
maintenance: "Maintenance",
offline: "Offline",
} as const
type Status = keyof typeof statuses
const dotVariants = cva("relative inline-flex size-2 shrink-0 rounded-full", {
variants: {
status: {
ready: "bg-success",
building: "bg-warning",
queued: "bg-muted-foreground/60",
error: "bg-destructive",
canceled: "bg-muted-foreground/40",
degraded: "bg-warning",
maintenance: "bg-info",
offline: "bg-muted-foreground/40",
},
},
})
const pulsing = new Set<Status>(["building", "queued"])
function StatusDot({
status,
className,
...props
}: React.ComponentProps<"span"> & { status: Status }) {
return (
<span
aria-hidden
data-slot="status-dot"
data-status={status}
className={cn(dotVariants({ status }), className)}
{...props}
>
{pulsing.has(status) && (
<span className="absolute inset-0 animate-ping rounded-full bg-inherit opacity-75 motion-reduce:animate-none" />
)}
</span>
)
}
function StatusIndicator({
status,
label,
className,
...props
}: Omit<React.ComponentProps<"span">, "children"> & {
status: Status
/** Visible text. Defaults to the status name; `false` keeps it for screen readers only. */
label?: React.ReactNode | false
}) {
const text = label === false || label === undefined ? statuses[status] : label
return (
<span
data-slot="status-indicator"
data-status={status}
className={cn("inline-flex items-center gap-2 text-sm", className)}
{...props}
>
<StatusDot status={status} />
<span className={cn(label === false && "sr-only")}>{text}</span>
</span>
)
}
export { StatusIndicator, StatusDot, statuses, type Status }