feat(frontend): add EmptyState primitive

This commit is contained in:
Tyler
2026-06-19 19:35:59 -06:00
parent f094b250b5
commit fb6730813f
+63
View File
@@ -0,0 +1,63 @@
import * as React from "react";
import { Inbox } from "lucide-react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
type EmptyStateProps = {
/** All-caps instrument label, e.g. "Claims · inbox idle". */
eyebrow?: string;
/** One-line plain-language message. No apologetic language. */
message: string;
/** Optional action surfaced as a small outline button. */
action?: { label: string; onClick: () => void };
/** Override the default inbox icon. */
icon?: React.ReactNode;
className?: string;
};
/**
* Empty surface state.
* Voice: instrument-label eyebrow + a one-line message + optional action.
* Quiet. Hairline. No apology copy.
*/
export function EmptyState({
eyebrow,
message,
action,
icon,
className,
}: EmptyStateProps) {
return (
<div
className={cn(
"flex flex-col items-center justify-center gap-2.5 py-14 text-center",
className,
)}
>
<div
aria-hidden
className="h-10 w-10 rounded-full ring-1 ring-inset ring-border/60 flex items-center justify-center text-muted-foreground"
>
{icon ?? <Inbox className="h-4 w-4" strokeWidth={1.5} />}
</div>
{eyebrow ? (
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
{eyebrow}
</div>
) : null}
<div className="text-sm text-muted-foreground/80 max-w-sm">
{message}
</div>
{action ? (
<Button
variant="outline"
size="sm"
onClick={action.onClick}
className="mt-1.5"
>
{action.label}
</Button>
) : null}
</div>
);
}