aura-web/src/main.tsx

133 lines
3.8 KiB
TypeScript

import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
import ReactDOM from 'react-dom/client';
import { ConfigProvider, App as AntApp, theme as antdTheme } from 'antd';
import zhCN from 'antd/locale/zh_CN';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import './styles.css';
type ThemeMode = 'light' | 'dark';
interface ThemeCtx {
mode: ThemeMode;
toggle: () => void;
setMode: (m: ThemeMode) => void;
}
const ThemeContext = createContext<ThemeCtx>({
mode: 'light',
toggle: () => {},
setMode: () => {}
});
export const useTheme = () => useContext(ThemeContext);
function ThemeProvider({ children }: { children: React.ReactNode }) {
const [mode, setMode] = useState<ThemeMode>(() => {
const saved = localStorage.getItem('app-theme');
if (saved === 'dark' || saved === 'light') return saved;
return 'light';
});
useEffect(() => {
document.documentElement.setAttribute('data-theme', mode);
localStorage.setItem('app-theme', mode);
}, [mode]);
const isDark = mode === 'dark';
const themeConfig = useMemo(
() => ({
algorithm: isDark ? antdTheme.darkAlgorithm : antdTheme.defaultAlgorithm,
token: {
colorPrimary: isDark ? '#e07b3e' : '#c2541f',
colorInfo: isDark ? '#e07b3e' : '#c2541f',
colorBgBase: isDark ? '#1a1816' : '#faf9f5',
colorBgContainer: isDark ? '#221f1c' : '#ffffff',
colorBgElevated: isDark ? '#2b2824' : '#ffffff',
colorBgLayout: isDark ? '#1a1816' : '#faf9f5',
colorBorder: isDark ? '#36322c' : '#ebe7da',
colorBorderSecondary: isDark ? '#2b2824' : '#f0ece0',
colorText: isDark ? '#f3efe6' : '#2a2622',
colorTextSecondary: isDark ? '#b6afa3' : '#6b6660',
colorTextTertiary: isDark ? '#7e7869' : '#a09a8e',
colorSuccess: isDark ? '#7fb87d' : '#4f8a4d',
colorWarning: isDark ? '#d49a4a' : '#b8782a',
colorError: isDark ? '#e07060' : '#c0392b',
borderRadius: 10,
borderRadiusLG: 12,
borderRadiusSM: 6,
fontFamily:
"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Microsoft YaHei', sans-serif",
fontSize: 14,
controlHeight: 36,
wireframe: false
},
components: {
Button: {
borderRadius: 10,
fontWeight: 500,
controlHeight: 36,
primaryShadow: 'none',
defaultShadow: 'none'
},
Card: {
borderRadiusLG: 14
},
Input: {
borderRadius: 10,
controlHeight: 38
},
Modal: {
borderRadiusLG: 16,
paddingContentHorizontalLG: 24
},
Tabs: {
itemHoverColor: isDark ? '#e07b3e' : '#c2541f',
itemSelectedColor: isDark ? '#e07b3e' : '#c2541f',
inkBarColor: isDark ? '#e07b3e' : '#c2541f'
},
Menu: {
itemBorderRadius: 8,
itemSelectedBg: isDark ? '#2d2017' : '#fdf2ea',
itemSelectedColor: isDark ? '#e07b3e' : '#c2541f'
},
Drawer: {
paddingLG: 20
},
Tag: {
borderRadiusSM: 6
}
}
}),
[isDark]
);
const ctxValue = useMemo<ThemeCtx>(
() => ({
mode,
toggle: () => setMode((m) => (m === 'dark' ? 'light' : 'dark')),
setMode
}),
[mode]
);
return (
<ThemeContext.Provider value={ctxValue}>
<ConfigProvider locale={zhCN} theme={themeConfig}>
<AntApp>{children}</AntApp>
</ConfigProvider>
</ThemeContext.Provider>
);
}
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<ThemeProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</ThemeProvider>
</React.StrictMode>
);