Skip to content

Restore theme picker with system dark support - #6951

Closed
piyushsarkar-dev wants to merge 1 commit into
nexu-io:mainfrom
piyushsarkar-dev:main
Closed

Restore theme picker with system dark support#6951
piyushsarkar-dev wants to merge 1 commit into
nexu-io:mainfrom
piyushsarkar-dev:main

Conversation

@piyushsarkar-dev

Copy link
Copy Markdown

Brings back theme controls in Settings with Light, Dark, and System options, and wires theme through app appearance updates so document state and host window appearance stay in sync. Theme persistence now accepts valid stored values (instead of forcing light), with a default fallback for invalid values.

Updates shared config contracts to include theme, adds new i18n strings, and adjusts dark-mode CSS selectors to treat data-theme="system" as OS-following dark mode. Tests were rewritten to validate the restored theme UI and the new theme persistence/application behavior.

Fixes #

Why

What users will see

Surface area

  • UI — new page / dialog / panel / menu item / setting / empty state in apps/web or apps/desktop (including Electron menu bar)
  • Keyboard shortcut — new or changed
  • CLI / env var — new od subcommand or flag, new tools-dev / tools-pack flag, or new OD_* env var
  • API / contract — new /api/* endpoint, new SSE event, or changed shape in packages/contracts
  • Extension point — new entry under skills/, design-systems/, design-templates/, or craft/, or change to the skills protocol
  • i18n keys — added new translation keys (see TRANSLATIONS.md for the locale workflow)
  • New top-level dependency — adding any new entry to the root package.json (dependencies or devDependencies); workspace-package package.json files are out of scope. Include a paragraph on what we get vs. what bytes we ship (see CONTRIBUTING.md → Code style)
  • Default behavior change — changes what existing users experience without opting in (default model, default setting, file/SQLite schema, auto-network on startup, auto-install)
  • None — internal refactor, docs, tests, or translation update only

Screenshots

Bug fix verification

Validation

Brings back theme controls in Settings with Light, Dark, and System options, and wires theme through app appearance updates so document state and host window appearance stay in sync. Theme persistence now accepts valid stored values (instead of forcing light), with a default fallback for invalid values.

Updates shared config contracts to include `theme`, adds new i18n strings, and adjusts dark-mode CSS selectors to treat `data-theme="system"` as OS-following dark mode. Tests were rewritten to validate the restored theme UI and the new theme persistence/application behavior.
@lefarcen

Copy link
Copy Markdown
Contributor

Thanks @piyushsarkar-dev — restoring the theme picker and wiring system-dark behavior back through Settings/App/config is a meaningful fix, and I’ll take care of the initial triage from here.

💡 To drive this PR to merge hands-free, paste this to your AI coding agent (Claude Code / Codex / opencode / Cursor …):
Take over nexu-io/open-design#6951 until it merges — read https://raw.githubusercontent.com/nexu-io/looper/main/skills/pr-takeover/SKILL.md and follow it.

@lefarcen
lefarcen requested a review from PerishCode August 16, 2026 09:10
@lefarcen lefarcen added size/L PR changes 300-700 lines risk/medium Medium risk: regular code changes type/bugfix Bug fix labels Aug 16, 2026
@lefarcen

Copy link
Copy Markdown
Contributor

🧪 This PR has changes that need a manual QA pass before merge — please hold off self-merging for now; we'll loop QA in once it's merge-ready (and design/product have signed off, where applicable).

@lefarcen lefarcen added needs-design-review Awaiting design review (external UI change); cleared by the Odcrew App applying design-approved needs-validation Runtime change detected; needs human or /explore agent validation. labels Aug 16, 2026

@lefarcen lefarcen 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.

Hey @piyushsarkar-dev — bringing the theme controls back and wiring the system-dark path through Settings/App/config is a solid direction. Before pool review can scope this cleanly, could you fill in the missing PR-body pieces: Why, What users will see, Surface area, and Validation with what you actually ran? Related: #6168 removed this setting and forced light, so it would also help to say explicitly whether this PR is restoring that earlier behavior and what changed since then.

@PerishCode PerishCode 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.

The restored picker currently leaves system mode inconsistent across first paint, runtime theme consumers, and the typed locale contract. The inline findings below need to be addressed before this can merge.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

getOpenDesignHost()?.appearance?.setTheme(FORCED_APP_THEME);
const resolvedTheme = resolveAppTheme(theme);

root.setAttribute('data-theme', resolvedTheme);

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.

BLOCKING: Preserve the existing system-theme contract across every consumer before stamping data-theme=system. Several unchanged consumers only implement system dark as html:not([data-theme]): for example apps/web/src/styles/workspace/artifacts.css lines 4224-4237 and apps/web/src/components/workspace/TerminalViewer.module.css lines 81-82. With this new attribute present on a dark OS, the main token files become dark but those controls retain their light-specific styling, producing a mixed theme. The changed tests only assert the attribute value, so they do not catch this. Either keep system mode represented by an absent attribute and store the preference separately, or update the complete selector/reader matrix to treat system as OS-following and add a dark-OS fixture matrix covering representative CSS-module and global-style consumers.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

Comment thread apps/web/src/App.tsx
useLayoutEffect(() => {
applyAppearanceToDocument({ accentColor: config.accentColor });
}, [config.accentColor]);
applyAppearanceToDocument({ accentColor: config.accentColor, theme: config.theme });

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.

BLOCKING: Apply the persisted theme in the pre-hydration path as well as this layout effect. apps/web/app/layout.tsx still unconditionally executes document.documentElement.setAttribute('data-theme','light'), so a stored dark/system preference paints light before React reaches this changed line; the comment there explicitly describes the now-obsolete light-only invariant. This reintroduces the startup flash that the pre-hydration script exists to prevent, especially in the packaged app. Update themeInitScript to validate and apply the stored light | dark | system value consistently with resolveAppTheme, update its documentation, and restore a test that executes the script for stored dark and system-on-dark-OS cases.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

'settings.agentInstallGroup': string;
'settings.agentAuthRequired': string;
'settings.agentAuthUnknown': string;
'settings.theme': string;

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.

BLOCKING: Define these new required dictionary keys in every locale. This interface makes all five keys mandatory, but the patch adds them only to en.ts and zh-CN.ts; the other 17 apps/web/src/i18n/locales/*.ts files still export objects explicitly typed as Dict, so the web typecheck cannot succeed and non-English locales cannot render the new labels through the typed contract. Add translations (or the repository-approved fallback values) to all 19 locale files, as required by the root i18n rule.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

@lefarcen

Copy link
Copy Markdown
Contributor

Thanks for the quick pass here, @PerishCode. @piyushsarkar-dev, the current blockers are covered in that review on this head: the system theme contract still needs to be made consistent across first paint/runtime consumers, the pre-hydration path in app/layout.tsx needs to match the restored theme behavior, and the new theme strings need to be defined across the full locale set. Once those are addressed, the next review round should be much cleaner.

@github-actions

Copy link
Copy Markdown
Contributor

Visual regression review

Head: e35d563 · Base: 62483a1

5 changed · 44 unchanged · 0 new without baseline · 0 failed

Changed cases

Case Main PR Diff
visual-home
593 px (0.05%)
main pr diff
visual-home-context-picker
1,111 px (0.09%)
main pr diff
visual-home-plugin-use-staged
4,914 px (0.38%)
main pr diff
visual-home-staged-attachment
3,904 px (0.30%)
main pr diff
visual-topbar-local-cli-model-list
1,179 px (0.09%)
main pr diff
Unchanged cases
Case Main PR Diff
visual-avatar-local-agent-list
57 px (0.00%)
main pr diff
visual-avatar-local-agent-list-panel
0 px (0.00%)
main pr diff
visual-avatar-menu
159 px (0.01%)
main pr diff
visual-avatar-menu-panel
30 px (0.09%)
main pr diff
visual-avatar-open-design-model-picker
186 px (0.01%)
main pr diff
visual-critical-settings
0 px (0.00%)
main pr diff
visual-critical-workspace
487 px (0.04%)
main pr diff
visual-critical-workspace-preview
276 px (0.02%)
main pr diff
visual-design-system-detail
1 px (0.00%)
main pr diff
visual-design-systems
1 px (0.00%)
main pr diff
visual-home-catalog
0 px (0.00%)
main pr diff
visual-home-context-picker-popover
0 px (0.00%)
main pr diff
visual-home-plugin-filter
0 px (0.00%)
main pr diff
visual-home-plugin-use-with-query
0 px (0.00%)
main pr diff
visual-integrations
0 px (0.00%)
main pr diff
visual-integrations-mcp
0 px (0.00%)
main pr diff
visual-integrations-use-everywhere
0 px (0.00%)
main pr diff
visual-new-project-modal
0 px (0.00%)
main pr diff
visual-onboarding-cloud
0 px (0.00%)
main pr diff
visual-plugin-details
0 px (0.00%)
main pr diff

Visual diff is advisory only and does not block merging.

@piyushsarkar-dev piyushsarkar-dev closed this by deleting the head repository Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-design-review Awaiting design review (external UI change); cleared by the Odcrew App applying design-approved needs-validation Runtime change detected; needs human or /explore agent validation. risk/medium Medium risk: regular code changes size/L PR changes 300-700 lines type/bugfix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants