From 4e223b623757131b9371571ca43f14c227029665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=9C=E5=AD=90?= Date: Fri, 15 May 2026 22:14:20 +0800 Subject: [PATCH] feat: add all Draw.io themes to settings panel (#835) * feat: add all Draw.io themes to settings panel Add all available Draw.io themes (kennedy, atlas, dark, min, sketch, simple) to the settings panel dropdown. Previously only min and sketch were available as a toggle button. Changes: - Replace the Draw.io style toggle button with a dropdown selector - Expand theme type from "min" | "sketch" to include all 6 themes - Update localStorage validation to accept all themes - Update handler from toggle to direct theme selection Closes #499 * fix: localize theme labels, tighten DrawioTheme typing, sync dark param - Move DRAWIO_THEMES + DrawioTheme to lib/drawio-themes.ts; reuse in page.tsx, chat-panel.tsx and settings-dialog.tsx instead of `string` - Localize theme dropdown labels (Dark/Minimal/Sketch/Simple) in en/zh/ja/zh-Hant; keep proper-noun themes (Kennedy/Atlas) as-is - Drop trailing colon from drawioStyleDescription and remove dead switchTo/minimal/sketch keys in all 4 dictionaries - Auto-sync drawio dark URL param when ui="dark" is selected - Add aria-label to drawio-style SelectTrigger * fix: use kennedy as default theme and label it "Default" --------- Co-authored-by: dayuan.jiang --- app/[lang]/page.tsx | 17 +++++----- components/chat-panel.tsx | 9 ++--- components/settings-dialog.tsx | 54 ++++++++++++++++++++---------- lib/drawio-themes.ts | 17 ++++++++++ lib/i18n/dictionaries/en.json | 10 +++--- lib/i18n/dictionaries/ja.json | 10 +++--- lib/i18n/dictionaries/zh-Hant.json | 10 +++--- lib/i18n/dictionaries/zh.json | 10 +++--- 8 files changed, 91 insertions(+), 46 deletions(-) create mode 100644 lib/drawio-themes.ts diff --git a/app/[lang]/page.tsx b/app/[lang]/page.tsx index e44bd6c..9d6acc8 100644 --- a/app/[lang]/page.tsx +++ b/app/[lang]/page.tsx @@ -10,6 +10,7 @@ import { ResizablePanelGroup, } from "@/components/ui/resizable" import { useDiagram } from "@/contexts/diagram-context" +import { type DrawioTheme, isDrawioTheme } from "@/lib/drawio-themes" import { i18n, type Locale } from "@/lib/i18n/config" import { isIndexedDBUsable } from "@/lib/session-storage" @@ -27,7 +28,7 @@ export default function Home() { const currentLang = (pathname.split("/")[1] || i18n.defaultLocale) as Locale const [isMobile, setIsMobile] = useState(false) const [isChatVisible, setIsChatVisible] = useState(true) - const [drawioUi, setDrawioUi] = useState<"min" | "sketch">("min") + const [drawioUi, setDrawioUi] = useState("kennedy") const [darkMode, setDarkMode] = useState(false) const [isLoaded, setIsLoaded] = useState(false) const [isDrawioReady, setIsDrawioReady] = useState(false) @@ -56,7 +57,7 @@ export default function Home() { } const savedUi = localStorage.getItem("drawio-theme") - if (savedUi === "min" || savedUi === "sketch") { + if (isDrawioTheme(savedUi)) { setDrawioUi(savedUi) } @@ -113,10 +114,9 @@ export default function Home() { resetDrawioReady() } - const handleDrawioUiChange = () => { - const newUi = drawioUi === "min" ? "sketch" : "min" - localStorage.setItem("drawio-theme", newUi) - setDrawioUi(newUi) + const handleDrawioUiChange = (theme: DrawioTheme) => { + localStorage.setItem("drawio-theme", theme) + setDrawioUi(theme) setIsDrawioReady(false) resetDrawioReady() } @@ -216,7 +216,8 @@ export default function Home() { saveAndExit: false, noSaveBtn: true, noExitBtn: true, - dark: darkMode, + dark: + darkMode || drawioUi === "dark", lang: currentLang, // Enable offline mode in Electron to disable external service calls ...(isElectron && { @@ -264,7 +265,7 @@ export default function Home() { isVisible={isChatVisible} onToggleVisibility={toggleChatPanel} drawioUi={drawioUi} - onToggleDrawioUi={handleDrawioUiChange} + onDrawioUiChange={handleDrawioUiChange} darkMode={darkMode} onToggleDarkMode={handleDarkModeChange} isMobile={isMobile} diff --git a/components/chat-panel.tsx b/components/chat-panel.tsx index bd763e1..8d533ce 100644 --- a/components/chat-panel.tsx +++ b/components/chat-panel.tsx @@ -32,6 +32,7 @@ import { useSessionManager } from "@/hooks/use-session-manager" import { useValidateDiagram } from "@/hooks/use-validate-diagram" import { getApiEndpoint } from "@/lib/base-path" import { findCachedResponse } from "@/lib/cached-responses" +import type { DrawioTheme } from "@/lib/drawio-themes" import { formatMessage } from "@/lib/i18n/utils" import { isPdfFile, isTextFile } from "@/lib/pdf-utils" import { sanitizeMessages } from "@/lib/session-storage" @@ -68,8 +69,8 @@ interface ChatMessage { interface ChatPanelProps { isVisible: boolean onToggleVisibility: () => void - drawioUi: "min" | "sketch" - onToggleDrawioUi: () => void + drawioUi: DrawioTheme + onDrawioUiChange: (theme: DrawioTheme) => void darkMode: boolean onToggleDarkMode: () => void isMobile?: boolean @@ -110,7 +111,7 @@ export default function ChatPanel({ isVisible, onToggleVisibility, drawioUi, - onToggleDrawioUi, + onDrawioUiChange, darkMode, onToggleDarkMode, isMobile = false, @@ -1442,7 +1443,7 @@ export default function ChatPanel({ open={showSettingsDialog} onOpenChange={setShowSettingsDialog} drawioUi={drawioUi} - onToggleDrawioUi={onToggleDrawioUi} + onDrawioUiChange={onDrawioUiChange} darkMode={darkMode} onToggleDarkMode={onToggleDarkMode} minimalStyle={minimalStyle} diff --git a/components/settings-dialog.tsx b/components/settings-dialog.tsx index 75064b1..d3dccc4 100644 --- a/components/settings-dialog.tsx +++ b/components/settings-dialog.tsx @@ -25,6 +25,7 @@ import { Switch } from "@/components/ui/switch" import { Textarea } from "@/components/ui/textarea" import { useDictionary } from "@/hooks/use-dictionary" import { getApiEndpoint } from "@/lib/base-path" +import type { DrawioTheme } from "@/lib/drawio-themes" import { i18n, type Locale } from "@/lib/i18n/config" import { STORAGE_KEYS } from "@/lib/storage" @@ -63,8 +64,8 @@ const LANGUAGE_LABELS: Record = { interface SettingsDialogProps { open: boolean onOpenChange: (open: boolean) => void - drawioUi: "min" | "sketch" - onToggleDrawioUi: () => void + drawioUi: DrawioTheme + onDrawioUiChange: (theme: DrawioTheme) => void darkMode: boolean onToggleDarkMode: () => void minimalStyle?: boolean @@ -90,7 +91,7 @@ function SettingsContent({ open, onOpenChange, drawioUi, - onToggleDrawioUi, + onDrawioUiChange, darkMode, onToggleDarkMode, minimalStyle = false, @@ -432,23 +433,40 @@ function SettingsContent({ {/* Draw.io Style */} - + + + + + + {dict.settings.themeDefault} + + Atlas + + {dict.settings.themeDark} + + + {dict.settings.themeMinimal} + + + {dict.settings.themeSketch} + + + {dict.settings.themeSimple} + + + {/* Diagram Style */} diff --git a/lib/drawio-themes.ts b/lib/drawio-themes.ts new file mode 100644 index 0000000..7eac1a6 --- /dev/null +++ b/lib/drawio-themes.ts @@ -0,0 +1,17 @@ +export const DRAWIO_THEMES = [ + "kennedy", + "atlas", + "dark", + "min", + "sketch", + "simple", +] as const + +export type DrawioTheme = (typeof DRAWIO_THEMES)[number] + +export function isDrawioTheme(value: unknown): value is DrawioTheme { + return ( + typeof value === "string" && + (DRAWIO_THEMES as readonly string[]).includes(value) + ) +} diff --git a/lib/i18n/dictionaries/en.json b/lib/i18n/dictionaries/en.json index 2e00502..607981a 100644 --- a/lib/i18n/dictionaries/en.json +++ b/lib/i18n/dictionaries/en.json @@ -102,10 +102,12 @@ "theme": "Theme", "themeDescription": "Dark/Light mode for interface and DrawIO canvas.", "drawioStyle": "DrawIO Style", - "drawioStyleDescription": "Canvas style:", - "switchTo": "Switch to", - "minimal": "Minimal", - "sketch": "Sketch", + "drawioStyleDescription": "Canvas style", + "themeDefault": "Default", + "themeDark": "Dark", + "themeMinimal": "Minimal", + "themeSketch": "Sketch", + "themeSimple": "Simple", "diagramStyle": "Diagram Style", "diagramStyleDescription": "Toggle between minimal and styled diagram output.", "sendShortcut": "Send Shortcut", diff --git a/lib/i18n/dictionaries/ja.json b/lib/i18n/dictionaries/ja.json index 189da7f..7992b84 100644 --- a/lib/i18n/dictionaries/ja.json +++ b/lib/i18n/dictionaries/ja.json @@ -102,10 +102,12 @@ "theme": "テーマ", "themeDescription": "インターフェースと DrawIO キャンバスのダーク/ライトモード。", "drawioStyle": "DrawIO スタイル", - "drawioStyleDescription": "キャンバススタイル:", - "switchTo": "切り替え", - "minimal": "ミニマル", - "sketch": "スケッチ", + "drawioStyleDescription": "キャンバススタイル", + "themeDefault": "デフォルト", + "themeDark": "ダーク", + "themeMinimal": "ミニマル", + "themeSketch": "スケッチ", + "themeSimple": "シンプル", "diagramStyle": "ダイアグラムスタイル", "diagramStyleDescription": "ミニマルとスタイル付きの出力を切り替えます。", "sendShortcut": "送信ショートカット", diff --git a/lib/i18n/dictionaries/zh-Hant.json b/lib/i18n/dictionaries/zh-Hant.json index 396459d..8c3d9c3 100644 --- a/lib/i18n/dictionaries/zh-Hant.json +++ b/lib/i18n/dictionaries/zh-Hant.json @@ -102,10 +102,12 @@ "theme": "主題", "themeDescription": "介面和 DrawIO 畫布的深色/淺色模式。", "drawioStyle": "DrawIO 樣式", - "drawioStyleDescription": "畫布樣式:", - "switchTo": "切換到", - "minimal": "簡約", - "sketch": "草圖", + "drawioStyleDescription": "畫布樣式", + "themeDefault": "預設", + "themeDark": "深色", + "themeMinimal": "簡約", + "themeSketch": "草圖", + "themeSimple": "簡單", "diagramStyle": "圖表樣式", "diagramStyleDescription": "切換簡約與精緻圖表輸出模式。", "sendShortcut": "傳送快捷鍵", diff --git a/lib/i18n/dictionaries/zh.json b/lib/i18n/dictionaries/zh.json index 2f3c266..0ee9f81 100644 --- a/lib/i18n/dictionaries/zh.json +++ b/lib/i18n/dictionaries/zh.json @@ -102,10 +102,12 @@ "theme": "主题", "themeDescription": "界面和 DrawIO 画布的深色/浅色模式。", "drawioStyle": "DrawIO 样式", - "drawioStyleDescription": "画布样式:", - "switchTo": "切换到", - "minimal": "简约", - "sketch": "草图", + "drawioStyleDescription": "画布样式", + "themeDefault": "默认", + "themeDark": "深色", + "themeMinimal": "简约", + "themeSketch": "草图", + "themeSimple": "简单", "diagramStyle": "图表样式", "diagramStyleDescription": "切换简约与精致图表输出模式。", "sendShortcut": "发送快捷键",