Skip to content

feat(graph): responsive mobile layout, light/dark/system theme, and zoom controls - #10

Merged
mchittineni merged 2 commits into
mainfrom
theme-mode
Aug 11, 2026
Merged

mchittineni merged 2 commits into
mainfrom
theme-mode

Conversation

@mchittineni

Copy link
Copy Markdown
Owner

Description

Makes the knowledge graph page usable on phones, and adds a theme switcher plus zoom controls.

1. Mobile layout fix. The page had no media queries at all — it was a desktop-only fixed-panel layout, so panels overlapped on a phone:

  • #header was left:20px; max-width:380px → 400px of panel on a 390px screen, overflowing the right edge.
  • The actual collision: the header grows downward as search results populate (+200px) while the inspector card grows upward from bottom:24px. On a phone they met in the middle, and nothing bounded either one.
  • body{overflow:hidden} meant anything buried under a panel was unreachable.
  • height:100vh includes Safari's collapsing URL bar, pushing the bottom card under browser chrome.
  • The search input's ~13px font triggered iOS Safari's auto-zoom-on-focus, which by itself shifts the whole layout.

Overlap is now impossible by construction: the header caps at 40dvh from the top and the bottom stack at 45dvh from the bottom, leaving a 15dvh gutter regardless of content. Both scroll internally instead of growing. Also: 100dvh, a 16px input font, 44px tap targets, a landscape branch that places panels side-by-side, and a prefers-reduced-motion guard. The library's "Left-click: rotate, Mouse-wheel: zoom" hint is hidden on touch devices, where it was clipped behind the card and described controls that don't exist.

2. Theme switcher (light / dark / system). A segmented control in the header (role="radiogroup", arrow-key navigable, roving tabindex), persisted to localStorage and defaulting to the OS preference.

The page was hardcoded dark, so the bulk of this is tokenizing every colour into CSS custom properties — no hardcoded colours remain in the stylesheet. Tokens use the three-state pattern: light on bare :root, dark layered twice (@media (prefers-color-scheme: dark) guarded with :not([data-theme="light"]) for system mode, and [data-theme="dark"] so an explicit pick beats the OS).

Three things needed more than CSS:

  • The WebGL scene can't read CSS variables, so it keeps a parallel palette applied via backgroundColor() / linkColor() / linkOpacity() on each switch.
  • A pre-paint inline script resolves the stored mode before first paint, avoiding a flash of the wrong theme.
  • Search highlight/dim colours were hardcoded inside the input handler, so switching theme mid-search stranded the old palette. Consolidated into one paintNodes() owner.

Card tags moved from JS inline styles to data attributes, since inline dark-only hex values can't respond to a theme.

3. Zoom controls, bottom-right. The inspector card already occupied bottom:24px; right:24px — exactly where the buttons go. Instead of nudging offsets, they're flex siblings in one positioned wrapper, so normal flow guarantees they can't overlap at any content size. The wrapper is pointer-events:none with children auto, so its empty area still rotates the graph rather than creating a dead zone. Zoom scales camera distance, clamped to 40–4000 so repeated clicks can't invert through the origin or lose the graph.

Accessibility

All 14 tag variants and every text token now clear WCAG AA (4.5:1) in both themes. Computing tag text against its actual tinted background (not the panel) surfaced 4 variants at 3.96–4.30:1; lowering --tag-alpha to 0.10/0.15 fixes it. Note the dark-mode failures there were pre-existing, not introduced here.

Verification

Measured in headless Chromium rather than assumed:

  • Zoom — cameraPosition() works as a getter (1390 → 1030 → 1390); clamps hold at exactly 40 and 4000; camera direction stays finite.
  • Theme — DOM and WebGL backgrounds both change; choice survives reload; theme resolves pre-paint (no FOUC); system mode follows a live OS flip while an explicit pick correctly ignores it.
  • Layout — across 8 viewports (320px → 1440px, both orientations), in the worst-case state with search results populated and the card open: no header/card/zoom overlap, no horizontal scroll, nothing past the viewport edge, all tap targets ≥44px.

validate_content.py and generate_indexes.py --check pass, and the build is deterministic (byte-identical rebuild), so CI won't churn the diff.

Type of Change

  • 🆕 New interview question(s) and answer(s)
  • 📝 Improving an existing answer
  • 📁 New topic directory
  • 🔧 Fixing links, formatting, or tooling

Topic

Not topic-scoped — this changes the generated knowledge-graph UI.

  • Directory: scripts/ (template) and docs/ (generated output)

Checklist

See CONTRIBUTING.md for the full format.

  • File name — n/a, no question files added or renamed.
  • Frontmatter — n/a, no Markdown content changed.
  • Heading — n/a, no Markdown content changed.
  • Answer structure — n/a, no answers changed.
  • New topic only — n/a, no new topic.
  • Ran python3 scripts/generate_indexes.py and python3 scripts/build_knowledge_graph.py — indexes verified up to date via --check; graph HTML is regenerated, not hand-edited. All UI changes were made in the HTML_TEMPLATE in scripts/build_knowledge_graph.py, since the workflow rebuilds docs/index.html on every push to main and a direct HTML edit would be silently overwritten.
  • Ran python3 scripts/validate_content.py and it passed.
  • Content is accurate, and any code examples actually work — behaviour verified in a real browser across 8 viewports and both themes, as above.

@github-actions

Copy link
Copy Markdown

✅ All automated checks passed

The following checks completed successfully:

  • ✅ Content validation
  • ✅ Index validation
  • ✅ Markdown formatting
  • ✅ Markdown linting

Your contribution is ready for review. 🎉

@mchittineni
mchittineni enabled auto-merge (rebase) August 11, 2026 18:45
@coderabbitai

coderabbitai Bot commented Aug 11, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added light, dark, and system theme options with saved preferences and automatic system-theme synchronization.
    • Introduced accessible zoom controls with bounded zoom behavior and keyboard navigation.
    • Added a responsive inspector panel with dismiss controls.
  • Improvements
    • Updated graph colors, node highlights, tags, and panels to adapt consistently to the selected theme.
    • Search highlights now remain synchronized when the theme changes.
    • Improved layout and accessibility for graph inspection controls.

Walkthrough

The knowledge graph UI now supports light, dark, and system themes. It adds persisted theme selection, system-theme synchronization, responsive inspector and zoom controls, accessible navigation, theme-aware graph palettes, and centralized node repainting. The generator and generated page contain matching changes.

Changes

Theme-aware graph UI

Layer / File(s) Summary
Theme foundation and responsive styling
docs/index.html, scripts/build_knowledge_graph.py
Theme tokens, pre-paint theme resolution, theme controls, accessible focus states, search styling, inspector styling, and responsive layouts were added.
Inspector and zoom controls
docs/index.html, scripts/build_knowledge_graph.py
The inspector and zoom controls now share a responsive wrapper. Inspector tags use data attributes. Dismiss and accessible control markup were added.
Theme runtime and graph synchronization
docs/index.html, scripts/build_knowledge_graph.py
Theme preferences persist and follow system changes. Graph palettes and node colors update with the active theme. Search repainting and bounded zoom controls were added.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ThemeControls
  participant localStorage
  participant matchMedia
  participant applyTheme
  participant paintNodes
  participant Graph
  ThemeControls->>localStorage: Persist selected theme
  ThemeControls->>applyTheme: Apply light, dark, or system theme
  matchMedia->>applyTheme: Report system theme changes
  applyTheme->>Graph: Update graph palette
  applyTheme->>paintNodes: Repaint nodes
  paintNodes->>Graph: Update search and node colors
Loading

Possibly related PRs

Poem

I twitch my nose at themes so bright,
Then hop through dark and system night.
The graph repaints, the zoom stays bound,
Search highlights glow all around.
A tidy inspector rests just right.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The description is complete, specific, and follows the repository template with scope, change type, topic, checklist, and verification details.
Title check ✅ Passed The title clearly summarizes the main changes: responsive layout, three-state theme support, and zoom controls for the graph UI.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch theme-mode

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.45.1)
docs/index.html

ast-grep timed out on this file


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/build_knowledge_graph.py`:
- Around line 1023-1027: Update the Graph.cameraPosition call in
scripts/build_knowledge_graph.py to pass 0 instead of 220 when
prefers-reduced-motion: reduce matches, while retaining 220 otherwise.
Regenerate docs/index.html so its corresponding Graph.cameraPosition call
reflects the same behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 98fd712b-cf87-4402-8c49-1b2e28917acb

📥 Commits

Reviewing files that changed from the base of the PR and between 95cb7b5 and 68c9998.

📒 Files selected for processing (2)
  • docs/index.html
  • scripts/build_knowledge_graph.py

Comment thread scripts/build_knowledge_graph.py
@mchittineni
mchittineni merged commit b7f4d2a into main Aug 11, 2026
5 checks passed
@mchittineni
mchittineni deleted the theme-mode branch August 11, 2026 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant