Hint Code Panel
A code panel for inline annotations. Each hint is declared once and rendered twice — as a compact pill anchored to its source line, and as a longer explanation in the side rail. Hovering either side threads them together: the source line tints, the rail entry lifts, and a connecting dot lights up.
Preview
step 02resource hintsLCP -120ms
<link rel="preload" as="font" href="/fonts/inter.woff2" />
<link rel="preconnect" href="https://cdn.example.com" />
<link rel="dns-prefetch" href="https://api.example.com" />
<link rel="prefetch" href="/next-route.js" />
Customize
Snippet
resource hints
Features
Installation
npx shadcn@latest add https://craftbits.dev/r/hint-code-panel.jsonUsage
import { HintCodePanel } from "@craft-bits/core";
<HintCodePanel
title="Resource hints"
code={source}
hints={[
{ line: 1, label: "high priority", content: "Preload eagerly fetches." },
{ line: 2, label: "TCP handshake", content: "Preconnect opens the socket." },
]}
/>With an eyebrow, verdict badge, and tones:
<HintCodePanel
eyebrow="step 02"
title="Resource hints"
badge={{ tone: "good", label: "LCP saved 120ms" }}
code={source}
hints={[
{ line: 1, tone: "good", label: "high priority", content: "..." },
{ line: 2, tone: "accent", label: "handshake", content: "..." },
{ line: 3, tone: "neutral", label: "DNS only", content: "..." },
{ line: 4, tone: "warn", label: "speculative", content: "..." },
]}
/>Understanding the component
- One source of truth for hints. Each entry in
hintscarries the line index, a short pill label, and the long content. The component derives two views — the inline pill at the end of the source line, and the rail entry on the right — from the same object. There's no separate "line decoration" pass. - Hover threads both sides. A single
hoveredLinepiece of local state is updated by mouse enter/leave on both the source line and the rail entry. Whichever you point at, the matching half lifts: source line gets a tone-keyed tint, rail entry gets a subtle border and elevated background. Keyboard focus on the pill triggers the same join viaonFocus/onBlur. - Generic, not perf-flavoured. The verdict pill (
"120ms earlier","50ms slower") from the source is generalised into an optionalbadgeslot — pass whatever short text fits your domain. The eyebrow ("step 02") is its own slot so step codes, file paths, or kind tags can sit there. - Token-driven tones. Five tones —
neutral/accent/good/bad/warn— map to the--cb-fg-subtle,--cb-accent,--cb-success,--cb-error,--cb-warningtokens. Re-skin the whole panel by overriding the--cb-*vars at the app root. - Reduced motion. Enter animations short-circuit when
prefers-reduced-motion: reduceis set, and the rail'slayoutshifts are disabled. The hover tint still applies — a 150ms color transition is well inside the perceptual budget.
Variants
- Code only — omit
hintsto render a plain code panel (the rail hides itself). - Header off — omit
title/eyebrow/badgeto render hints with no chrome. - Tone mix — combine
good/bad/warnpills to read like a code review.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
code | string | required | The code string. Split on newline to derive lines. |
hints | readonly HintCodePanelHint[] | [] | Inline hints keyed to 1-indexed line numbers. |
title | ReactNode | — | Title rendered in the header. |
eyebrow | ReactNode | — | Small uppercase tag before the title (e.g. step code). |
badge | { label: ReactNode; tone?: HintTone } | — | Verdict pill rendered on the header's right. |
showLineNumbers | boolean | true | Render the 1-indexed line-number gutter. |
className | string | — | Merged onto the root <div>. |
HintCodePanelHint
| Field | Type | Description |
|---|---|---|
line | number | 1-indexed line number to attach to. |
label | string | Short pill label that sits at the end of the source line. |
content | ReactNode | Expanded body shown in the side rail. |
tone | 'neutral' | 'accent' | 'good' | 'bad' | 'warn' | Optional tone — defaults to 'accent'. |
Accessibility
- Each hint pill is a
<button type="button">witharia-describedbywired to the rail entry's id — assistive tech announces the line's hint when the button is focused. - The rail is wrapped in an
<aside aria-label="Inline hints">so it surfaces as a landmark. - Pill focus is visible via a
focus-visible:outline keyed tovar(--cb-accent). - The connecting dots and line-number gutter spans are
aria-hidden="true"— they're decorative; the line and label text are what's read. - Reduced motion (
prefers-reduced-motion: reduce) collapses the enter spring and disables the rail's layout shift; only the 150ms tint remains.
Credits
- Extracted from:
terminal-dreams(src/components/frontend-design/perf-resource-hints/ui/HintCodePanel.tsx). The library version generalises the perf-only verdict into a tone-awarebadgeslot, replaces the CSS-module chrome with token classes, and introduces the side-rail hint pattern with hover-threaded source lines.