Skip to content

feat(ui): polish pawwork theme to match mockups and enable dark mode#198

Merged
Astro-Han merged 3 commits into
devfrom
worktree-worktree-feat-theme-surface-lift
Apr 23, 2026
Merged

feat(ui): polish pawwork theme to match mockups and enable dark mode#198
Astro-Han merged 3 commits into
devfrom
worktree-worktree-feat-theme-surface-lift

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Apr 23, 2026

Copy link
Copy Markdown
Owner

Summary

Brings the PawWork home + session chrome in line with the latest light / dark mockups and turns on the bundled dark palette so users can switch color schemes from Settings.

  • Light polish: invert the surface layering so content raises to white on a cream shell, de-saturate shell / sidebar cream toward near-neutral to match the mockup, align brand accent to #FF5910, and give the "新建会话" sidebar button an orange-tint fill with orange icon as the primary affordance.
  • Dark palette: fill in a real pawwork dark palette derived from the dark mockups (cool slate content with warm interactive tint; sidebar sits above content, reversing the light layering) plus the matching [data-color-scheme="dark"] shell overrides so the frame / titlebar also switch.
  • Unlock scheme toggle: drop the eight pawwork-light hard-locks in the theme context, simplify the preload so it respects stored light / dark / system instead of stamping light every boot, and preserve stored scheme across legacy theme migrations. canSwitchColorScheme is always true now, so the Settings picker is visible.
  • Titlebar cleanup: remove the back / forward chevrons from the titlebar; the keyboard shortcuts (⌘[ / ⌘]) stay wired through command.register.

Test plan

  • bun dev:desktop — verify light home: sidebar + titlebar cream match the mockup, "新建会话" pill shows orange tint, content surfaces stay white.
  • Settings → General → color scheme — switch to Dark, verify: sidebar lifts above content, titlebar / frame go slate, brand orange stays visible.
  • Switch to System, toggle macOS Appearance, verify the app follows.
  • ⌘[ / ⌘] still navigate history despite the titlebar chevrons being gone.
  • bun test packages/app/src/theme-preload.test.ts — 8 tests pass (first install, stored dark, system, legacy migration).
  • bun typecheck — clean.

Summary by CodeRabbit

  • New Features

    • Color scheme now respects system preferences (light/dark/system options).
    • Dark mode support added for desktop interface.
    • Color scheme switching enabled for all themes.
  • Style

    • Updated theme color palette.
    • Refined sidebar styling.
    • Removed navigation buttons from titlebar.

@Astro-Han Astro-Han added enhancement New feature or request P2 Medium priority app Application behavior and product flows ui Design system and user interface labels Apr 23, 2026
@coderabbitai

coderabbitai Bot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@Astro-Han has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 0 minutes and 9 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 0 minutes and 9 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c0095cf2-cab6-4985-8aa7-87f6ff1f34e2

📥 Commits

Reviewing files that changed from the base of the PR and between 4c9b8c7 and d376d6e.

📒 Files selected for processing (8)
  • packages/app/e2e/app/shell-frame.spec.ts
  • packages/app/public/oc-theme-preload.js
  • packages/app/src/components/titlebar.tsx
  • packages/app/src/index.css
  • packages/app/src/pages/layout/pawwork-sidebar.tsx
  • packages/app/src/theme-preload.test.ts
  • packages/ui/src/theme/context.tsx
  • packages/ui/src/theme/themes/pawwork.json
📝 Walkthrough

Walkthrough

This pull request enables dynamic color scheme selection for the pawwork theme. The preload script now computes color schemes from localStorage or system preferences instead of forcing light mode. The theme context removes restrictions that locked the default theme to light mode, and CSS variables are updated with light/dark mode variants. Component styling and theme tokens are adjusted accordingly.

Changes

Cohort / File(s) Summary
Theme Preload & Script
packages/app/public/oc-theme-preload.js, packages/app/src/theme-preload.test.ts
Dynamic color scheme computation from localStorage or system preferences. Tests updated to validate scheme persistence and resolution logic with mocked matchMedia for system preference detection.
Theme Context & Configuration
packages/ui/src/theme/context.tsx, packages/ui/src/theme/themes/pawwork.json
Removed hardcoded color-scheme restrictions for pawwork theme. Context now permits color scheme switching for all themes. Pawwork theme tokens updated with new color values for both light and dark modes.
Desktop Shell Styling
packages/app/src/index.css
Added dark mode CSS variable overrides for desktop shell. Light/dark mode colors updated for backgrounds, surfaces, borders. Highlight effect refactored into --shell-highlight-overlay variable. Sidebar color adjusted.
UI Components
packages/app/src/components/titlebar.tsx, packages/app/src/pages/layout/pawwork-sidebar.tsx
Titlebar removes navigation state computations and back/forward button UI. Sidebar background changed from bg-background-base to bg-background-weak. "New session" button updated with inline CSS variable overrides for secondary button colors.

Sequence Diagram

sequenceDiagram
    participant Browser as Browser<br/>(Page Load)
    participant Preload as Preload Script
    participant Storage as localStorage
    participant Prefs as System<br/>Preferences
    participant DOM as DOM

    Browser->>Preload: Execute preload script
    Preload->>Storage: Read pawwork theme
    Storage-->>Preload: Return stored theme
    Preload->>Storage: Ensure theme is "pawwork"
    Preload->>Storage: Read pawwork-color-scheme
    Storage-->>Preload: Return scheme value
    
    alt scheme is "light" or "dark"
        Preload->>DOM: Set colorScheme directly
    else scheme is "system"
        Preload->>Prefs: Query prefers-color-scheme
        Prefs-->>Preload: Return system preference
        Preload->>DOM: Set colorScheme to system value
    else invalid or empty
        Preload->>Storage: Reset to "light"
        Preload->>DOM: Set colorScheme to "light"
    end
    
    DOM->>DOM: Apply color-scheme CSS variables
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

desktop, P3

Poem

🐰 Behold, the pawwork theme now dances free,
Light and dark, a spectrum's jubilee!
System calls, localStorage listens bright,
Colors bloom in both the dark and light!
No longer locked, the rabbit's theme takes flight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: polishing the PawWork theme to match mockups and enabling dark mode support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed PR description comprehensively addresses all required template sections with clear summaries, rationale, test plan with checkboxes, and implementation details.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-worktree-feat-theme-surface-lift

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/app/src/index.css`:
- Around line 95-97: Add a blank line immediately before the existing
background: declaration to satisfy Stylelint's rule about spacing; locate the
background: block (the multi-line background property using
var(--shell-highlight-overlay) and linear-gradient(180deg,
var(--shell-background-base), var(--shell-background-weak))) and insert a single
empty line above it so the stylesheet has a separating blank line before that
declaration.

In `@packages/ui/src/theme/themes/pawwork.json`:
- Around line 32-33: The contrast between "button-primary-base" (`#FF5910`) and
"text-on-interactive-base" (`#FFFFFF`) is too low (3.14:1); update pawwork.json to
use colors that meet WCAG AA 4.5:1 for normal text by either darkening
"text-on-interactive-base" (choose a darker hex that yields ≥4.5:1 against
`#FF5910`) or darkening "button-primary-base" (choose a darker hex and keep text
white), then verify the new pair with a contrast checker and commit the adjusted
hex values for the "button-primary-base" and/or "text-on-interactive-base" keys.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ad5c8da2-3530-4696-9fb8-e54fd7bcbea3

📥 Commits

Reviewing files that changed from the base of the PR and between d36c6ba and 4c9b8c7.

📒 Files selected for processing (7)
  • packages/app/public/oc-theme-preload.js
  • packages/app/src/components/titlebar.tsx
  • packages/app/src/index.css
  • packages/app/src/pages/layout/pawwork-sidebar.tsx
  • packages/app/src/theme-preload.test.ts
  • packages/ui/src/theme/context.tsx
  • packages/ui/src/theme/themes/pawwork.json
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: unit-windows-opencode-server-tools
  • GitHub Check: unit-windows-desktop
  • GitHub Check: unit-windows-opencode-session
  • GitHub Check: unit-windows-opencode-config-project
  • GitHub Check: unit-opencode
  • GitHub Check: unit-windows-app
  • GitHub Check: unit-desktop
  • GitHub Check: typecheck
  • GitHub Check: unit-app
  • GitHub Check: smoke-macos-arm64
  • GitHub Check: analyze-js-ts
  • GitHub Check: e2e-artifacts
🧰 Additional context used
📓 Path-based instructions (1)
packages/app/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (packages/app/AGENTS.md)

Always prefer createStore over multiple createSignal calls in SolidJS

Files:

  • packages/app/src/components/titlebar.tsx
  • packages/app/src/pages/layout/pawwork-sidebar.tsx
  • packages/app/src/theme-preload.test.ts
  • packages/app/public/oc-theme-preload.js
🧠 Learnings (16)
📓 Common learnings
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/ui/src/theme/context.tsx:11-16
Timestamp: 2026-04-22T09:32:52.535Z
Learning: In Astro-Han/pawwork (`packages/ui/src/theme/context.tsx` and related files), the renaming of localStorage theme keys from `opencode-*` to `pawwork-*` (THEME_ID, COLOR_SCHEME, THEME_CSS_LIGHT, THEME_CSS_DARK) is intentional and should NOT include a migration path from the old keys. Migrating would re-couple PawWork and OpenCode browser storage namespaces, which the PR is explicitly designed to avoid. A reset to the PawWork default theme on upgrade is acceptable by design.
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 191
File: packages/app/src/components/session/pawwork-skill-meta.ts:38-39
Timestamp: 2026-04-23T15:10:21.635Z
Learning: In Astro-Han/pawwork, Tailwind v4 is configured with `--color-*: initial`, which resets the entire default palette. This means standard Tailwind color utilities like `text-violet-500` resolve to no CSS variable and render black (i.e., they are a no-op). For accent/brand colors that do not have a semantic design token (e.g., the violet writing-assistant accent `#8B5FBF`), use an inline style (e.g., `homeIconStyle: { color: "#8B5FBF" }`) and document the reason with a comment. Do NOT suggest replacing inline hex colors with Tailwind palette utilities in this repo.
📚 Learning: 2026-04-22T09:32:52.535Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/ui/src/theme/context.tsx:11-16
Timestamp: 2026-04-22T09:32:52.535Z
Learning: In Astro-Han/pawwork (`packages/ui/src/theme/context.tsx` and related files), the renaming of localStorage theme keys from `opencode-*` to `pawwork-*` (THEME_ID, COLOR_SCHEME, THEME_CSS_LIGHT, THEME_CSS_DARK) is intentional and should NOT include a migration path from the old keys. Migrating would re-couple PawWork and OpenCode browser storage namespaces, which the PR is explicitly designed to avoid. A reset to the PawWork default theme on upgrade is acceptable by design.

Applied to files:

  • packages/app/src/components/titlebar.tsx
  • packages/app/src/pages/layout/pawwork-sidebar.tsx
  • packages/app/src/theme-preload.test.ts
  • packages/app/public/oc-theme-preload.js
  • packages/app/src/index.css
  • packages/ui/src/theme/themes/pawwork.json
📚 Learning: 2026-04-23T07:23:23.849Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 180
File: packages/app/src/components/session/session-new-view.tsx:13-18
Timestamp: 2026-04-23T07:23:23.849Z
Learning: In pawwork (Astro-Han/pawwork), prefer using `createStore` instead of multiple `createSignal` calls only when the signals represent **coupled** object state that is updated together (i.e., there is at least one shared batch-update site where the state is changed in the same transaction). If the state fields are **independent** and are mutated by separate handlers (e.g., one handler updates only `selectedSkill` while another updates only `mode`), keep them as individual `createSignal` calls—using `createStore` for truly independent fields adds boilerplate without behavioral benefit.

Applied to files:

  • packages/app/src/components/titlebar.tsx
  • packages/app/src/pages/layout/pawwork-sidebar.tsx
  • packages/app/src/theme-preload.test.ts
  • packages/app/public/oc-theme-preload.js
📚 Learning: 2026-04-23T15:10:21.635Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 191
File: packages/app/src/components/session/pawwork-skill-meta.ts:38-39
Timestamp: 2026-04-23T15:10:21.635Z
Learning: This repo configures Tailwind v4 with `--color-*: initial`, which effectively breaks standard Tailwind palette utilities (e.g., `text-violet-500` can resolve to no CSS variable and render as a no-op/black). For brand/accent colors that are not backed by semantic design tokens, use inline styles with the exact hex value (e.g., `style={{ color: '#8B5FBF' }}` / `homeIconStyle: { color: '#8B5FBF' }`) and add a short comment explaining that Tailwind palette utilities won’t work due to the `--color-*: initial` setup. Do not suggest replacing these inline hex colors with Tailwind palette classes anywhere in this repo.

Applied to files:

  • packages/app/src/components/titlebar.tsx
  • packages/app/src/pages/layout/pawwork-sidebar.tsx
  • packages/app/src/theme-preload.test.ts
📚 Learning: 2026-04-23T15:26:03.112Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 193
File: packages/app/src/pages/layout/sidebar-items.tsx:102-107
Timestamp: 2026-04-23T15:26:03.112Z
Learning: In Astro-Han/pawwork (`packages/app/src/pages/layout/sidebar-items.tsx`), the `indicator()` function in `SessionRow` intentionally renders `props.leadingSlot` (the pin button) only as a fallback when no status indicator (running/permission/error/unseen) is active. When a higher-priority status wins the slot, the pin button is removed from the DOM — this is a deliberate design choice for the merged leading slot (`#150`). The keyboard unpin path is preserved via: (1) focusing the row anchor triggers `group-focus-within` which reveals the dots menu trigger, then Tab → Enter → "Unpin Session"; (2) the context menu (right-click / Shift+F10) exposes "Unpin Session". The "always render + CSS overlay" approach was considered but rejected due to z-index/pointer-events complexity; residual `...` slot behavior is tracked in `#192`. Do NOT flag the absence of the pin button from the DOM when a status is active as an accessibility regression.

Applied to files:

  • packages/app/src/pages/layout/pawwork-sidebar.tsx
📚 Learning: 2026-04-22T09:32:52.535Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/ui/src/theme/context.tsx:11-16
Timestamp: 2026-04-22T09:32:52.535Z
Learning: In the PawWork UI theme module (e.g., packages/ui/src/theme/context.tsx and related files), do not add a browser storage migration for the theme localStorage keys renamed from `opencode-*` to `pawwork-*` (`THEME_ID`, `COLOR_SCHEME`, `THEME_CSS_LIGHT`, `THEME_CSS_DARK`). The rename is intentionally meant to keep PawWork and OpenCode storage namespaces decoupled; migrating would re-couple the namespaces. Resetting/using the PawWork default theme on upgrade is acceptable by design.

Applied to files:

  • packages/ui/src/theme/context.tsx
📚 Learning: 2026-04-20T14:36:04.099Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.099Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Import test utilities from `../fixtures` instead of `playwright/test`

Applied to files:

  • packages/app/src/theme-preload.test.ts
📚 Learning: 2026-04-20T14:36:04.099Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.099Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Use `expect.poll(...)` for probing mock or backend state rather than transient DOM visibility

Applied to files:

  • packages/app/src/theme-preload.test.ts
📚 Learning: 2026-04-20T14:36:04.099Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.099Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Prefer the `project` fixture for tests that need a dedicated project with LLM mocking

Applied to files:

  • packages/app/src/theme-preload.test.ts
📚 Learning: 2026-04-20T14:36:31.017Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.017Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Prefer Effect-aware helpers from `fixture/fixture.ts` over building manual runtimes in tests: use `tmpdirScoped()` for scoped temp directories, `provideInstance(dir)(effect)` for low-level binding without directory creation, `provideTmpdirInstance(...)` for single temp instance binding, or `provideTmpdirServer(...)` for tests that also need the test LLM server.

Applied to files:

  • packages/app/src/theme-preload.test.ts
📚 Learning: 2026-04-20T14:36:04.099Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.099Z
Learning: Applies to packages/app/e2e/packages/app/src/testing/**/*.ts : Test-only hooks must be inert unless explicitly enabled and should not add normal-runtime listeners, reactive subscriptions, or per-update allocations

Applied to files:

  • packages/app/src/theme-preload.test.ts
📚 Learning: 2026-04-22T08:49:44.563Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/desktop-electron/src/main/index-sidecar-source.test.ts:3-11
Timestamp: 2026-04-22T08:49:44.563Z
Learning: In `packages/desktop-electron/src/main/index-sidecar-source.test.ts` (Astro-Han/pawwork), the test intentionally uses `expect(source).toContain` / `expect(source).not.toContain` string matching against the raw `index.ts` source text as a lightweight sidecar contract guard. The maintainer has explicitly chosen not to introduce an AST parser (e.g., `babel/parser` or acorn) for this purpose. Do not flag these string-based assertions as fragile or suggest converting them to AST-based matching.

Applied to files:

  • packages/app/src/theme-preload.test.ts
📚 Learning: 2026-04-20T14:36:04.099Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.099Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Test one feature per test file

Applied to files:

  • packages/app/src/theme-preload.test.ts
📚 Learning: 2026-04-22T09:32:52.806Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/opencode/test/provider/provider.test.ts:64-85
Timestamp: 2026-04-22T09:32:52.806Z
Learning: In `packages/opencode/test/provider/provider.test.ts`, the file intentionally uses AppRuntime-based async helpers (`run`, `list`, `getProvider`, etc.) rather than `testEffect(...)` for all tests. Converting individual tests to `testEffect` while leaving the rest on the async pattern would create internal inconsistency. A full harness migration of this file is the right approach if the pattern needs to change, but that should be a separate PR.

Applied to files:

  • packages/app/src/theme-preload.test.ts
📚 Learning: 2026-04-20T14:36:31.017Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.017Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use `testEffect(...)` from `test/lib/effect.ts` for tests that exercise Effect services or Effect-based workflows.

Applied to files:

  • packages/app/src/theme-preload.test.ts
📚 Learning: 2026-04-23T15:10:21.635Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 191
File: packages/app/src/components/session/pawwork-skill-meta.ts:38-39
Timestamp: 2026-04-23T15:10:21.635Z
Learning: In Astro-Han/pawwork, Tailwind v4 is configured with `--color-*: initial`, which resets the entire default palette. This means standard Tailwind color utilities like `text-violet-500` resolve to no CSS variable and render black (i.e., they are a no-op). For accent/brand colors that do not have a semantic design token (e.g., the violet writing-assistant accent `#8B5FBF`), use an inline style (e.g., `homeIconStyle: { color: "#8B5FBF" }`) and document the reason with a comment. Do NOT suggest replacing inline hex colors with Tailwind palette utilities in this repo.

Applied to files:

  • packages/app/public/oc-theme-preload.js
  • packages/ui/src/theme/themes/pawwork.json
🪛 ast-grep (0.42.1)
packages/app/src/theme-preload.test.ts

[warning] 14-14: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: document.head.innerHTML = ""
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)

🪛 Stylelint (17.9.0)
packages/app/src/index.css

[error] 95-97: Expected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🔇 Additional comments (12)
packages/app/src/pages/layout/pawwork-sidebar.tsx (1)

241-258: LGTM!

The sidebar background update and Button styling changes align well with the PR objectives. Using inline CSS variable overrides for the orange-tinted filled primary affordance is appropriate given the repo's Tailwind v4 configuration where --color-*: initial breaks standard palette utilities.

packages/app/src/components/titlebar.tsx (2)

7-7: LGTM!

The import cleanup is correct—Tooltip is no longer needed after removing the back/forward chevron buttons. Keyboard navigation (⌘[ / ⌘]) remains functional via command.register.


144-149: LGTM!

The spacing adjustment and retained conditional rendering logic are correct. The sidebar wrapper div's class change aligns with the titlebar cleanup.

packages/app/public/oc-theme-preload.js (1)

1-31: LGTM!

The preload script correctly implements dynamic color scheme resolution:

  • Directly uses stored "light"/"dark" values
  • Resolves "system" via matchMedia with a defensive window.matchMedia && guard
  • Falls back to "light" for invalid/missing values
  • Clears cached CSS when migrating from non-pawwork themes while preserving the stored scheme

This aligns well with the test coverage in packages/app/src/theme-preload.test.ts.

packages/app/src/theme-preload.test.ts (3)

7-12: LGTM!

The setMatchMedia helper is well-designed with configurable: true allowing proper reassignment between tests. The beforeEach setup correctly initializes a deterministic state for scheme resolution tests.

Also applies to: 14-19


22-50: LGTM!

Test coverage is comprehensive:

  • First-install defaults to "light" with proper storage initialization
  • Stored "dark" scheme is preserved and applied
  • "system" resolves against mocked matchMedia result and persists the "system" preference (not the resolved value)

52-68: LGTM!

The legacy migration tests correctly verify that cached CSS entries are cleared while the stored color scheme ("dark") is preserved during theme migration. This aligns with the PR objective to preserve stored scheme across legacy theme migrations.

packages/ui/src/theme/context.tsx (3)

98-100: LGTM!

Removing the pawwork-specific coercion from resolveMode is correct. The underscore prefix (_themeId) clearly signals the unused parameter for future extensibility.


147-148: LGTM!

The fallback logic is well-designed:

  • First-install users default to "light" for a predictable initial experience
  • Returning users without a stored scheme get "system" to respect their OS preference

264-268: LGTM!

The simplified setColorScheme function and unconditional canSwitchColorScheme: () => true correctly unlock scheme switching for all themes. This enables the color scheme selector in Settings → General and the mod+shift+s command (per packages/app/src/pages/layout.tsx:1237-1262).

Also applies to: 278-278

packages/app/src/index.css (2)

77-98: LGTM!

The light mode shell token updates and highlight overlay integration look correct. The new --shell-highlight-overlay property cleanly separates the radial gradient for reuse in both modes.


100-114: LGTM!

The dark mode desktop-shell overrides are well-structured. The selector :root[data-color-scheme="dark"] [data-component="desktop-shell"][data-platform="desktop"] correctly targets the shell when dark mode is active (driven by the preload script and theme context).

Comment thread packages/app/src/index.css
Comment thread packages/ui/src/theme/themes/pawwork.json
@Astro-Han Astro-Han force-pushed the worktree-worktree-feat-theme-surface-lift branch from 4c9b8c7 to f0413d6 Compare April 23, 2026 17:02
The back/forward chevrons in the titlebar duplicated keyboard shortcuts
(⌘[ / ⌘]) which remain wired through command.register, and added visual
noise that diverges from the PawWork home mockups. Drop the UI buttons
along with the now-dead canBack / canForward / hasProjects memos and
Tooltip import.
Light polish:
- Invert the surface layering so content raises to white on top of a
  cream shell, reversing the previous darker-on-top gradient that read
  as muddy gray in the content area.
- Pull shell, sidebar, and background-weak down to near-neutral cream
  (R≈G≈B) to match the mockup's clean off-white chrome.
- Align brand accent to #FF5910 everywhere (replaces the #E8533A drift)
  and give the sidebar "new session" button an orange-tint fill with
  orange icon so it reads as the primary affordance.

Dark palette:
- Add a real pawwork dark palette (cool slate with warm interactive
  tint) derived from the dark mockups, replacing the placeholder that
  mirrored light values. In dark, sidebar sits slightly above content
  rather than below it, matching the mockup's layering.
- Add the matching [data-color-scheme="dark"] shell overrides so the
  titlebar, frame, and chrome tokens also switch to the dark palette.
Now that pawwork ships a real dark palette, stop force-locking the
theme to light. Drop the eight pawwork-special cases in the theme
context (resolveMode, shouldCacheTheme, onStorage, mount, setTheme,
setColorScheme) so canSwitchColorScheme returns true and Settings
surfaces the light / dark / system picker.

The preload script no longer overwrites pawwork-color-scheme on every
boot; it respects stored light / dark and resolves "system" against
prefers-color-scheme for the first paint. Legacy theme migrations
continue to redirect to pawwork but preserve the user's stored scheme
instead of stamping light. Tests cover first install, stored dark,
system, and legacy migration paths.
@Astro-Han Astro-Han force-pushed the worktree-worktree-feat-theme-surface-lift branch from f0413d6 to d376d6e Compare April 23, 2026 17:06
@Astro-Han Astro-Han merged commit 733b5fb into dev Apr 23, 2026
22 of 23 checks passed
@Astro-Han Astro-Han deleted the worktree-worktree-feat-theme-surface-lift branch April 23, 2026 17:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows enhancement New feature or request P2 Medium priority ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant