Skip to content

DO NOT MERGE VSCode theme support in T3 Code#2550

Open
bmdavis419 wants to merge 7 commits intomainfrom
t3code/vscode-theme-plan
Open

DO NOT MERGE VSCode theme support in T3 Code#2550
bmdavis419 wants to merge 7 commits intomainfrom
t3code/vscode-theme-plan

Conversation

@bmdavis419
Copy link
Copy Markdown

@bmdavis419 bmdavis419 commented May 6, 2026

auto-detects vscode/cursor themes installed on ur machine. u pick one, it just works in t3 code

image image

enjoy the 5.5 xHigh slop pr, do with it what u will I just want this to exist at some point in some way

Summary

  • Add desktop-side discovery and loading for VS Code and Cursor color themes, including safe path resolution and JSONC settings parsing.
  • Extend the desktop bridge and contracts so the web app can refresh, select, and apply external themes.
  • Update web theme handling so syntax highlighting, diffs, terminal colors, and app CSS can respond to resolved editor themes.
  • Add tests for theme discovery, theme resolution, shared theme mapping, and client settings persistence.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • Not run: bun run test

Note

Add VSCode/Cursor editor theme discovery and application to T3 Code

  • Adds a full theme discovery pipeline: the desktop main process exposes IPC handlers to scan VS Code, VS Code Insiders, and Cursor extension directories for installed color themes, load a selected theme by ID, and read editor theme preferences.
  • Introduces a structured ThemePreference type (system, builtin, external, follow-editor) stored in client settings; the theme runtime loads and caches external themes asynchronously with deduplication and localStorage bootstrapping.
  • Maps VS Code workbench colors to app CSS variables (sidebar, terminal, diff, chat-request tokens) via a new mapVscodeColorsToAppVariables utility in packages/shared/src/themeMapping.ts; desktop window chrome colors (background, title bar) update to match the active theme.
  • Replaces Suspense-based code block highlighting with an async, idle-scheduled ShikiCodeBlock that caches results per code+language+theme and falls back gracefully for unsupported languages.
  • The General Settings theme selector now lists discovered external themes and supports refresh; resolveSyntaxThemeName registers content-addressed custom Shiki themes derived from the resolved color theme.
  • Risk: This PR is marked DO NOT MERGE and introduces many new IPC channels and a significantly reworked theme runtime that changes how dark mode, CSS variables, and desktop window colors are derived.

Macroscope summarized bb538d7.

bmdavis419 added 2 commits May 6, 2026 01:09
- Document discovery, mapping, and persistence strategy
- Outline desktop bridge, settings UI, and rollout phases
- Discover editor themes from desktop installs
- Map theme colors into shared app and syntax tokens
- Wire theme state through desktop, web, and settings
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 76407cd2-f15a-487d-a6b3-544e59fc748c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/vscode-theme-plan

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

@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels May 6, 2026
@bmdavis419 bmdavis419 changed the title Add VS Code theme discovery and app theming VSCode theme support in T3 Code May 6, 2026
Comment thread packages/shared/src/themeMapping.ts Outdated
Comment thread apps/web/src/hooks/useTheme.ts
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented May 6, 2026

Approvability

Verdict: Needs human review

2 blocking correctness issues found. The PR title explicitly indicates 'DO NOT MERGE'. Additionally, this introduces a significant new feature (VSCode/Cursor theme discovery and sync) with complex async state management, and there are unresolved review comments identifying potential race conditions and error handling issues.

You can customize Macroscope's approvability policy. Learn more.

- Reset stored theme preference when the requested VS Code theme cannot be loaded
- Reuse the resolved destructive color for both destructive and destructive-foreground mapping
Comment thread apps/web/src/hooks/useTheme.ts
- Add preference equality guard in theme hook
- Prevent outdated async theme loads from overriding newer selections
Comment thread apps/web/src/hooks/useTheme.ts
Comment on lines +315 to +320
localStorage.setItem(
BOOTSTRAP_THEME_CACHE_KEY,
JSON.stringify({ id: theme.id, kind: theme.kind, appVariables: theme.appVariables }),
);
recomputeSnapshot({ preference, resolvedColorTheme: theme, status: "ready", message: null });
applyResolvedTheme(theme, suppressTransitions);
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.

🟡 Medium hooks/useTheme.ts:315

If localStorage.setItem on line 315 throws (e.g., QuotaExceededError or SecurityError in private browsing), the exception propagates unhandled. This prevents recomputeSnapshot and applyResolvedTheme on lines 319-320 from executing, leaving the state stuck at status: "loading" while the successfully loaded theme is never applied.

-    localStorage.setItem(
-      BOOTSTRAP_THEME_CACHE_KEY,
-      JSON.stringify({ id: theme.id, kind: theme.kind, appVariables: theme.appVariables }),
-    );
-    recomputeSnapshot({ preference, resolvedColorTheme: theme, status: "ready", message: null });
-    applyResolvedTheme(theme, suppressTransitions);
+    try {
+      localStorage.setItem(
+        BOOTSTRAP_THEME_CACHE_KEY,
+        JSON.stringify({ id: theme.id, kind: theme.kind, appVariables: theme.appVariables }),
+      );
+    } catch {
+      // Cache failure should not block theme application
+    }
+    recomputeSnapshot({ preference, resolvedColorTheme: theme, status: "ready", message: null });
+    applyResolvedTheme(theme, suppressTransitions);
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file apps/web/src/hooks/useTheme.ts around lines 315-320:

If `localStorage.setItem` on line 315 throws (e.g., `QuotaExceededError` or `SecurityError` in private browsing), the exception propagates unhandled. This prevents `recomputeSnapshot` and `applyResolvedTheme` on lines 319-320 from executing, leaving the state stuck at `status: "loading"` while the successfully loaded `theme` is never applied.

Evidence trail:
apps/web/src/hooks/useTheme.ts lines 275-322 (REVIEWED_COMMIT): `loadPreference` function. Line 290 sets status to 'loading'. try/catch on lines 291-301 only wraps `bridge.loadColorTheme`. Line 315-318 `localStorage.setItem(BOOTSTRAP_THEME_CACHE_KEY, ...)` is outside try/catch. Lines 319-320 set 'ready' status and apply theme. Callers at lines 392, 409, 421 all use `void loadPreference(...)` (fire-and-forget).

@bmdavis419 bmdavis419 changed the title VSCode theme support in T3 Code DO NOT MERGE VSCode theme support in T3 Code May 6, 2026
Comment on lines +345 to 357
function loadThemePreference(preference: ThemePreference, suppressTransitions = true) {
const key = themePreferenceKey(preference);
const existing = preferenceLoadPromises.get(key);
if (existing) return existing;

const promise = loadPreference(preference, suppressTransitions).finally(() => {
if (preferenceLoadPromises.get(key) === promise) {
preferenceLoadPromises.delete(key);
}
});
preferenceLoadPromises.set(key, promise);
return promise;
}
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.

🟡 Medium hooks/useTheme.ts:345

When a user rapidly switches themes A→B→A, the third call returns the cached promise from the first call without updating state.preference to A. Meanwhile the B call already set state.preference = B. When the original A promise completes, isSamePreference(state.preference, preference) compares B to A, returns false, and bails. Result: the user's final selection A is ignored and theme B remains applied.

 function loadThemePreference(preference: ThemePreference, suppressTransitions = true) {
   const key = themePreferenceKey(preference);
   const existing = preferenceLoadPromises.get(key);
-  if (existing) return existing;
+  if (existing) {
+    state.preference = preference;
+    return existing;
+  }
 
   const promise = loadPreference(preference, suppressTransitions).finally(() => {
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file apps/web/src/hooks/useTheme.ts around lines 345-357:

When a user rapidly switches themes A→B→A, the third call returns the cached promise from the first call without updating `state.preference` to A. Meanwhile the B call already set `state.preference = B`. When the original A promise completes, `isSamePreference(state.preference, preference)` compares B to A, returns false, and bails. Result: the user's final selection A is ignored and theme B remains applied.

Evidence trail:
apps/web/src/hooks/useTheme.ts lines 346-358 (loadThemePreference with preferenceLoadPromises cache), lines 292-343 (loadPreference with recomputeSnapshot and isSamePreference staleness check at lines 308, 317), line 349 (early return of cached promise without calling loadPreference).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant