Learning Path Card
A high-impact "destination" tile that links to a multi-chapter learning module. Magazine-style hierarchy: a mono-caps eyebrow, a serif title, an optional italic subtitle, a short description, a metadata row (chapters · duration), and a thin progress bar that hugs the bottom edge.
Customize
Progress
35%
Chapters
3
Accent
Installation
npx shadcn@latest add https://craftbits.dev/r/learning-path-card.jsonUsage
import { LearningPathCard } from "@craft-bits/core";
<LearningPathCard
href="/paths/attention"
eyebrow="Learning path"
title="Attention, from the ground up"
subtitle="A walk through the transformer's beating heart."
description="Three chapters that build attention from a dot product to a multi-head block."
chapters={3}
duration="~45 min"
progress={0.35}
accent
/>Understanding the component
- Anchor at the root. The card renders as a single
<a>so the entire surface is one click target — no nested-link traps, no JS for navigation.forwardRef<HTMLAnchorElement>lets routers (Next.jsLink, RemixLink) hand off the underlying anchor. - Editorial hierarchy. Eyebrow (small mono caps) → serif title → italic subtitle → body description → metadata row. The serif title uses
text-wrap: balanceso two-line headlines break evenly; the description usestext-wrap: prettyto avoid orphans. - Accent rail signals the featured path.
accent={true}paints a 3px--cb-accentleft border and tints the eyebrow with the accent color. Use it once per row to mark a recommended or in-progress path. - Hover lift is two-property only.
transitionis scoped tobox-shadow,transform,border-color(nevertransition-all). On hover the card lifts-translate-y-0.5, its shadow deepens via a two-layer recipe, and the title color shifts toward the accent. The arrow in the metadata row nudges right viagroup-hover:translate-x-0.5. - Progress hugs the bottom edge. When
progressis provided, a 4px track sits flush against the bottom of the card (outside the inner padding) with the fill colored by the accent state. The fill width animates via a CSStransition: width 300ms ease-out— no motion library, SSR-safe. - Shadows never use pure black. Both shadow layers are
rgb(15, 15, 15)(a neutral near-black) at low alpha, which sits naturally over any theme.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | required | Card title — serif, large. |
subtitle | string | — | Italic subtitle line below the title. |
description | ReactNode | — | Short editorial blurb. |
progress | number | — | Completion ratio in [0, 1]. Renders the thin bottom progress bar when provided. |
chapters | number | — | Chapter count — rendered in the metadata row. |
duration | string | — | Duration label, e.g. '~45 min'. |
href | string | required | Destination URL. |
eyebrow | string | — | Small uppercase label above the title. |
accent | boolean | false | When true, adds a 3px accent left rail and accent-tinted eyebrow. |
className | string | — | Merged onto the rendered <a> via cn(). |
Accessibility
- The entire card is a single anchor — the title, subtitle, description, and metadata all read as part of the link's accessible name.
- When
progressis provided, the bottom track exposesrole="progressbar"witharia-valuenow/aria-valuemin/aria-valuemaxand a synthesizedaria-label("35% complete"). - Decorative separators (the
·between chapters and duration) are markedaria-hidden="true". - The focus ring is
:focus-visibleonly — a 2px accent ring with a 2px offset against the page background, meeting WCAG AA contrast in both light and dark themes. - The hover lift transitions only
box-shadow,transform, andborder-color— nevertransition-all. Animations complete in under 300ms (Doherty).
Credits
- Extracted from:
terminal-dreams(src/components/principles/LearningPathCard.tsx).