Skip to content

Add Haar, Abyss and Understory atmosphere themes - #456

Closed
parsakhaz wants to merge 1 commit into
mainfrom
themes-nature
Closed

Add Haar, Abyss and Understory atmosphere themes#456
parsakhaz wants to merge 1 commit into
mainfrom
themes-nature

Conversation

@parsakhaz

Copy link
Copy Markdown
Member

Three new themes in the Atmosphere & Natural Light direction — each drawn from a real light condition, low-saturation and tonal rather than neon. One of five parallel theme batches; compare and cherry-pick. No new dependencies.

Try them: check out the branch, pnpm dev, Settings → Appearance → Theme (or the Theme dropdown on the Home page).

Lane: light: simple-plan → prepare-pr.

For cherry-picking: besides the three themes and their registration, this PR carries theme-agnostic scaffolding — a contrast checker, a single THEME_OPTIONS source for both pickers, an isLightTheme() helper (Haar depends on it), and a screenshot generator. Details under Shared changes.

The themes

id name base vibe palette (bg · surface · text · accent · terminal bg) screenshot
haar Haar light Pre-dawn North Sea fog: cold blue-white surfaces, ink text, steel-blue accent #eceff3 · #f5f7f9 · #252d36 · #4f6d8a · #e6ebef Haar
abyss Abyss dark Deep ocean: near-black navy, bioluminescent sea-glass teal accent, sea-life ANSI #07111c · #0b1826 · #dbeaf1 · #4db8ab · #04090f Abyss
understory Understory dark Forest floor: moss-green editor, bark-brown sidebar/chrome, pale lichen accent #131911 · #192117 · #e4e9d9 · #a6b56d · #0d110c Understory

Appearance picker (all three, with their one-line descriptions):

Appearance picker

Design notes:

  • Haar composes on the light base; Abyss and Understory on dark. All three use the islanded-shell layout (like Dusk/Forge/Light-rounded) with theme-specific depth borders.
  • Abyss and Understory are two-tone (sunken editor/terminal below the chrome) with an accent underline on the active tab; Haar keeps fill-mode tabs. Understory's chrome/sidebar is bark brown while the editor is moss — the only theme with a hue split between chrome and editor.
  • Primary buttons in the two dark themes carry near-black text on the accent fill (8–9:1) instead of white (which would fail on teal/lichen).

Contrast

Each of haar, abyss, understory: 44/44 token pairs pass, plus 4/4 high-contrast pairs.

Those numbers come from a new script. No contrast tooling existed (PR #362 fixed tokens by hand), so this adds scripts/check-theme-contrast.mjs (pnpm check:theme-contrast, no dependencies). It resolves var() chains per theme class list the way the cascade does, composites alpha colors, and checks 44 token pairs per theme — body/secondary/tertiary/muted text on backgrounds, sidebar text, button text on button fills (all states), input text and placeholder, status + focus ring at ≥3:1, terminal fg + cursor + all 15 ANSI colors against the terminal background — plus 4 more with the additive .high-contrast class (muted family ≥7:1).

Run with no arguments it also checks the 12 existing themes and surfaces pre-existing debt. I did not touch those tokens (out of scope); listed below so it's not mistaken for a regression from this PR. Because of that debt the script is a standalone command, not part of pnpm lint.

Pre-existing contrast debt in the 12 existing themes (not changed here)
  • --color-input-placeholder under 4.5:1 — dark, dusk, dusk-oled, forge, night-owl, night-owl-oled, terracotta
  • white primary-button text under 4.5:1 — dusk, dusk-oled, forge, terracotta
  • terminal red 2.76:1 — light, light-rounded; terminal bright-black 2.95:1 — ember
  • high-contrast nav-muted under 7:1 against the sidebar surface — light, light-rounded, ember

Shared changes (not theme-specific)

  • Tokens per theme live where the existing themes' do: frontend/src/styles/tokens/colors.css (:root.<id> block + :root.high-contrast.<id> block), effects.css, spacing.css, frontend/src/index.css (body background, islanded shells, depth borders, tab underline, Monaco vars), frontend/src/styles/monaco-overrides.css (note: that file isn't imported anywhere — the live Monaco overrides are the copy in index.css; updated both for parity, deleting the dead file is a separate cleanup).
  • Registration in every place the theme list lives: themeContextValue.ts, ThemeProvider.tsx, both index.html bootstrap scripts, frontend/src/types/config.ts, main/src/types/config.ts.
  • frontend/src/utils/themeOptions.ts — single THEME_OPTIONS list (id · label · description) now feeds both pickers (Appearance settings Select and the HomePage dropdown); the HomePage label map is gone, and a missing entry for any Theme id is a typecheck error. SelectItem gained an optional description line rendered outside ItemText, so the trigger still shows just the label. New themes are grouped after the two Light entries; existing relative order unchanged. Side effect: the HomePage dropdown now uses the same order as Settings (it previously listed Light (sharp)/Dark/OLED at the end).
  • isLightTheme() in themeContextValue.ts replaces four hard-coded theme === 'light' || theme === 'light-rounded' checks (DiffViewer, FileEditor, LogsView, usePaneLogo) — otherwise Haar would have gotten dark Monaco/diff colors and the dark logo.
  • tests/theme-screenshots.spec.ts — opt-in (THEME_SCREENSHOTS=1) generator for screenshots/themes/; skipped in normal runs. Drives the mocked app (terminal dock with a restored ANSI sample + Review/diff panel) at 1440×900. Screenshots are of the real renderer via the existing Playwright mock, not the Electron shell.
  • Tests touched by the picker change: tests/accessibility.spec.ts (theme-name regex; Night Owl menu item matched by label prefix now that items carry a description in their accessible name), tests/settings.spec.ts (same for the Select option), tests/dropdown-keyboard-nav.spec.ts (arrow-key expectations follow the new item order — second item is Light (sharp), selection test now picks Haar).
  • AGENTS.md: one line documenting the contrast gate and screenshot command.

Testing

  • pnpm typecheck, pnpm lint (oxlint, eslint, advisory, knip) — clean.
  • pnpm check:theme-contrast haar abyss understory — pass.
  • pnpm --filter frontend test — 165 passed.
  • Playwright (Chromium against a Vite dev server, mocked electron API): tests/accessibility.spec.ts, tests/settings.spec.ts, tests/dropdown-keyboard-nav.spec.ts, tests/review-availability.spec.ts — all pass except settings.spec.ts:282 (“discards remote subview drafts…”), which also fails on a clean stash of these changes (environmental, unrelated).
  • Screenshots regenerated with THEME_SCREENSHOTS=1 PLAYWRIGHT_PORT=4587 pnpm exec playwright test tests/theme-screenshots.spec.ts.

Manual checks worth doing in the app: toggle High contrast on each of the three; open a Monaco editor tab and a Logs tab under Haar (light detection); check the terminal palette with a real CLI (Claude Code / Codex) under Abyss and Understory.

Three low-saturation themes drawn from natural light: Haar (pre-dawn sea
fog, light base), Abyss (deep ocean, dark), Understory (moss and bark,
dark). Full token coverage in colors.css plus effects/spacing/index.css
shells and Monaco overrides, high-contrast blocks, and registration in
every theme list (provider, bootstrap scripts, config types).

Also: a shared THEME_OPTIONS list with picker descriptions feeding both
theme pickers, an isLightTheme helper replacing hard-coded light checks,
scripts/check-theme-contrast.mjs (pnpm check:theme-contrast), an opt-in
Playwright screenshot generator, and screenshots/themes/ evidence.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@github-actions

Copy link
Copy Markdown

React Doctor found 2 new issues in 1 file · 2 warnings · score 68 / 100 (Needs work) · 3 fixed · vs main

2 warnings

src/components/panels/editor/FileEditor.tsx

  • ⚠️ L63 Many related useState calls prefer-useReducer
  • ⚠️ L1195 Many related useState calls prefer-useReducer

Reviewed by React Doctor for commit 02d4b55. See inline comments for fixes.

parsakhaz added a commit that referenced this pull request Aug 18, 2026
…families (#459)

Consolidates #451, #453, #454, #456 and themes-a11y into one batch: synthwave, acid, tokyo-rain, folio, newsprint, walnut, amber-crt, teletype, dot-matrix, haar, abyss, understory, colorblind-safe, low-fatigue, high-legibility. Pickers read one grouped THEME_OPTIONS list; pnpm theme:contrast gates all 15; pnpm theme:screenshots regenerates screenshots/themes/batch/.
@parsakhaz

Copy link
Copy Markdown
Member Author

Superseded by #459 (merged as 867795a), which consolidated all five theme branches — these themes are on main with their palettes unchanged. Closing without merge.

@parsakhaz parsakhaz closed this Aug 18, 2026
@parsakhaz
parsakhaz deleted the themes-nature branch August 18, 2026 23:00
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