Repository navigation
Light mode with a two-theme contrast gate, and generated architecture diagrams - #70
Merged
Merged
Conversation
Adds a three-state theme control: follow system, light, dark. Three rather than two because "follow system" is the one most people want and a binary switch cannot express it, and because silently pinning a theme on first visit is what sends people looking for a setting. It is a segmented control rather than the usual sun/moon switch for the same reason. How it works: every colour moves out of tailwind.config.js and into CSS custom properties holding RGB channels, so `rgb(var(--signal) / <alpha-value>)` keeps Tailwind's opacity modifiers composing. Two concrete theme blocks, no media query in the stylesheet: a pre-paint script in index.html resolves "system" and stamps data-theme on <html> before React mounts, which is what stops the page flashing the wrong theme on load. useTheme keeps following the OS while the preference is "system". Light is a real inversion rather than the dark palette lightened. The surface step flips, so `raised` still means "this lifts": on dark a card is lighter than the page, on light it is white against off-white. Every ink tone and severity colour is re-picked, because #62C073 on white is 2.1:1 and a 1.6px chart stroke in it simply disappears. The 67 `bg-white/[0.0x]` washes are the thing that actually blocked this. White at 3% over a near-black card is a subtle lift; over a white card it is nothing. They collapse onto three semantic surface tokens that invert with the theme. scripts/check-contrast.mjs reads the palette straight out of index.css and checks every foreground tone against every surface in both themes, plus the chart series at the 3:1 non-text minimum. It runs as part of `npm run build`. It immediately found twelve failures, three of them in the DARK theme that already shipped: ink-2, ink-3 and ink-4 only ever cleared AA against the card, and a nested block lifts the background enough to sink all three. ink-4 on bg-surface-3 was 3.77:1. Both palettes are adjusted until all 112 pairs pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Five diagrams the capstone review asked for, each in a dark and a light variant so they drop into the deck and into a README without looking borrowed: system architecture, incident lifecycle, the recovery ladder for when the first fix does not work, the three data sources, and how autonomy is earned. Generated by scripts/make-diagrams.mjs rather than drawn, and hand-built rather than Mermaid: these sit next to slides that were designed, so they have to carry the product's own palette and type scale, which Mermaid's auto-layout cannot be made to do. The palette is lifted from frontend/src/styles/index.css so the diagrams, the console and the deck are one visual system. The cost of manual layout is that SVG has no layout engine, so a coordinate that is 80px wrong does not raise an error, it produces a picture that is quietly unreadable. Every solid box and every arrow label therefore registers its rectangle and the generator exits non-zero on any overlap or overflow. It earned its place immediately, catching: - `action` rendering underneath `read model` - two boxes running off the right edge of the incident-flow canvas - the `situations.diagnosed` label being wider than the 74px gap it sat in, so it overprinted the node on either side Two things it cannot check were found by looking: the execute arrow pointed at empty space, which is now an explicit Kubernetes API node, and a 30px title collided with its own tag because the node layout assumed 17px. The bus topology is read out of the services rather than from memory: ingestion publishes telemetry.raw, correlation consumes it and publishes situations.detected plus situations.suppressed, rca publishes situations.diagnosed, action publishes remediation.outcomes, and feedback, read and governance all consume that last one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two things the capstone needs: a console that is not dark-only, and the architecture and flow diagrams the mentor asked for.
Light mode
A three-state control: follow system, light, dark. Three rather than two because "follow system" is the one most people want, a binary switch cannot express it, and silently pinning a theme on first visit is what sends people looking for a setting. A segmented control rather than the usual sun/moon switch, for the same reason.
How it works. Every colour moves out of
tailwind.config.jsand into CSS custom properties holding RGB channels, sorgb(var(--signal) / <alpha-value>)keeps Tailwind's opacity modifiers composing. Two concrete theme blocks and no media query in the stylesheet: a pre-paint script inindex.htmlresolves "system" and stampsdata-themeon<html>before React mounts, which is what stops the page flashing the wrong theme on load.useThemekeeps following the OS while the preference is "system".Light is a real inversion, not the dark palette lightened. The surface step flips so
raisedstill means "this lifts": on dark a card is lighter than the page, on light it is white against off-white. Every ink tone and severity colour is re-picked, because#62C073on white is 2.1:1 and a 1.6px chart stroke in it simply disappears.The 67
bg-white/[0.0x]washes were the actual blocker. White at 3% over a near-black card is a subtle lift; over a white card it is nothing at all. They collapse onto three semantic surface tokens that invert with the theme.The contrast gate
frontend/scripts/check-contrast.mjsreads the palette straight out ofindex.css— so it cannot drift from what ships — and checks every foreground tone against every surface in both themes, plus the chart series at the 3:1 non-text minimum. It runs as part ofnpm run build.It immediately found twelve failures, three of them in the dark theme that already shipped:
ink-2,ink-3andink-4only ever cleared AA against the card. A nested block lifts the background enough to sink all three, and nothing was checking. Both palettes are adjusted until all 112 pairs pass.Diagrams
Five, each in a dark and a light variant, in
docs/diagrams/with anindex.htmlcontact sheet:01-architecture02-incident-flow03-recovery-ladder04-data-sources05-earned-autonomyGenerated by
scripts/make-diagrams.mjs, hand-built rather than Mermaid because these sit next to deck slides that were designed and have to carry the product's own palette and type scale. The palette is lifted fromindex.css, so the diagrams, the console and the deck are one visual system.The geometry gate
SVG has no layout engine, so a coordinate that is 80px wrong does not raise an error — it produces a picture that is quietly unreadable. Every solid box and every arrow label registers its rectangle, and the generator exits non-zero on any overlap or overflow.
It earned its place immediately:
actionrendering underneathread modelsituations.diagnosedbeing wider than the 74px gap it sat in, so its white-out rect overprinted the node on either sideTwo things a gate cannot check were found by looking at the output: the execute arrow pointed at empty space (now an explicit Kubernetes API node), and a 30px title collided with its own tag because
node()assumed a 17px one.Topology is read, not remembered
Testing
npm run buildpasses, which now includes the contrast gate (112/112).node scripts/make-diagrams.mjspasses the geometry gate for all five.tsc --noEmitclean.Note
frontend/scripts/check-contrast.mjsis worth keeping in CI. The three dark-theme failures it found had been live since the redesign, and nothing else would have caught them.🤖 Generated with Claude Code