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.json

Usage

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

  1. One source of truth for hints. Each entry in hints carries 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.
  2. Hover threads both sides. A single hoveredLine piece 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 via onFocus / onBlur.
  3. Generic, not perf-flavoured. The verdict pill ("120ms earlier", "50ms slower") from the source is generalised into an optional badge slot — 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.
  4. Token-driven tones. Five tones — neutral / accent / good / bad / warn — map to the --cb-fg-subtle, --cb-accent, --cb-success, --cb-error, --cb-warning tokens. Re-skin the whole panel by overriding the --cb-* vars at the app root.
  5. Reduced motion. Enter animations short-circuit when prefers-reduced-motion: reduce is set, and the rail's layout shifts are disabled. The hover tint still applies — a 150ms color transition is well inside the perceptual budget.

Variants

  • Code only — omit hints to render a plain code panel (the rail hides itself).
  • Header off — omit title / eyebrow / badge to render hints with no chrome.
  • Tone mix — combine good / bad / warn pills to read like a code review.

Props

PropTypeDefaultDescription
codestringrequiredThe code string. Split on newline to derive lines.
hintsreadonly HintCodePanelHint[][]Inline hints keyed to 1-indexed line numbers.
titleReactNodeTitle rendered in the header.
eyebrowReactNodeSmall uppercase tag before the title (e.g. step code).
badge{ label: ReactNode; tone?: HintTone }Verdict pill rendered on the header's right.
showLineNumbersbooleantrueRender the 1-indexed line-number gutter.
classNamestringMerged onto the root <div>.

HintCodePanelHint

FieldTypeDescription
linenumber1-indexed line number to attach to.
labelstringShort pill label that sits at the end of the source line.
contentReactNodeExpanded 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"> with aria-describedby wired 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 to var(--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-aware badge slot, replaces the CSS-module chrome with token classes, and introduces the side-rail hint pattern with hover-threaded source lines.