Explore/dark mode theme - #68
Merged
Merged
Conversation
Adds a real dark-mode token pass on top of the light "paper cream / navy ink / blue accent" theme from the updated-ui redesign, following prefers-color-scheme automatically. Re-tunes every existing hue for a dark navy surface rather than introducing a new palette: - Surface: #070c1a / #0b1226 / #101a35 (was cream/paper) - Ink: the light theme's own paper cream (#f2e9d6), reused as the dark theme's text color instead of a separate near-white - Accent: #3d8fe0 (brightened from the light-mode blue) - Identity: teal #3fae9c, terracotta #e08a54, violet #a08cf0 Two helper custom properties (--paper-rgb, --ink-rgb) let the one-off rgba() literals scattered through app-theme.css (glass nav/sidebar backgrounds, hover washes, texture patterns) flip with the theme instead of staying baked to the light values -- box-shadows are deliberately left alone since a shadow should stay dark-hued in both themes, not invert to a light glow. The logo's recolor filter gets its own dark-mode chain since it's driven by a filter on a black source image, not --ink. Also mirrors the token values into globals.css's plain :root block, which app-theme.css doesn't otherwise shadow for consumers outside .app-page/.auth-page. --workspace-* tokens are untouched -- the embedded IDE surface is already permanently dark by design. Every dark rule is duplicated under both `@media (prefers-color-scheme: dark)` and `[data-theme="dark"]`. Only the media query is live today (no theme-toggle UI exists yet); the data-theme selectors are prepared for whenever one is added, at zero cost if it never is. Verified by inlining the real CSS into a throwaway static harness (not committed) and toggling data-theme -- confirmed to render correctly. Could not verify against the live dev server: middleware fails to build for every route in this environment on a pre-existing, unrelated @azure/core-tracing/@azure/core-lro export mismatch (also hit during the gen2 test run on the control-updates branch), not touched here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two real bugs, both from the previous commit's dark tokens only reaching
app-theme.css's own selectors:
1. globals.css, mission-control.css, team-chat.css and
settings/orca-theme.css each hardcode their own copies of the current
light-palette hex/rgba values instead of referencing the shared tokens
-- over 150 occurrences. Toggling the tokens did nothing for any of
them, which is why gen2 and sign-in (styled mostly through app-theme.css
directly) went dark while the dashboard, rooms, admin, and mission
control did not.
Fixed every occurrence that is a bare, unwrapped literal (verified by
excluding anything already inside `var(--token, fallback)`, which was
already correct and needed no change). Two new RGB-triplet helpers,
--accent-rgb and --teal-rgb, join the existing --paper-rgb/--ink-rgb so
the many one-off rgba() badges/borders/washes flip too. Modal-backdrop
scrims are deliberately left as a literal dark navy wash in both themes
-- a dimmer should stay dark, not invert to a light glow when it
happens to reuse the ink color.
Also fixed `html`/`body { background: #f2e9d6 }` in globals.css, which
applied globally and outside any dark-aware token -- almost certainly
the dominant reason pages still looked light at their edges regardless
of what their own content did.
orca-theme.css's Tailwind v4 `@theme` block can't itself be
conditional, so its --color-* overrides are written as ordinary
selector rules after it, following the same pattern as everywhere else.
Left untouched, and flagged rather than guessed at: a second, older
layer of literals from at least one earlier redesign
(rgba(237,238,240,*), rgba(23,59,45,*), #121417, #1a1d21, plus a few
standalone colors like #46c771/#e3c98a/#86590b) that isn't even
rendering today's intended light theme correctly -- a pre-existing bug
independent of dark mode, not safe to fix by blind substitution.
2. There was no way to switch modes -- dark mode only ever followed the OS
preference. Added `ThemeToggle`, a standalone icon button (not a menu
item, so it doesn't require opening anything to find) next to the
profile menu in both AppChrome layouts and on the sign-in page. Clicking
it stamps an explicit `data-theme` on <html> and remembers the choice in
localStorage; a blocking inline script in the root layout's <head>
re-stamps that choice before first paint so a returning dark-mode
visitor never sees a light flash. Until a visitor ever clicks it, the
theme still just follows `prefers-color-scheme` with no JS involved.
Verified with the same throwaway static-harness technique as the previous
commit (real CSS inlined, data-theme flipped directly) since the dev
server still can't build on the pre-existing, unrelated
@azure/core-tracing/@azure/core-lro dependency conflict -- confirmed the
dashboard's stat-card/workspace-browser/workspace-card, previously stuck
light, now render correctly in both themes with no regression to the
light-mode screenshot from the prior commit.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A third, previously-missed theme file: product-theme.css is a separate Tailwind @theme block scoped to .product-scope/.rooms-scope, hardcoding its own copy of the light palette independent of both app-theme.css's plain CSS tokens and settings/orca-theme.css's own @theme block. Rooms and the dashboard's actual workspace grid (components/workspace/ workspace-grid.tsx) are built entirely through this file's Tailwind utility classes (text-primary, border-border, bg-card, etc.), so neither of the previous two commits reached them at all -- confirmed live: this is why Rooms stayed light after everything else went dark. Gives product-theme.css the same treatment as orca-theme.css: a dark override block redeclaring every --color-* custom property as an ordinary rule after the @theme block (which can't itself be conditional), duplicated under both the prefers-color-scheme media query and [data-theme="dark"]. Also updates app-theme.test.ts, which had one assertion hardcoded to the exact light-mode literal `rgba(255, 253, 247, 0.72)` for .workspace-browser -- expected breakage from the --paper-rgb fix two commits ago, not a regression; updated to check for the theme-aware reference instead. Adds two new tests locking in that both app-theme.css and product-theme.css now carry a dark override with the right key values. Verified against the real running dev server this time (previous two commits could only use a static-CSS harness): dashboard, Rooms, and Settings all render correctly in both themes, and clicking the toggle flips every one of them instantly with no reload. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
app-theme.css (plain CSS custom properties), product-theme.css (a Tailwind @theme block for Rooms/dashboard) and settings/orca-theme.css (a separate Tailwind @theme block for Settings) each held their own independent copy of the same cream/navy/blue palette under three different naming conventions. That duplication is what let Rooms drift out of sync with everything else going dark two commits ago, and it will keep happening on every future redesign unless the duplication itself goes away -- fixing today's instance without fixing the structure just schedules the next one. Adds theme-tokens.css as the single file that actually writes a hex or rgba literal for this palette, as plain --brand-* custom properties (raw swatches, not role names) with the light default in :root and the dark override under both prefers-color-scheme and [data-theme="dark"]. Imported once, globally, from the root layout -- CSS custom properties on :root are visible to every stylesheet regardless of which one declared them, so app-theme.css, product-theme.css and orca-theme.css don't need their own copy or their own dark-mode block anymore. Each of them keeps its own @theme/token names (--codev-*, --color-*) and its own structural rules (scoping class, radius, layout), now expressed as var() references into the shared swatches instead of independent literals. Deliberately did NOT force every surface to identical values: Rooms and the dashboard sit over an animated gradient backdrop and use translucent glass-panel cards, while Settings has no such backdrop and uses solid opaque cards. Both derive from the same --brand-paper-rgb swatch, just at different alpha, because that's a real design difference between the two surfaces, not drift to eliminate. `.workspace-page` (globals.css, the embedded IDE, permanently dark by design) and `.lp-page` (landing.css, the marketing page's own richer multi-hue palette) are deliberately untouched -- neither is part of the authenticated product's shared palette this file governs. Updated app-theme.test.ts's assertions to match: checks theme-tokens.css for the actual literals, and checks the three consumer files for var() references plus the *absence* of any hex/rgba literal, so the test would catch a regression back into per-file duplication. Verified against the real dev server (not the static-harness workaround from earlier commits): Rooms, dashboard, and Settings all render identically to before this refactor in both themes, confirming this is a pure internal consolidation with no visible change. Full apps/web suite: 233 files / 1199 tests passed, 1 pre-existing skip. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…e else OrcaCard (components/settings/orca-style.tsx) -- used across Settings and the workspace activity feed -- rendered its own visual treatment instead of the shared shadcn <Card> that Rooms and the dashboard use (components/ui/card.tsx): border-border/50 + bg-card/50 + shadow-xs, versus Card's plain border-border + bg-card + text-card-foreground. The 50%-opacity border and background made every Settings card read as a visibly fainter, muddier surface than a Rooms or dashboard card, even though both now pull from the exact same theme-tokens.css swatches. Aligned OrcaCard's border/background/text classes to match <Card> exactly and dropped the extra shadow; kept its own px-7 py-6 padding, since that's a real layout choice for settings rows, not part of the "look" that was inconsistent. Verified against the real dev server in both themes: Settings' provider cards and profile cards now render with the same solid card surface as Rooms/the dashboard. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
OrcaCard (components/settings/orca-style.tsx) became a byte-for-byte
duplicate of components/ui/card.tsx's <Card> the moment its classes were
aligned to match in the previous commit -- at that point it was pure
indirection with no remaining reason to exist as its own component.
Removed it and switched every consumer to the shared <Card> directly:
provider-account-card.tsx, integrations-list.tsx, and
workspace-activity-feed.tsx, plus four page files that used it inline
(settings/personal/{environment,profile}/page.tsx and
workspaces/[workspaceId]/{session-imports/page.tsx,activity/layout.tsx}
-- the latter only for a stale doc comment naming it).
Every call site already passed its own padding override, so this is a
behavior-identical swap, not a redesign -- confirmed against the real
dev server on Profile, Environment Variables, Integrations, and AI
Provider Accounts, all rendering identically to before in both themes.
OrcaPageShell, OrcaPageHeader, and OrcaSubsectionHeader stay -- Rooms and
the dashboard have no equivalent shared components for a page shell or
header (workspace-grid.tsx hand-rolls its own <main className=
"product-scope"> and its own eyebrow/h1/p header inline each time), so
removing these would mean duplicating that markup across seven
settings/workspace-activity pages instead of keeping it in one place.
That would be a step away from consistency, not toward it.
settings/orca-theme.css (the @theme block these components read from)
also stays: it's the only place --color-worktree-sidebar-* is defined,
which components/settings/SettingsSidebar.tsx actually consumes and
product-theme.css has no equivalent for.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The "Integrations"/"Profile"/etc active nav item used bg-worktree-sidebar- accent (a solid fill) plus ring-1 ring-worktree-sidebar-ring/25 stacked on top. bg-worktree-sidebar-accent resolves to --brand-paper-tan, which in dark mode is #101a35 -- a fully opaque dark navy-blue, not the light neutral tan it is in light mode. Combined with the blue ring, the active item read as a heavy, solid blue block, visibly heavier than the main app sidebar's own active state one level up, which just uses a 12%-opacity accent tint with no fill or ring at all. Swapped to the same soft-tint convention: bg-primary/10 text-primary, no ring. Softened the hover state the same way (hover:bg-primary/5) since it read from the same heavy token and would have hit the identical problem on interaction. Verified against the real dev server: the active settings nav item is now a light, translucent accent wash consistent with the rest of the product, in both themes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nt rule Per feedback that the bg-primary/10 blue wash still read as heavy: active state is now a neutral bg-foreground/5 background with a 2px border-primary rule on the left edge, text in --foreground rather than accent-colored. "Selected" now reads through a precise mark instead of a color wash. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
No description provided.