fix(theme): adapt custom styles to dark mode via design tokens

- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
fix(theme): adapt custom styles to dark mode via design tokens
- Add useEffect in App.tsx to set data-theme attribute on documentElement
(also toggles html.dark class) so CSS rules can use [data-theme='dark']
selectors and Ant Design's darkAlgorithm can fully cascade.
- Replace hardcoded rgba(0,0,0,*) colors in Dashboard.tsx with Ant Design
tokens via theme.useToken():
- ProcessUsageWall: colorTextSecondary (was rgba 0.45),
colorTextDisabled (was rgba 0.35), colorBorderSecondary (was rgba 0.06),
colorFillQuaternary (was rgba 0.02 header bg), HIGH/MED/LOW usage
colors now use colorError / colorWarning / colorSuccess tokens.
- Statistic valueStyles and Progress trailColor also token-based.
- Login.tsx: replace isDark ternary '#141414' / '#f5f5f5' with
token.colorBgLayout (single source of truth, auto-adapts).
- Logs.tsx: replace '#888' timestamp color with token.colorTextTertiary.
- Sidebar.tsx: replace hardcoded rgba(5,5,5,0.06) logout divider border with
var(--ant-color-border-secondary, ...) CSS variable fallback chain.
- responsive.css: add dark variants for .app-bottom-nav box-shadow and
.app-header-bar border so sticky surfaces stay readable in dark mode.
- Delete dead hooks/useTheme.ts (never imported; the data-theme attribute
is now set centrally by App.tsx).
Tested: build PASS, lint 0 errors (42 pre-existing warnings unchanged),
unit tests 16/16 PASS.
This commit is contained in:
Z User committed 2026-09-15 11:45:01 +00:00
1 parent a3ee711f5d
commit b53b996dd7
7 files changed
+67 -56

No files matched your search

+11 -1
View File
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect } from 'react';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { ConfigProvider, App as AntApp, theme } from 'antd';
import enUS from 'antd/locale/en_US';
@@ -40,6 +40,16 @@ import SharePage from './pages/Share';
const ThemedApp: React.FC = () => {
const isDark = useThemeStore((s) => s.isDark);
const { locale } = useI18n();
// Propagate isDark to <html data-theme="…"> so plain CSS rules
// (e.g. `[data-theme='dark'] …` in responsive.css) and any other
// data-theme-aware styles can adapt alongside Ant Design's darkAlgorithm.
useEffect(() => {
if (typeof document === 'undefined') return;
document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
document.documentElement.classList.toggle('dark', isDark);
}, [isDark]);
return (
<ConfigProvider
locale={(() => {
+4 -1
View File
@@ -51,6 +51,9 @@ export const SidebarMenu: React.FC<{ onNavigate?: () => void; style?: React.CSSP
}) => {
const { items, selectedKeys, onMenuClick, onLogout, t } = useSidebarMenuItems(onNavigate);
// Sidebar is rendered with theme="light" on the Sider below; the logout
// divider is therefore a light-mode border regardless of the global theme,
// so a static light color is correct here.
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%', ...style }}>
<div style={{ height: 64, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, fontWeight: 700, fontSize: 18, flexShrink: 0, padding: '0 12px' }}>
@@ -58,7 +61,7 @@ export const SidebarMenu: React.FC<{ onNavigate?: () => void; style?: React.CSSP
{!collapsed && <span>3M-UI</span>}
</div>
<Menu mode="inline" selectedKeys={selectedKeys} items={items} onClick={onMenuClick} style={{ flex: 1, borderInlineEnd: 'none' }} />
<Menu mode="inline" selectable={false} items={[{ key: 'logout', icon: <LogoutOutlined />, label: t('nav.logout'), onClick: onLogout }]} style={{ borderInlineEnd: 'none', borderTop: '1px solid rgba(5,5,5,0.06)' }} />
<Menu mode="inline" selectable={false} items={[{ key: 'logout', icon: <LogoutOutlined />, label: t('nav.logout'), onClick: onLogout }]} style={{ borderInlineEnd: 'none', borderTop: '1px solid var(--ant-color-border-secondary, rgba(0, 0, 0, 0.06))' }} />
</div>
);
};
-19
View File
@@ -1,19 +0,0 @@
import { useState, useEffect } from 'react';
type Theme = 'light' | 'dark';
export function useTheme() {
const [theme, setTheme] = useState<Theme>(() => {
const saved = localStorage.getItem('3m-ui-theme');
return (saved as Theme) || 'light';
});
useEffect(() => {
localStorage.setItem('3m-ui-theme', theme);
document.documentElement.setAttribute('data-theme', theme);
}, [theme]);
const toggle = () => setTheme((prev) => (prev === 'light' ? 'dark' : 'light'));
return { theme, toggle, isDark: theme === 'dark' };
}
+30 -30
View File
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { Card, Row, Col, Statistic, Button, Space, Tag, Progress, Typography, Grid, message } from 'antd';
import { Card, Row, Col, Statistic, Button, Space, Tag, Progress, Typography, Grid, message, theme } from 'antd';
import { PlayCircleOutlined, StopOutlined, RedoOutlined } from '@ant-design/icons';
import { fetchDashboard, startMihomo, stopMihomo, restartMihomo } from '../api/system';
import { isCanceledError } from '../api/client';
@@ -29,25 +29,6 @@ type ProcSample = {
memory_percent?: number;
};
const muted: React.CSSProperties = { fontSize: 12, color: 'rgba(0,0,0,0.45)', lineHeight: 1.4 };
/** Usage level → color. ≥80% high (red), ≥50% medium (orange), else inherit. */
const HIGH = '#cf1322';
const MED = '#d46b08';
const LOW = '#3f8600';
function usageColor(pct: number): string | undefined {
if (pct >= 80) return HIGH;
if (pct >= 50) return MED;
return undefined;
}
/** Bar variant: always resolves, so a healthy bar reads green rather than neutral. */
function usageBarColor(pct: number): string {
if (pct >= 80) return HIGH;
if (pct >= 50) return MED;
return LOW;
}
/**
* Process usage, grouped by **process**: Panel | Core.
*
@@ -71,9 +52,17 @@ const ProcessUsageWall: React.FC<{
memLabel: string;
pidLabel: string;
}> = ({ panel, core, coreRunning, panelLabel, coreLabel, cpuLabel, memLabel, pidLabel }) => {
const { token } = theme.useToken();
const screens = Grid.useBreakpoint();
const stacked = !screens.sm; // xs: groups stacked; sm+: side by side
/** Usage level → color. ≥80% high (red), ≥50% medium (orange), else inherit. */
const usageColor = (pct: number): string | undefined => {
if (pct >= 80) return token.colorError;
if (pct >= 50) return token.colorWarning;
return undefined;
};
const groups = [
{
key: 'panel',
@@ -117,7 +106,7 @@ const ProcessUsageWall: React.FC<{
});
const detailStyle: React.CSSProperties = {
fontSize: 11,
color: 'rgba(0,0,0,0.45)',
color: token.colorTextSecondary,
marginTop: 2,
lineHeight: 1.3,
whiteSpace: 'nowrap',
@@ -126,7 +115,7 @@ const ProcessUsageWall: React.FC<{
};
const labelStyle: React.CSSProperties = {
fontSize: 12,
color: 'rgba(0,0,0,0.45)',
color: token.colorTextSecondary,
marginTop: 4,
lineHeight: 1.4,
whiteSpace: 'nowrap',
@@ -135,10 +124,10 @@ const ProcessUsageWall: React.FC<{
};
const emptyStyle: React.CSSProperties = {
...numStyle(0),
color: 'rgba(0,0,0,0.35)',
color: token.colorTextDisabled,
};
const cellStyle: React.CSSProperties = { textAlign: 'center', padding: '10px 4px', minWidth: 0 };
const border = '1px solid rgba(0,0,0,0.06)';
const border = `1px solid ${token.colorBorderSecondary}`;
return (
<div
@@ -173,12 +162,12 @@ const ProcessUsageWall: React.FC<{
gap: 8,
padding: '6px 10px',
borderBottom: border,
background: 'rgba(0,0,0,0.02)',
background: token.colorFillQuaternary,
}}
>
<span style={{ fontSize: 12, fontWeight: 600 }}>{g.name}</span>
{g.live && g.pid ? (
<span style={{ fontSize: 11, color: 'rgba(0,0,0,0.45)' }}>
<span style={{ fontSize: 11, color: token.colorTextSecondary }}>
{pidLabel} {g.pid}
</span>
) : null}
@@ -214,11 +203,22 @@ const ProcessUsageWall: React.FC<{
const Dashboard: React.FC = () => {
const { t } = useI18n();
const isMobile = useIsMobile();
const { token } = theme.useToken();
const [data, setData] = useState<any>(null);
const [busy, setBusy] = useState(false);
const cardSize = isMobile ? 'small' as const : 'default' as const;
const gutter = isMobile ? ([8, 8] as [number, number]) : ([16, 16] as [number, number]);
// Theme-adaptive muted text style (was a hardcoded rgba(0,0,0,0.45)).
const muted: React.CSSProperties = { fontSize: 12, color: token.colorTextSecondary, lineHeight: 1.4 };
/** Bar variant: always resolves, so a healthy bar reads green rather than neutral. */
const usageBarColor = (pct: number): string => {
if (pct >= 80) return token.colorError;
if (pct >= 50) return token.colorWarning;
return token.colorSuccess;
};
const load = async (signal?: AbortSignal) => {
try {
const d = await fetchDashboard(signal);
@@ -316,8 +316,8 @@ const Dashboard: React.FC = () => {
<Card size={cardSize} title={t('dashboard.listeners')}>
<Row gutter={isMobile ? [8, 8] : 16}>
<Col span={8}><Statistic title={t('dashboard.total')} value={data?.listeners?.total || 0} /></Col>
<Col span={8}><Statistic title={t('dashboard.enabled')} value={data?.listeners?.enabled || 0} valueStyle={{ color: '#3f8600' }} /></Col>
<Col span={8}><Statistic title={t('dashboard.disabled')} value={data?.listeners?.disabled || 0} valueStyle={{ color: '#cf1322' }} /></Col>
<Col span={8}><Statistic title={t('dashboard.enabled')} value={data?.listeners?.enabled || 0} valueStyle={{ color: token.colorSuccess }} /></Col>
<Col span={8}><Statistic title={t('dashboard.disabled')} value={data?.listeners?.disabled || 0} valueStyle={{ color: token.colorError }} /></Col>
</Row>
</Card>
</Col>
@@ -356,7 +356,7 @@ const Dashboard: React.FC = () => {
return (
<div key={m.key}>
<div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 8 }}>
<span style={{ fontSize: 13, color: 'rgba(0,0,0,0.65)' }}>{m.label}</span>
<span style={{ fontSize: 13, color: token.colorText }}>{m.label}</span>
<span style={{ fontSize: 13, fontWeight: 600, color, fontVariantNumeric: 'tabular-nums' }}>
{m.pct}%
</span>
@@ -366,7 +366,7 @@ const Dashboard: React.FC = () => {
showInfo={false}
size="small"
strokeColor={color}
trailColor="rgba(0,0,0,0.06)"
trailColor={token.colorBorderSecondary}
strokeLinecap="butt"
/>
{m.detail ? <div style={{ ...muted, fontSize: 11, marginTop: 2 }}>{m.detail}</div> : null}
+4 -3
View File
@@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from 'react';
import { Card, Form, Input, Button, Typography, message, Space, Dropdown, Steps, Alert } from 'antd';
import { Card, Form, Input, Button, Typography, message, Space, Dropdown, Steps, Alert, theme } from 'antd';
import {
UserOutlined,
LockOutlined,
@@ -25,7 +25,8 @@ const Login: React.FC = () => {
const [form] = Form.useForm();
const totpInputRef = useRef<any>(null);
const { t, locale, setLocale } = useI18n();
const { mode, setMode, isDark } = useThemeStore();
const { mode, setMode } = useThemeStore();
const { token } = theme.useToken();
const from = (location.state as { from?: { pathname?: string } } | null)?.from?.pathname || '/';
useEffect(() => {
@@ -94,7 +95,7 @@ const Login: React.FC = () => {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
background: isDark ? '#141414' : '#f5f5f5',
background: token.colorBgLayout,
padding: '24px 0',
}}
>
+3 -2
View File
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { Card, List, Tag, Button, Space, Empty, Spin, message } from 'antd';
import { Card, List, Tag, Button, Space, Empty, Spin, message, theme } from 'antd';
import { ReloadOutlined, ClearOutlined } from '@ant-design/icons';
import dayjs from 'dayjs';
import client from '../api/client';
@@ -14,6 +14,7 @@ const levelColor: Record<string, string> = { debug: 'default', info: 'blue', war
const Logs: React.FC = () => {
const { t } = useI18n();
const isMobile = useIsMobile();
const { token } = theme.useToken();
const [logs, setLogs] = useState<LogEntry[]>([]);
const [loading, setLoading] = useState(false);
const [autoRefresh, setAutoRefresh] = useState(true);
@@ -39,7 +40,7 @@ const Logs: React.FC = () => {
{loading && logs.length === 0 ? <Spin /> : logs.length === 0 ? <Empty description={t('logs.empty')} /> : (
<List size="small" dataSource={logs} renderItem={(log, i) => (
<List.Item key={i} style={{ fontFamily: 'monospace', fontSize: 13 }}>
<span style={{ color: '#888', marginRight: 8 }}>[{dayjs(log.timestamp).format('YYYY-MM-DD HH:mm:ss')}]</span>
<span style={{ color: token.colorTextTertiary, marginRight: 8 }}>[{dayjs(log.timestamp).format('YYYY-MM-DD HH:mm:ss')}]</span>
<Tag color={levelColor[log.level?.toLowerCase()] || 'default'} style={{ marginRight: 8 }}>{log.level?.toUpperCase()}</Tag>
<span>{log.payload}</span>
</List.Item>
+15
View File
@@ -385,6 +385,21 @@ html.dark .mobile-entity-card,
border-color: rgba(255, 255, 255, 0.12);
}
/* Dark mode: subtle lift for sticky surfaces whose hardcoded light shadow
(rgba(0,0,0,0.04)) is invisible on a dark background. */
html.dark .app-bottom-nav,
[data-theme='dark'] .app-bottom-nav {
box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.35);
}
/* Dark mode: lift the sticky header bar's blur scrim slightly so light text
stays readable over scrolling content. The var() fallback (rgba(0,0,0,0.06))
is too faint on dark surfaces. */
html.dark .app-header-bar,
[data-theme='dark'] .app-header-bar {
border-bottom-color: var(--ant-color-border-secondary, rgba(255, 255, 255, 0.08)) !important;
}
/* —— Mobile bottom navigation —— */
.app-bottom-nav {