Share and embed The dashboard leaves the tool and has to keep meaning something. A shared link carrying a relative range means a different thing tomorrow, so the dialog has to make the absolute choice visible rather than defaulting quietly. npx shadcn@latest add tabs input button switch label npm i lucide-react Tokens this needs: --background, --card, --card-foreground, --muted-foreground, --border, --chart-1 ──────────────────────────────────────────────────────────────────────── // SharePanel.tsx ──────────────────────────────────────────────────────────────────────── import { useState, type ReactNode } from "react"; import { Copy } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; /** Four needs wearing one button, each described by what it is good for. */ export type Mechanism = "link" | "snapshot" | "embed" | "export"; const MECHANISMS: { id: Mechanism; label: string; blurb: string }[] = [ { id: "link", label: "Link", blurb: "Live state, cheapest, best when they have access. Hinges on the URL carrying all of it." }, { id: "snapshot", label: "Snapshot", blurb: "Frozen data, viewable without access. Solves the writeup that links to a healthy system." }, { id: "embed", label: "Embed", blurb: "Rendered inside a wiki or a portal, updating live, read by people who never open the tool." }, { id: "export", label: "Export", blurb: "A PDF arriving on a timetable, for people who will never open the tool at all." }, ]; export type ShareState = { title: string; /** The window as it stands right now, absolute. */ range: { from: Date; to: Date }; /** The relative form the page is actually on, if any: "last 1h". */ relative?: string; filters: string[]; /** Set when the viewer has isolated part of the chart. It travels or it lies. */ isolated?: { shown: number; of: number }; }; const hhmm = (d: Date) => d.toISOString().slice(11, 16); /** What gets written onto everything that leaves. */ export const stamp = (s: ShareState) => [`${hhmm(s.range.from)}-${hhmm(s.range.to)}`, ...s.filters].join(" · "); /** * One panel behind the share button, with the state it will carry shown * before anything is produced. The absolute range is the default and the * relative one is a switch, so a link that means something else tomorrow is * a choice rather than an accident. Public is a switch with its consequence * written beside it. */ export function SharePanel({ state, url, preview, onCopy, onSnapshot, onExport }: { state: ShareState; /** The live URL. It must carry the range, filters and selection already. */ url: string; /** The panel as it will leave, rendered small. */ preview?: ReactNode; onCopy: (text: string) => void; onSnapshot: (opts: { isPublic: boolean }) => void; onExport: (opts: { every: "day" | "week" }) => void; }) { const [absolute, setAbsolute] = useState(true); const [isPublic, setPublic] = useState(false); const href = absolute || !state.relative ? url : url.replace(/from=[^&]*&to=[^&]*/, `range=${encodeURIComponent(state.relative)}`); const embed = ``; const copyRow = (text: string, label: string) => (
); return (

{state.title}

{stamp(state)}

{preview} {state.isolated && (

{state.isolated.shown} of {state.isolated.of} series isolated

)}
{MECHANISMS.map((m) => ( {m.label} {m.blurb} ))} {copyRow(href, "link")}
{copyRow(embed, "embed code")}
); } ──────────────────────────────────────────────────────────────────────── // demo.tsx ──────────────────────────────────────────────────────────────────────── import { SharePanel } from "./SharePanel"; /** The checkout errors panel, an hour of eu-west, one series isolated. */ const STATE = { title: "Checkout errors", range: { from: new Date("2026-09-15T14:00:00Z"), to: new Date("2026-09-15T15:00:00Z") }, relative: "last 1h", filters: ["eu-west"], isolated: { shown: 1, of: 6 }, }; const URL = "https://ops.internal/d/checkout?from=2026-09-15T14:00Z&to=2026-09-15T15:00Z®ion=eu-west&series=5xx"; /** Six points of the isolated series, drawn small so the stamp has a picture. */ const Preview = () => ( ); export default function Demo() { return (
} onCopy={(text) => navigator.clipboard.writeText(text)} onSnapshot={(o) => console.log("snapshot", o)} onExport={(o) => console.log("export", o)} />
); }