Report sheet
ProThe paged chassis of a report (release readiness, configuration audit): a cover with what it covers and when its data was read, numbered sections, an export bar, and a provenance footer saying who or what generated it from which sources. Prints one section per page.
Preview
Install
With the Candor CLI
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/report-sheet
Brings in: button, freshness-stamp, locale, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import { ReportSection, ReportSheet } from "@/components/report-sheet"
import { ComparisonView } from "@/components/comparison-view"
import { KpiRow } from "@/components/stat-card"
const ago = (hours: number) => new Date(Date.now() - hours * 3_600_000).toISOString()
export default function Example() {
return (
<ReportSheet
className="max-w-3xl"
title="Release readiness: 4.2"
scope="Acme Production"
period="Changes since the 4.1 release"
generatedAt={ago(0)}
generatedBy="Keel"
dataReadAt={ago(3)}
onExport={() => {}}
>
<ReportSection number={1} title="Summary" lede="From last night’s CI run and the 4.1 release.">
<KpiRow
kpis={[
{ label: "Changes in the release", value: 62, delta: { value: 18, vs: "4.1 release", good: "down" } },
{ label: "Failing tests", value: 6, delta: { value: -4, vs: "last week", good: "down" } },
{ label: "Users affected", value: null, missing: "Needs session analytics, which isn’t connected." },
]}
/>
</ReportSection>
<ReportSection number={2} title="Before and after" lede="This release against 4.1.">
<ComparisonView
before="4.1"
after="4.2"
rows={[
{ label: "Test coverage", before: 0.72, after: 0.78, format: "percent", good: "up" },
{ label: "Failing tests", before: 10, after: 6, good: "down" },
]}
/>
</ReportSection>
</ReportSheet>
)
}<ReportSheet>
| Prop | Type | Default | Description |
|---|---|---|---|
| titlerequired | string | — | The report's name, as the cover heading. |
| scoperequired | string | — | e.g. "Shop production". |
| period | string | undefined | — | The time span the report covers, shown after the scope, e.g. "March 2026". |
| generatedAtrequired | string | — | When the report was generated (ISO timestamp), shown in the footer. |
| generatedByrequired | string | — | Who or what generated it, a person or an agent, named in the footer. |
| dataReadAtrequired | string | null | — | When the underlying data was read (ISO timestamp); null shows that it's unknown. |
| onExport | ((format: "pdf" | "csv" | "md") => void) | undefined | — | Shows PDF, CSV and Markdown export buttons; called with the chosen format. |
| childrenrequired | React.ReactNode | — | What goes inside. |
| className | string | undefined | — | Extra classes for the outer element. |
<ReportSection>
A numbered section with one prop shape: number, title, optional lede, content.
| Prop | Type | Default | Description |
|---|---|---|---|
| numberrequired | number | — | The section's number, shown zero-padded above the title. |
| titlerequired | string | — | The section heading. |
| lede | string | undefined | — | A sentence under the heading saying what the section shows. |
| childrenrequired | React.ReactNode | — | What goes inside. |
| className | string | undefined | — | Extra classes for the outer element. |
Strings
The fixed words, in English by default. Change any of them under reportSheet in <LocaleProvider strings={{ … }}>; the table is exported as reportSheetStrings.
| Key | English |
|---|---|
| report | Report |
| dataRead | Data read |
| csv | CSV |
| md | Markdown |
| footer | Generated by {by} on {date}. Figures come from the sources named in each section; a dash means it wasn’t measured. |