feat(frontend): ClaimDrawer skeleton + error states

This commit is contained in:
Tyler
2026-06-20 11:09:41 -06:00
parent 7dbcba8fa3
commit 67653f0da8
5 changed files with 388 additions and 2 deletions
@@ -0,0 +1,62 @@
import { AlertCircle, WifiOff } from "lucide-react";
import { Button } from "@/components/ui/button";
type ClaimDrawerErrorProps = {
kind: "not_found" | "network";
onRetry?: () => void;
onClose: () => void;
};
const COPY = {
not_found: {
eyebrow: "NOT FOUND",
message: "This claim doesn't exist or has been removed.",
},
network: {
eyebrow: "CONNECTION",
message: "Couldn't reach the server. Check your connection and try again.",
},
} as const;
/**
* Error state for the claim detail drawer (SP4).
*
* Two shapes — `not_found` (the claim id in the URL doesn't resolve on
* the server, e.g. a stale deep link) and `network` (the request
* failed). The not_found variant has no retry affordance (retrying won't
* help), the network variant does when `onRetry` is supplied.
*/
export function ClaimDrawerError({ kind, onRetry, onClose }: ClaimDrawerErrorProps) {
const { eyebrow, message } = COPY[kind];
const Icon = kind === "network" ? WifiOff : AlertCircle;
return (
<div
className="flex flex-col items-start gap-4 p-6 bg-[color:var(--m-surface)] text-[color:var(--m-ink-primary)]"
role="alert"
data-testid={`claim-drawer-error-${kind}`}
>
<div className="flex items-center gap-2">
<Icon
className="h-5 w-5 text-[color:var(--m-error)]"
strokeWidth={1.75}
aria-hidden
/>
<span className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-[color:var(--m-error)]">
{eyebrow}
</span>
</div>
<p className="text-sm text-[color:var(--m-ink-secondary)]">{message}</p>
<div className="flex items-center gap-2">
{kind === "network" && onRetry ? (
<Button variant="outline" size="sm" onClick={onRetry} data-testid="error-retry">
Retry
</Button>
) : null}
<Button variant="ghost" size="sm" onClick={onClose} data-testid="error-close">
Close
</Button>
</div>
</div>
);
}