As a student using the Explorer, I want to click a course and see its full details (title, credits, description, prerequisites, preclusions) in a side panel, so I don't have to recognise a course from its code alone.
🧠 Context
A shared CourseDetailPanel component has already been scaffolded at src/components/CourseDetailPanel.tsx. The contract and wiring are done — this ticket fills in the body and styling.
What's already in place (do not change):
- Props contract:
{ course: Course | null; onClose: () => void }. The component is intentionally prop-driven and page-agnostic (no store imports) so it can be reused elsewhere later. Keep it that way.
- Open/close behaviour: renders
null when course is null; otherwise a right-side drawer.
- Explorer integration: it's already wired into
src/pages/Explorer.tsx — clicking a node sets selectedCourse, which feeds the panel; the ✕ button calls onClose. You don't need to touch the Explorer wiring.
The body is currently a skeleton — just the course code and a close button, with a TODO. Your job is to render the rest of the fields and style it.
Prereq display: render course.prereqRaw as plain text. A nicer rendering of the parsed prereq AST is a separate future enhancement — not this ticket.
🛠️ Implementation Plan
- Open
src/components/CourseDetailPanel.tsx. Keep the props, the null guard, and the <aside> drawer shell as they are.
- In the body, render the remaining
Course fields: title, credits, description, prereqRaw (plain text), and precludes (e.g. a comma-separated list, only shown when non-empty). Avoid rendering misleading content for empty fields.
- Style it with Tailwind to match the rest of the app. Keep it readable within the drawer width.
- Accessibility: close on
Escape as well as the ✕ button, and manage focus sensibly (move focus into the panel on open, return it on close). The ✕ already has an aria-label.
- Mobile: the fixed right drawer may need a different treatment on narrow screens (e.g. close to full-width or a bottom sheet). At minimum, it must not break the layout.
- Test in the Explorer (
pnpm dev): clicking a node opens the panel with that course's details; ✕ / Escape closes it; selecting a different node swaps the content.
- Run
pnpm typecheck, pnpm test, and pnpm lint / pnpm format.
🚫 Out of scope (do not do in this ticket)
- Wiring the panel into the Planner — that's a separate future ticket. The component stays prop-driven so that integration is purely additive later.
- Rendering the parsed
prereq AST — use prereqRaw text only; the richer view is a future enhancement.
✅ Acceptance Criteria
As a student using the Explorer, I want to click a course and see its full details (title, credits, description, prerequisites, preclusions) in a side panel, so I don't have to recognise a course from its code alone.
🧠 Context
A shared
CourseDetailPanelcomponent has already been scaffolded atsrc/components/CourseDetailPanel.tsx. The contract and wiring are done — this ticket fills in the body and styling.What's already in place (do not change):
{ course: Course | null; onClose: () => void }. The component is intentionally prop-driven and page-agnostic (no store imports) so it can be reused elsewhere later. Keep it that way.nullwhencourseisnull; otherwise a right-side drawer.src/pages/Explorer.tsx— clicking a node setsselectedCourse, which feeds the panel; the ✕ button callsonClose. You don't need to touch the Explorer wiring.The body is currently a skeleton — just the course code and a close button, with a
TODO. Your job is to render the rest of the fields and style it.Prereq display: render
course.prereqRawas plain text. A nicer rendering of the parsedprereqAST is a separate future enhancement — not this ticket.🛠️ Implementation Plan
src/components/CourseDetailPanel.tsx. Keep the props, thenullguard, and the<aside>drawer shell as they are.Coursefields:title,credits,description,prereqRaw(plain text), andprecludes(e.g. a comma-separated list, only shown when non-empty). Avoid rendering misleading content for empty fields.Escapeas well as the ✕ button, and manage focus sensibly (move focus into the panel on open, return it on close). The ✕ already has anaria-label.pnpm dev): clicking a node opens the panel with that course's details; ✕ /Escapecloses it; selecting a different node swaps the content.pnpm typecheck,pnpm test, andpnpm lint/pnpm format.🚫 Out of scope (do not do in this ticket)
prereqAST — useprereqRawtext only; the richer view is a future enhancement.✅ Acceptance Criteria
Escapekey, with sensible focus handlingprereqRaw, or noprecludes) don't render misleading or broken-looking contentpnpm typecheckandpnpm testpass