Interactive Answers
Blast Radius
What a key, agent or tool can reach, hop by hop around a centre, with the affected paths in red.
2 variantsMIT
Preview
Blast radius
sk-live-…7f2a · issued 14 min ago
Scanning
ServiceDatabaseBucketSecretPerson
Installation
Copies the component into components/ui and installs its dependencies and theme tokens.
pnpm dlx shadcn@latest add https://tuffui.com/r/blast-radius.jsonUsage
Pass your own data and wire the callbacks to your agent runtime.
import { BlastRadius } from "@/components/ui/blast-radius";
export function KeyExposure({ grants }: { grants: Grant[] }) {
return (
<BlastRadius
title="Blast radius"
subtitle="sk-live-…7f2a"
center={{ label: "sk-live-…7f2a", initials: "SK" }}
nodes={grants.map((g) => ({
id: g.resourceId,
label: g.resourceName,
parent: g.viaResourceId, // undefined = granted directly
kind: g.resourceType, // "database", "bucket", …
affected: g.canRead,
indirect: Boolean(g.viaResourceId),
note: g.reason,
}))}
kinds={{
database: { label: "Database", color: "#1a9e8c" },
bucket: { label: "Bucket", color: "#bf5af2" },
}}
onSelect={(node) => openResource(node.id)}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| center* | { label: string; initials?: string; icon?: Icon } | — | The entity everything is measured from. Shows the icon, else the initials, else the first two letters of the label. |
| nodes* | BlastNode[] | — | Everything it can reach. Hop depth comes from the parent chain; the first hop is spaced evenly by angle and later hops fan around their parent. |
| kinds | Record<string, BlastKind> | — | Label and colour per kind, in legend order. Kinds left out get the categorical palette. |
| title* | string | — | Header title. |
| subtitle | string | — | Secondary line under the title. |
| aside | React.ReactNode | — | Right side of the header, e.g. a status pill with the count. |
| onSelect | (node: BlastNode) => void | — | Called when a node is hovered or reached with the arrow keys. |
| className | string | — | Extra classes for the root element. |
type BlastNode = {
id: string;
label: string;
parent?: string; // id it is reached through; omit for the centre
kind: string; // key into kinds
affected?: boolean; // negative ring, path to the centre turns negative
indirect?: boolean; // dashed edge and ring
note?: string; // tooltip line, e.g. "Read by the new key"
};
type BlastKind = { label: string; color: string };