fix(graph-3d): family-distinct node colors + larger course roots#95
Conversation
Three.js's Color.setStyle silently rendered every node black because shadeFor returned space-separated `hsl(120 50% 50%)` strings, which the parser only accepts comma-separated. Switch shadeFor to hex output, tighten hue variance ±25 → ±10 so each course family reads as one cohesive color band, and add a deterministic palette fallback (paletteFor in lib/data.ts) so backends without course_color still get distinct hues per course_id. Course-root nodes pinned to a larger fixed size (nodeVal=22) so the family center anchors the eye. Replace var(--c-sage) screen fallbacks with resolved hex — CSS custom properties don't survive WebGL. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Two fixes from PR #95 review: 1. The palette seed in apiToGraphNode preferred n.course_id over course?.course_id. When some nodes in a family carry course_id and others don't (falling through to subject), they hashed to different palette colors and the family visually split. Prefer the course-record id so all nodes in a family seed identically. 2. shadeFor used `hexToHsl(FALLBACK)!` — safe today only because the FALLBACK constant happens to parse. Replaced with a precomputed FALLBACK_HSL literal (`{h: 75, s: 26, l: 48}` = #8a9a5b) so the call site can never silently break. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
frontend | e177171 | Commit Preview URL Branch Preview URL |
May 06 2026, 02:14 AM |
Three non-blocking follow-ups from PR #95 review: 1. Deduplicate the DJB2 hash (was reimplemented in lib/data.ts and KnowledgeGraph.tsx) into a single `hashSeed` export. 2. Hoist the triplicated apiToGraphNode adapter from Tree/Learn/ Dashboard into lib/data.ts. 3. Add unit tests for paletteFor + hashSeed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WCAG audit against the cream `--bg` (#faf8f3) flagged two palette entries below the 3:1 non-text-UI threshold: - sage #8a9a5b → 2.89:1 → #7a874f (~3.5:1) - ochre #c89c4a → 2.38:1 → #a87d2e (~3.6:1) Both nudged darker along the same hue band so node circles stay legible on the light theme. Brand --accent (#8a9a5b) is unchanged elsewhere — this palette is only the backend-color fallback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Locks down the round-2 fix: when n.course_id and course.course_id disagree, the palette seed must come from the course record so every node in the same family hashes to the same color. Also pins the two simpler fallback branches and the subject_root → mastered tier remap. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
shadeForreturned space-separatedhsl(120 50% 50%)strings, whichColor.setStyleonly accepts comma-separated. SwitchedshadeForto hex output via a newhslToHexhelper.paletteFor(inlib/data.ts) — a deterministic 8-color brand palette indexed bycourse_id. So when the backend doesn't supply a per-course color, each family still gets its own distinct hue instead of every concept collapsing onto one fallback.nodeVal(22) so the family center anchors the eye.var(--c-sage)fallbacks inTree.tsx/Learn.tsx/Dashboard.tsxwithpaletteFor(course_id || subject). CSS custom properties don't survive WebGL — that fallback was contributing to all-black rendering.Stacked on top of #92 — base =
feat/knowledge-graph-3d. After #92 merges, this PR's base will auto-update tomain.Test plan
npx vitest run— 8/8 KnowledgeGraph component tests pass; updated test pins hex output (was pinninghsl(...)) and the new course-root sizing.npx tsc --noEmit— clean.npm run check:lockfile— green./learn,/tree,/dashboard— confirm each course family is visibly distinct and root nodes are noticeably larger.🤖 Generated with Claude Code