Lesson Hint Bar

A compact hint affordance for lesson and quiz primitives. Each tap of the reveal button surfaces the next hint in the sequence — conceptual nudge first, concrete trace next, near-answer last. Remaining hints are surfaced as small dots beside the button so the learner always knows how much help is left.

Preview
Customize
Options

Installation

npx shadcn@latest add https://craftbits.dev/r/lesson-hint-bar.json

Usage

import { LessonHintBar } from "@craft-bits/core";
 
const HINTS = [
  { id: "concept", text: "What does the loop actually accumulate?" },
  { id: "trace", text: "After the second iteration, the running total is 6." },
  { id: "answer", text: "The function returns the prefix-sum at index 3." },
];
 
<LessonHintBar hints={HINTS} defaultRevealedCount={0} />

Controlled — lift the count into your own state to drive scoring or token deduction:

const [revealed, setRevealed] = useState(0);
 
<LessonHintBar
  hints={HINTS}
  revealedCount={revealed}
  onRevealedCountChange={setRevealed}
  cost={1}
/>

Anatomy

  • Revealed hint list — top of the bar. Each revealed hint fades in via SPRINGS.snap inside an aria-live="polite" region.
  • Reveal button — a small lightbulb pill. Hides itself once every hint has been revealed.
  • Remaining-hint dots — a row of small dots beside the button. Available dots tint to --cb-warning (or the optional accentColor); used dots fall back to the subtle foreground tone.
  • Cost suffix — an inline (-N) annotation that appears next to the button when cost is provided. Purely presentational.

Props

PropTypeDefaultDescription
hintsReadonlyArray<LessonHintBarHint>Ordered list of progressive hints. Each entry needs a stable id and a text ReactNode.
revealedCountnumberControlled count of revealed hints. Pair with onRevealedCountChange.
defaultRevealedCountnumber0Uncontrolled starting count.
onRevealedCountChange(next: number) => voidFires whenever the learner reveals another hint.
costnumberOptional per-reveal cost suffix. Presentational only — parent owns the budget.
revealLabelReactNode"Need a hint?"Label for the reveal button.
accentColorstringwarning tokenOverride accent color for the icon and remaining-hint dots.
classNamestringMerged onto the root via cn().

Accessibility

  • The revealed-hint list is wrapped in an aria-live="polite" region so screen readers announce each new hint as it appears, without interrupting in-flight speech.
  • The reveal button enforces a 44 px minimum hit area (min-h-[44px] min-w-[44px]) and shows a visible :focus-visible ring keyed to --cb-accent.
  • The button's aria-label defaults to a Show hint N of M template so screen readers convey progress even when the visible label is a generic prompt.
  • Color is never the only channel — the remaining-hint count is mirrored in the dot-row's aria-label.

Credits

  • Extracted from: AlgoFlashcards (src/lessons/primitives/chrome/LessonHintBar.tsx). Replaced the project-specific RichText import and the raw trackHex prop with a plain ReactNode hint body plus a generic accentColor override, lifted the counter into a controlled + uncontrolled API, and added an optional cost annotation so the primitive can plug into token-budget flows without leaking project state.