дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 11:15:40 +02:00
feat(themes): Built-in Solarized and One light/dark themes (#85)
Adds Solarized Light, Solarized Dark, One Light and One Dark as built-in themes across the workbench, editor, terminal and Mermaid, keeping the original palettes (MIT notices in THIRD_PARTY_LICENSES.md, mapping in docs/themes.md). - Native window colours are read from tokens.css at build time (`theme_frame.rs`) instead of a second colour table. - Startup restores the built-in palette before first paint. - Editor schemes, the terminal and Mermaid refresh on switches between themes of the same kind. - The plugin packages of the same themes are removed. - A test requires every built-in palette theme to define each token (only listed ones may inherit from the base theme), so new tokens can't silently miss them. Co-authored-by: Claude <[email protected]> Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Цей коміт міститься в:
1 джерело
50308a956d
коміт
3b608355a3
48 files changed
+1267
-1351
No files matched your search
@@ -4,9 +4,10 @@ import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
import { create } from "zustand";
|
||||
import { call, commands, isTauri } from "@/platform/ipc";
|
||||
import { useProject } from "@/platform/project";
|
||||
import { BUILTIN_THEMES, isBuiltinTheme, themeKind, type BuiltinThemeId } from "@/platform/themes";
|
||||
import { resolveTokenColor, toHex } from "@/platform/cssColor";
|
||||
|
||||
export type ThemeSetting = "dark" | "light" | "system" | "dark-hc";
|
||||
export type ThemeSetting = BuiltinThemeId | "system";
|
||||
/** PyCharm's brand blue: the accent both Islands themes ship with. */
|
||||
export const DEFAULT_ACCENT = "#3871e1";
|
||||
/** Accent presets (Settings › Appearance, Welcome › Customize); the first is the Islands default. */
|
||||
@@ -44,8 +45,8 @@ interface AppearanceLike {
|
||||
* Concrete theme id: the chosen theme, or with "Sync with OS" (legacy
|
||||
* `theme = "system"`) the preferred light / dark theme for the OS mode.
|
||||
*/
|
||||
export function resolveThemeId(a: AppearanceLike | undefined, systemLight: boolean): "dark" | "light" | "dark-hc" {
|
||||
const concrete = (v: string | undefined, d: "dark" | "light") => (v === "dark" || v === "light" || v === "dark-hc" ? v : d);
|
||||
export function resolveThemeId(a: AppearanceLike | undefined, systemLight: boolean): BuiltinThemeId {
|
||||
const concrete = (v: string | undefined, d: "dark" | "light") => (isBuiltinTheme(v) ? v : d);
|
||||
if (a?.syncWithOs || a?.theme === "system")
|
||||
return systemLight ? concrete(a?.preferredLightTheme, "light") : concrete(a?.preferredDarkTheme, "dark");
|
||||
return concrete(a?.theme, "light");
|
||||
@@ -53,7 +54,7 @@ export function resolveThemeId(a: AppearanceLike | undefined, systemLight: boole
|
||||
|
||||
/** `dark-hc` resolves to `dark` plus `data-contrast="high"`. */
|
||||
export function resolveTheme(setting: string | undefined, systemLight: boolean): "dark" | "light" {
|
||||
return resolveThemeId({ theme: setting }, systemLight) === "light" ? "light" : "dark";
|
||||
return themeKind(resolveThemeId({ theme: setting }, systemLight));
|
||||
}
|
||||
|
||||
const ACCENT_RE = /^#[0-9a-f]{3,8}$/i;
|
||||
@@ -82,17 +83,21 @@ export function useApplyTheme() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets `data-theme` / `data-contrast` for a built-in theme id. While a plugin
|
||||
* Sets `data-theme` / `data-contrast` / `data-color-theme` (the palette themes
|
||||
* over a light / dark base, tokens.css) for a built-in theme id. While a plugin
|
||||
* theme is active (`data-plugin-theme-kind`), its light / dark base wins.
|
||||
*/
|
||||
export function applyThemeAttributes(id: "dark" | "light" | "dark-hc", root: HTMLElement = document.documentElement) {
|
||||
export function applyThemeAttributes(id: BuiltinThemeId, root: HTMLElement = document.documentElement) {
|
||||
const pluginKind = root.dataset.pluginThemeKind;
|
||||
if (pluginKind === "light" || pluginKind === "dark") {
|
||||
delete root.dataset.colorTheme;
|
||||
root.dataset.theme = pluginKind;
|
||||
delete root.dataset.contrast;
|
||||
return;
|
||||
}
|
||||
root.dataset.theme = id === "light" ? "light" : "dark";
|
||||
if (id === "light" || id === "dark" || id === "dark-hc") delete root.dataset.colorTheme;
|
||||
else root.dataset.colorTheme = id;
|
||||
root.dataset.theme = themeKind(id);
|
||||
if (id === "dark-hc") root.dataset.contrast = "high";
|
||||
else delete root.dataset.contrast;
|
||||
}
|
||||
@@ -135,6 +140,7 @@ export function rememberStartupTheme(root: HTMLElement = document.documentElemen
|
||||
JSON.stringify({
|
||||
theme: root.dataset.theme,
|
||||
contrast: root.dataset.contrast,
|
||||
colorTheme: root.dataset.colorTheme,
|
||||
frame: hex("--bg-frame"),
|
||||
fg: hex("--fg-muted"),
|
||||
accent: hex("--accent"),
|
||||
@@ -162,18 +168,14 @@ export function syncWindowBackground() {
|
||||
}
|
||||
|
||||
export function currentTheme(): "dark" | "light" {
|
||||
return currentThemeId() === "light" ? "light" : "dark";
|
||||
return themeKind(currentThemeId());
|
||||
}
|
||||
|
||||
/** Themes offered by quick switch menus, in IDEA's order. */
|
||||
export const THEME_CHOICES: ReadonlyArray<{ id: "light" | "dark" | "dark-hc"; label: string }> = [
|
||||
{ id: "light", label: "Islands Light" },
|
||||
{ id: "dark", label: "Islands Dark" },
|
||||
{ id: "dark-hc", label: "High Contrast" },
|
||||
];
|
||||
export const THEME_CHOICES = BUILTIN_THEMES;
|
||||
|
||||
/** The concrete theme in effect (`dark-hc` kept distinct). */
|
||||
export function currentThemeId(): "dark" | "light" | "dark-hc" {
|
||||
export function currentThemeId(): BuiltinThemeId {
|
||||
const override = useThemeOverride.getState().theme;
|
||||
return override
|
||||
? resolveThemeId({ theme: override }, prefersLight())
|
||||
|
||||
Reference in new issue
Заблокувати користувача