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.jsonUsage
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.snapinside anaria-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 optionalaccentColor); used dots fall back to the subtle foreground tone. - Cost suffix — an inline
(-N)annotation that appears next to the button whencostis provided. Purely presentational.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
hints | ReadonlyArray<LessonHintBarHint> | — | Ordered list of progressive hints. Each entry needs a stable id and a text ReactNode. |
revealedCount | number | — | Controlled count of revealed hints. Pair with onRevealedCountChange. |
defaultRevealedCount | number | 0 | Uncontrolled starting count. |
onRevealedCountChange | (next: number) => void | — | Fires whenever the learner reveals another hint. |
cost | number | — | Optional per-reveal cost suffix. Presentational only — parent owns the budget. |
revealLabel | ReactNode | "Need a hint?" | Label for the reveal button. |
accentColor | string | warning token | Override accent color for the icon and remaining-hint dots. |
className | string | — | Merged 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-visiblering keyed to--cb-accent. - The button's
aria-labeldefaults to aShow hint N of Mtemplate 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-specificRichTextimport and the rawtrackHexprop with a plain ReactNode hint body plus a genericaccentColoroverride, lifted the counter into a controlled + uncontrolled API, and added an optionalcostannotation so the primitive can plug into token-budget flows without leaking project state.