Repository navigation
Add the Neutral theme and a per-user theme picker - #293
Open
salman1993 wants to merge 16 commits into
Open
salman1993 wants to merge 16 commits into
salman1993 wants to merge 16 commits into
Conversation
Mermaid labels took their font from <html>, so a theme that changes --font-sans would restyle diagrams inside slides too. foundation.css now names the built-in stacks --font-builtin-sans and --font-builtin-mono, and decks set --font-sans and --font-mono back to them. Mermaid reads the font from the diagram's container, and its configuration cache keys on the font as well as the palette, so a deck and a document diagram on one page each get their own. Classic looks the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neutral is the reading look from the warm-neutral reading view, ported into theme hooks: warm grays, the system font, no glass or page backdrop, the document flat on the page, quieter code blocks and its own Mermaid palette, in light and dark. It also hides an opening H1 that repeats the plan title; render_content_regions(title:) marks those documents, and Classic ignores the mark. Each person picks a theme under Settings > Appearance > Theme, next to the existing light/dark Mode row. coplan_users.app_theme stores "default" (follow the host's config.default_theme) or a theme key. The pick applies without a reload, saves with PATCH /settings/app_theme, and reverts if the save fails. A stored theme the host later removes falls back to the default and doesn't block saving the user. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A half-filled circle beside notifications opens a small popover with the light/dark mode (System, Light, Dark) and the app theme (Classic or Neutral, the one showing checked). Picks apply at once, save in the background like Settings, and the popover stays open to compare. It positions on beforetoggle, so it never paints a frame at the wrong spot. The menu reuses the mode and theme controllers. They now keep each other's radios in step, so the menu and Settings agree when both are on screen, and the app theme controller takes the stored choice from the page, since the menu has no Default option to read it from. Segmented controls also get a visible keyboard focus ring. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Themes.default now returns a Theme, and Themes.resolve(choice) owns the fallback from a stored choice to the theme it shows: the named theme, else the host default, else Classic. The helpers and both pickers use it. Also note why the picker has its own coplan:app-theme event, and say that CoPlan may remove a theme in a later release rather than "retire" one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mermaid took the label font from the diagram's container but the palette from <html>, with a separate deck check to skip it. Both now come from the container, and .deck resets every palette variable to initial, so slides keep Mermaid's built-in themes the same way they keep the deck's fonts. The configuration cache also keys on the palette values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neutral hid an opening H1 that repeated the plan title. That made the theme change what the page shows, not only how it looks. Drop the rule, MarkdownHelper#repeats_title?, the title: argument and the title in the content cache key. Neutral's document H1 is now 1.25rem, under the 1.75rem plan title, so a repeated title reads as a heading below it. THEMES.md now says themes set custom properties only, and that a fix for the repeated title belongs to every theme. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neutral repeated every color in a forced-dark block and again in a system-dark block. Each color now carries both values in light-dark(), which follows the mode's color-scheme. Shadows have the same three layers in both modes, with transparent where a mode has none, so each mode looks as it did. Only the Mermaid hex palette keeps per-mode blocks, because getComputedStyle returns light-dark() unresolved. A computed-style diff of the reader, editor and Settings, light, dark and system, desktop and phone, matched before and after apart from those transparent shadow layers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phones size the plan title with --plan-title-size-narrow, 1.25rem by default, the same as Neutral's new document H1. Neutral sets it to 1.5rem, so a repeated title still reads as the heading below the title. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neutral set its own H1, H2 and H3 sizes, and its 20px H1 came out smaller than its 22px H2. Drop all three, so headings take the shared scale Classic uses: 24, 20 and 18px under the 28px plan title. Neutral keeps its heading leading, spacing, weight and tracking. Also drop the 1.5rem phone plan title from b9194aa: it made a heavy header at 390px. On phones the H1 is now larger than the 20px plan title; the fix for that is the all-themes handling of a repeated title. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only lightness changes, so each color keeps its hue and chroma. - Dark muted text and the code label go from L 0.68 to 0.75 (APCA Lc -45 to -57), and dark code comments to 0.72. They were dimmer than Classic's dark muted text. - Dark keyword, tag and deletion colors go from L 0.76 to 0.8, so they are as bright as the other syntax colors (Lc -63). - The light deletion background drops to C 0.025, inside sRGB. - Sequence diagram lifelines reach 3:1 against the diagram in both modes (#8f8c84 light, #6b6964 dark). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Floating panels already have a 1px border, so the shadow drops its ring. In dark mode the shadow is now transparent: the black ring made the edge look thick and muddy, and the drop couldn't be seen. - Add an --image-radius hook (Classic keeps --radius). Neutral sets 6px, so images match code blocks, diagrams and tables. The image resize handle follows it, and decks reset it. - The dark diagram background moves to #252422, the same tint as a code block. Clusters go to #282725 to stay above it, and lifelines to #706e69 to keep 3:1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From a UI review of Neutral: - Set the reading measure to 68ch. 80ch ran 100-115 characters a line, because a ch is the width of "0", not an average letter. - Give shadows three heights instead of one. Page cards and pills get a hairline drop, buttons and hover lifts a small one, and menus, dialogs and floating panels keep the full drop. - Add --reading-h4-weight and set it to 600 in Neutral, so an H4 (body size) no longer reads as body text at weight 500. - Bring back --plan-title-size-narrow, so the plan title stays above the document's H1 on phones. - Keep sup and sub from raising their line, in every theme. Neutral's 1.6 leading made footnote markers push lines apart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From a ship check of Neutral: - The editable title now reads the same title hooks as the plain title. Before, `.page-header h1` set it to 24px at weight 700, so clicking Edit in Neutral shrank the 28px/500 title, made it bold, and moved the body by about 5px. Classic's values don't change. - The Theme and Mode segments on Settings are radio groups named by their row labels. A screen reader now says which choice a radio belongs to. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80e1d12 gave sup and sub a line-height of 0. The editor's citation button inherits its font from the sup, so it took that line height too and drew at zero height: it couldn't be clicked, in every theme. The button now sets its own line height. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
Author
salman1993
marked this pull request as ready for review
October 31, 2026 18:11
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 12a5ba81bd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Settings and the bar's Appearance menu each have an app-theme controller, and each kept its own save queue. A pick in Settings followed quickly by one in the menu sent both saves at once, and if the first landed last the server kept the older theme while the page showed the newer one. The queue now lives at module level, so every control's saves go out in the order they were picked. Co-Authored-By: Claude Opus 5.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.






What changed and why
Stacked on #290 (the theme system). This PR adds a second theme, Neutral, and lets each person pick their theme. Classic stays the default, so Classic readers see the same page, with one exception: footnote markers and other raised text no longer push their line apart (see the last bullet).
engine/app/assets/stylesheets/coplan/themes/neutral.cssand sets custom properties only, the hooks fromdocs/THEMES.md. Each color gives both modes inlight-dark(). Only the Mermaid hex palette has dark-mode blocks, because Mermaid reads it withgetComputedStyle.--image-radius(Classic keeps--radius) and--reading-h4-weight. Decks reset--image-radius.PATCH /settings/app_theme, and reverts if the save fails.coplan_users.app_theme, default"default"(follow the host'sconfig.default_theme).Themes.resolveturns a stored choice into the theme it shows. A stored theme that a later CoPlan release removes falls back to the default..deckresets the theme's fonts, image radius and all twelve Mermaid palette variables, and Mermaid reads its label font and palette from the diagram's container.supandsubin rendered Markdown haveline-height: 0in every theme, so a footnote marker keeps its line's height. The editor's citation button sets its own line height so it stays clickable.Hosts must copy the new migration with
bin/rails co_plan:install:migrations.Evidence
Screenshots to follow.
How to try it
/hampton/demo-content/rich-text/reading-specimen-webhook-delivery-through-a-durable-outbox. Expect warm grays, the system font, the document flat on the page, headings stepping down from the plan title, and right-aligned code labels. Switch between System, Light and Dark in the same menu.Testing
New browser specs in
spec/system/app_theme_spec.rbcover the picker (no-reload switch, Default, failed-save revert, quick picks in order), the bar's Appearance menu (in step with Settings, on screen at 320px, correct after a Turbo cache restore), Neutral's flat document, reading type and heading scale in both modes, editor typography, and deck diagram fonts and colors.changed_sections_ux_spec.rbnow checks the mobile update dots under both themes.spec/lib/deck_theme_isolation_spec.rb(from Add app theme abstraction with Classic as the default #290) passes withneutral.css.bundle exec rspecon 7cc0c85: 3090 examples, 4 failures. Three were editor citation specs: the sharedsupline-height made the editor's citation button zero-height. 12a5ba8 fixes that, and the three spec files (90 examples) now pass. The fourth, a template-notes spec, passed on rerun.Added or updated real JavaScript-enabled browser specs in
spec/system/for changed UI behavior, covering the user interaction and visible result; or explained why no browser UI is involved.Added model, service, or request specs where needed for domain behavior, authorization, or API cases.
Ran
bundle exec rspec, or explained why it could not run and listed the specs that did run.Tested affected UI behavior in both light and dark mode, or explained why mode testing does not apply.
Attached a video or images demonstrating the change, if this PR adds or changes a feature or fixes a UI bug.
🤖 Generated with Claude Code