DetailPanel
Key-value details as boxed rows or `variant="grid"` stats, plus a live pulse. Idle copy is `inactiveLabel`; `label` only overrides Live.
Wraps: none (theme tokens only)
Delivery D-2047
- Carrier
- Colissimo
- Status
- In transit
- Destination
- 14 rue des Lilas, 69003 Lyon
- Arrival
- Thursday 29 October, before 6 pm
- Weight
- 1.8 kg
Shown once tracking stops, for example after delivery.
Use it
Examples import from the package. With copied source, import from @/components/ui/detail-panel instead.
import { DetailPanel, LivePulse, PageHeader } from "@zedtech/zedkit-ui";
<PageHeader title="Server" actions={<LivePulse active={false} inactiveLabel="Paused" />} />
<DetailPanel items={[{ label: "Region", value: "eu" }]} />Composed rows
- Customer
- Camille Rousseau
- Plan
- Pro
- Last seen
2 minutes ago
- Renews
- 1 December 2026
- Customer ID
import { DetailPanelRow } from "@zedtech/zedkit-ui";
<dl>
<DetailPanelRow label="Region" value="eu" />
</dl>Stat grid
- Requests
- 12,480
- Uptime
- 99.9%
- Latency
- 42 ms
- Errors
- 0.12%
import { DetailPanel } from "@zedtech/zedkit-ui";
<DetailPanel
variant="grid"
items={[{ label: "Requests", value: "12,480" }, { label: "Uptime", value: "99.9%" }]}
/>Kit not installed yet?
Install
Terminal pnpm add @zedtech/zedkit-ui @fontsource-variable/inter @fontsource-variable/space-groteskLoad the styles
Tailwind does not scan node_modules, so the @source line points it at the kit's class names. The path is relative to this file.
src/app/globals.cssReplace the contents@import "tailwindcss"; @import "@zedtech/zedkit-ui/styles.css"; @source "../../node_modules/@zedtech/zedkit-ui/src/**/*.{ts,tsx}"; @source not "../../node_modules/@zedtech/zedkit-ui/src/**/*.test.*";Pick a look
Set data-identity="glass" on <html> so the finished app matches the site. Fresh app: replace src/app/layout.tsx. Existing app: merge, and keep ThemeProvider and other providers.
src/app/layout.tsxReplace the contentsimport "./globals.css"; import "./fonts"; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en" data-identity="glass"> <body>{children}</body> </html> ); }Load the fonts
The Glass look uses Inter and Space Grotesk; these imports self-host them.
src/app/fonts.tsCreate the fileimport "@fontsource-variable/inter"; import "@fontsource-variable/space-grotesk";Import and render
src/app/page.tsxReplace the contentsimport { DetailPanelRow } from "@zedtech/zedkit-ui"; export default function Page() { return ( <main className="px-page-gutter py-section-sm"> <dl> <DetailPanelRow label="Region" value="eu" /> </dl> </main> ); }
Package version 2.0.1.
Props
Prop
Type
Accessibility
Native dl/dt/dd semantics; rows read in order. Grid wraps each pair so a two-column layout does not interleave terms and definitions. LivePulse is role="status" (name from aria-label, not contents). aria-label is the shown word (label when live, inactiveLabel when idle, kit idle when the word is hidden) so the StatusDot is never unnamed. inactiveLabel is caller-localized (no lang).
Troubleshooting
Custom row content — compose `DetailPanelRow` inside your own `<dl>` (see Composed rows); `DetailPanel` only covers the plain `items[]` case. Grid is `items[]` only — there is no composed-cell export. Grid reading order — each item is one wrapped `dt`/`dd` pair, not flattened grid children. Boxed look on a grid — wrap in Card (`<Card><DetailPanel variant="grid" items={items} /></Card>`); `className` also works; grid drops list chrome. Grid loading — `DetailPanelSkeleton` is the boxed-list shape only. Cramped rows — inline padding is `px-detail-panel-inline`; block padding is `py-detail-panel-block`. Idle word stuck on Idle — pass `inactiveLabel`; `label` is ignored when `active={false}`. Dot-only idle still unnamed — empty `inactiveLabel` hides the visible word; `aria-label` stays the kit idle string. Mixed-language idle copy — localize `inactiveLabel` on the host; LivePulse does not translate it.