From beaa6f1f044106bd2f8b8733fb1cee9a7b7c73ab Mon Sep 17 00:00:00 2001 From: Bill Date: Fri, 16 Oct 2026 20:29:53 +0800 Subject: [PATCH] =?UTF-8?q?refactor(theme):=20SFTP/=E7=9B=91=E6=8E=A7/?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE/=E9=AB=98=E4=BA=AE/=E9=94=81=E5=B1=8F?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E9=A2=9C=E8=89=B2=E8=AF=AD=E4=B9=89=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E5=8C=96=EF=BC=9BMonitorPanel=20=E5=9B=BE=E8=A1=A8?= =?UTF-8?q?=E8=89=B2=E9=9A=8F=E4=B8=BB=E9=A2=98=E6=98=8E=E6=9A=97=E6=B4=BE?= =?UTF-8?q?=E7=94=9F=EF=BC=88canvas=20=E9=9C=80=E5=AE=9E=E8=89=B2=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/src/lock/lock.css | 4 +-- src/renderer/src/monitor/MonitorPanel.tsx | 34 +++++++++++++-------- src/renderer/src/monitor/monitor.css | 30 +++++++++---------- src/renderer/src/settings/highlight.css | 12 ++++---- src/renderer/src/settings/settings.css | 20 ++++++------- src/renderer/src/sftp/sftp.css | 36 +++++++++++------------ 6 files changed, 72 insertions(+), 64 deletions(-) diff --git a/src/renderer/src/lock/lock.css b/src/renderer/src/lock/lock.css index 46157c9..eea9562 100644 --- a/src/renderer/src/lock/lock.css +++ b/src/renderer/src/lock/lock.css @@ -37,7 +37,7 @@ border: 1px solid var(--chrome-border, #2d2d2d); border-radius: 10px; background: var(--chrome-bg, #181818); - box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45); + box-shadow: 0 18px 48px var(--ot-shadow, rgba(0, 0, 0, 0.45)); text-align: center; } @@ -70,7 +70,7 @@ min-height: 18px; font-size: 12px; line-height: 18px; - color: #f85149; + color: var(--ot-danger-fg, #f85149); } .lock-screen-hint { diff --git a/src/renderer/src/monitor/MonitorPanel.tsx b/src/renderer/src/monitor/MonitorPanel.tsx index dbc7c9e..5aaeaaa 100644 --- a/src/renderer/src/monitor/MonitorPanel.tsx +++ b/src/renderer/src/monitor/MonitorPanel.tsx @@ -1,7 +1,8 @@ import { useEffect, useRef, useState } from 'react' import type { SysinfoMeta, SysinfoSample } from '@shared/sysinfo' import { DEFAULT_LANGUAGE, tFor, type Language } from '@shared/i18n' -import { useSettingsStore } from '@renderer/settings/store' +import { useResolvedTheme, useSettingsStore } from '@renderer/settings/store' +import { isLightTheme, semanticVars } from '@renderer/theme/semantic' import { useWorkspaceModeStore } from '../workspace/workspaceModeStore' import './monitor.css' @@ -105,11 +106,13 @@ function HistoryChart({ data, lineColor, fillColor, height, maxY }: HistoryChart ) } -/** Red/green/yellow threshold bar color for CPU usage. */ -function cpuColor(usage: number): string { - if (usage > 80) return '#f85149' - if (usage > 60) return '#e3b341' - return '#3fb950' +/** Red/green/yellow threshold bar color for CPU usage. Takes the semantic + * var map so light themes get the darkened (WCAG-compliant) variants โ€” + * canvas fills need actual color strings, CSS vars don't resolve there. */ +function cpuColor(usage: number, vars: Record): string { + if (usage > 80) return vars.dangerFg + if (usage > 60) return vars.warningFg + return vars.successFg } /** Format a size in MB: show GB (1 decimal) once over 1024 MB. */ @@ -156,6 +159,11 @@ export function MonitorPanel({ sessionId }: MonitorPanelProps): React.JSX.Elemen /** Switching workspace mode only hides the dockview (panels stay mounted), so * polling has to stop explicitly while the SSH workspace is not visible. */ const workspaceMode = useWorkspaceModeStore((s) => s.mode) + const theme = useResolvedTheme() + const vars = semanticVars(theme.colors, isLightTheme(theme.colors.background)) + // #rrggbb + alpha โ†’ 'rgba(r, g, b, a)' โ€” canvas fill needs a solid color. + const withAlpha = (hex: string, a: number): string => + `rgba(${[1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16)).join(', ')}, ${a})` useEffect(() => { if (workspaceMode !== 'ssh') return @@ -226,15 +234,15 @@ export function MonitorPanel({ sessionId }: MonitorPanelProps): React.JSX.Elemen
CPU - + {cpu.usage.toFixed(0)}% ยท {tFor(language, 'ssh.monitor.cores', { n: cpu.cores })}
- +
{tFor(language, 'ssh.monitor.loadavg', { value: cpu.loadavg.map((v) => v.toFixed(1)).join(' / ') })}
- +
@@ -246,7 +254,7 @@ export function MonitorPanel({ sessionId }: MonitorPanelProps): React.JSX.Elemen
- +
{memPct.toFixed(0)}%
@@ -266,7 +274,7 @@ export function MonitorPanel({ sessionId }: MonitorPanelProps): React.JSX.Elemen {d.mount}
- +
{formatSize(d.usedMb)} / {formatSize(d.totalMb)} @@ -295,8 +303,8 @@ export function MonitorPanel({ sessionId }: MonitorPanelProps): React.JSX.Elemen
- - + +
diff --git a/src/renderer/src/monitor/monitor.css b/src/renderer/src/monitor/monitor.css index 3c5065a..21329e3 100644 --- a/src/renderer/src/monitor/monitor.css +++ b/src/renderer/src/monitor/monitor.css @@ -19,10 +19,10 @@ } .mm-error { - border: 1px solid #f85149; + border: 1px solid var(--ot-danger, #f85149); border-radius: 6px; - background: rgba(248, 81, 73, 0.12); - color: #f85149; + background: color-mix(in srgb, var(--ot-danger, #f85149) 12%, transparent); + color: var(--ot-danger-fg, #f85149); padding: 5px 8px; font-size: 12px; } @@ -49,7 +49,7 @@ .mm-os { font-size: 11px; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -78,7 +78,7 @@ .mm-label { font-size: 11px; font-weight: 500; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); text-transform: uppercase; letter-spacing: 0.04em; user-select: none; @@ -86,19 +86,19 @@ .mm-value { font-size: 13px; - color: #3fb950; + color: var(--ot-success-fg, #3fb950); font-variant-numeric: tabular-nums; line-height: 1.2; } .mm-value-sub { font-size: 11px; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); } .mm-sub { font-size: 11px; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); } .mm-load { @@ -141,7 +141,7 @@ .mm-mem-pct { flex: 0 0 auto; font-size: 11px; - color: #d29922; + color: var(--ot-warning-fg, #d29922); font-variant-numeric: tabular-nums; min-width: 32px; text-align: right; @@ -177,7 +177,7 @@ .mm-disk-size { font-size: 11px; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; @@ -221,7 +221,7 @@ .mm-net-unit { font-size: 11px; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); } .mm-arrow { @@ -231,17 +231,17 @@ } .mm-up { - color: #58a6ff; + color: var(--ot-info-fg, #58a6ff); } .mm-down { - color: #f0a55a; + color: var(--ot-warning-fg, #f0a55a); } /* ---------- footer ---------- */ .mm-footer { font-size: 11px; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); } .mm-uptime { @@ -253,7 +253,7 @@ align-items: center; justify-content: center; min-height: 120px; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); } .mm-dots { diff --git a/src/renderer/src/settings/highlight.css b/src/renderer/src/settings/highlight.css index b26c55a..7a5f368 100644 --- a/src/renderer/src/settings/highlight.css +++ b/src/renderer/src/settings/highlight.css @@ -79,12 +79,12 @@ } .hl-pattern-bad { - color: #f85149; + color: var(--ot-danger-fg, #f85149); } .hl-warn-icon { flex: 0 0 auto; - color: #f85149; + color: var(--ot-danger-fg, #f85149); font-size: 12px; line-height: 1; cursor: help; @@ -289,17 +289,17 @@ .hl-editor-error { font-size: 12px; - color: #f85149; + color: var(--ot-danger-fg, #f85149); } .hl-editor-input-bad { - border-color: #f85149; + border-color: var(--ot-danger, #f85149); } .hl-editor-input-bad:hover, .hl-editor-input-bad:focus { - border-color: #f85149; - box-shadow: 0 0 0 2px rgba(248, 81, 73, 0.2); + border-color: var(--ot-danger, #f85149); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--ot-danger, #f85149) 20%, transparent); } .hl-editor-sub-label { diff --git a/src/renderer/src/settings/settings.css b/src/renderer/src/settings/settings.css index 11bec2e..079a992 100644 --- a/src/renderer/src/settings/settings.css +++ b/src/renderer/src/settings/settings.css @@ -200,12 +200,12 @@ antd's own checked colour loses to our text overrides, so pin it here. */ .settings-radio-group .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled), .settings-language-group .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled) { - color: #fff; + color: var(--tab-accent-fg, #fff); } .settings-radio-group .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover, .settings-language-group .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover { - color: #fff; + color: var(--tab-accent-fg, #fff); } /* Own positive spacing: the shared `.settings-render-hint` uses a negative @@ -299,8 +299,8 @@ } .theme-card-selected { - border-color: #3b8eea; - box-shadow: 0 0 0 1px #3b8eea inset; + border-color: var(--ot-focus-ring, #3b8eea); + box-shadow: 0 0 0 1px var(--ot-focus-ring, #3b8eea) inset; } .theme-card-bg { @@ -333,7 +333,7 @@ line-height: 1; padding: 2px 5px; border-radius: 4px; - background: rgba(59, 142, 234, 0.2); + background: var(--ot-focus-ring, rgba(59, 142, 234, 0.2)); color: color-mix(in srgb, var(--chrome-accent, #3b8eea) 55%, var(--chrome-fg, #cccccc)); } @@ -510,11 +510,11 @@ } .about-status.is-new { - color: #3fd06a; + color: var(--ot-success-fg, #3fd06a); } .about-error { - color: #f85149; + color: var(--ot-danger-fg, #f85149); margin-top: 4px; font-size: 12px; word-break: break-all; @@ -596,11 +596,11 @@ } .settings-lock-feedback.is-ok { - color: #3fb950; + color: var(--ot-success-fg, #3fb950); } .settings-lock-feedback.is-error { - color: #f85149; + color: var(--ot-danger-fg, #f85149); } .settings-lock-note { @@ -627,5 +627,5 @@ margin: -4px 0 10px; padding-left: 2px; font-size: 12px; - color: #d29922; + color: var(--ot-warning-fg, #d29922); } diff --git a/src/renderer/src/sftp/sftp.css b/src/renderer/src/sftp/sftp.css index 914296e..259ad9b 100644 --- a/src/renderer/src/sftp/sftp.css +++ b/src/renderer/src/sftp/sftp.css @@ -24,7 +24,7 @@ .sftp-breadcrumb { padding: 3px 8px; font-size: 12px; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); border-bottom: 1px solid var(--chrome-border); overflow-x: auto; white-space: nowrap; @@ -152,17 +152,17 @@ } .sftp-row-selected { - background: rgba(59, 142, 234, 0.18); + background: var(--ot-focus-ring, rgba(59, 142, 234, 0.18)); } .sftp-icon { display: inline-flex; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); font-size: calc(14px * var(--sftp-scale, 1)); } .sftp-icon-dir { - color: #e3b341; + color: var(--ot-warning-fg, #e3b341); } .sftp-name { @@ -175,7 +175,7 @@ .sftp-mode { text-align: center; - color: #9a9a9a; + color: var(--ot-text-muted, #9a9a9a); font-family: Consolas, 'Courier New', monospace; font-size: var(--sftp-fs-meta, 12px); white-space: nowrap; @@ -184,7 +184,7 @@ .sftp-owner { text-align: right; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); font-size: var(--sftp-fs-meta, 12px); font-variant-numeric: tabular-nums; white-space: nowrap; @@ -192,7 +192,7 @@ .sftp-size { text-align: right; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); font-size: var(--sftp-fs-meta, 12px); font-variant-numeric: tabular-nums; white-space: nowrap; @@ -200,7 +200,7 @@ .sftp-time { text-align: right; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); font-size: var(--sftp-fs-meta, 12px); font-variant-numeric: tabular-nums; white-space: nowrap; @@ -210,12 +210,12 @@ .sftp-error { padding: 12px; text-align: center; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); font-size: 12px; } .sftp-error { - color: #f85149; + color: var(--ot-danger-fg, #f85149); } /* ---- permission / owner dialog ---- */ @@ -248,7 +248,7 @@ } .sftp-perm-octal { - color: #3fb950; + color: var(--ot-success-fg, #3fb950); } .sftp-perm-grid { @@ -264,7 +264,7 @@ align-items: center; column-gap: 8px; font-size: 12px; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); } .sftp-perm-grid-head span { @@ -305,7 +305,7 @@ .sftp-perm-label { font-size: 12px; - color: #8a8a8a; + color: var(--ot-text-muted, #8a8a8a); } .sftp-perm-own-field .ant-input { @@ -314,7 +314,7 @@ .sftp-perm-hint { font-size: 11px; - color: #6a6a6a; + color: var(--ot-text-muted, #6a6a6a); } /* ---- global transfer overlay ---- */ @@ -339,7 +339,7 @@ border: 1px solid var(--chrome-border); border-radius: 6px; padding: 8px 10px; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45); + box-shadow: 0 4px 16px var(--ot-shadow, rgba(0, 0, 0, 0.45)); } .sftp-transfer-head { @@ -357,11 +357,11 @@ } .sftp-transfer-done .sftp-transfer-title { - color: #3fb950; + color: var(--ot-success-fg, #3fb950); } .sftp-transfer-error .sftp-transfer-title { - color: #f85149; + color: var(--ot-danger-fg, #f85149); } .sftp-transfer-cancelled .sftp-transfer-title { @@ -423,7 +423,7 @@ .sftp-transfer-err { font-size: 11px; - color: #f85149; + color: var(--ot-danger-fg, #f85149); margin-top: 3px; word-break: break-all; }