foundation-theme
Foundation 脚手架的主题注册系统使用指南。说明如何注册新主题、切换主题、扩展调色板,以及如何在组件里安全地消费主题色。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Foundation 脚手架的主题注册系统使用指南。说明如何注册新主题、切换主题、扩展调色板,以及如何在组件里安全地消费主题色。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
| name | foundation-theme |
| description | Foundation 脚手架的主题注册系统使用指南。说明如何注册新主题、切换主题、扩展调色板,以及如何在组件里安全地消费主题色。 |
Foundation 脚手架内置一套注册式主题系统,建立在 MUI Theme 之上:
bg.surface / text.primary / accent ...),而不是裸十六进制色值;themeRegistry,可在运行时增删切换;<FoundationThemeProvider> 把当前预设编译成 MUI Theme 注入下游,组件继续用 MUI 的 sx / useTheme() 即可。默认注册了
foundation-light(白色,默认)与foundation-dark(暗色)两个预设。
src/styles/themes/
├── types.ts # FoundationPalette / FoundationThemePreset 接口
├── buildMuiTheme.ts # preset → MUI Theme 编译器(含组件覆盖)
├── registry.ts # 注册中心单例(register / get / list / subscribe)
├── ThemeProvider.tsx # <FoundationThemeProvider> + useFoundationTheme
├── presets/
│ ├── light.ts # 默认白色预设
│ └── dark.ts # 暗色预设
└── index.ts # 对外出口(含 registerFoundationThemes 启动函数)
App.tsx 顶部调用一次:
import { FoundationThemeProvider, registerFoundationThemes } from '@/styles/themes';
registerFoundationThemes(); // 幂等:内置 light + dark
export const App = () => (
<FoundationThemeProvider>
{/* ... */}
</FoundationThemeProvider>
);
registerFoundationThemes() 内部会把 light 标记为默认主题。如果你想换默认主题,不要直接改这个函数——注册一个新主题并指定 default: true(见第 4 节)。
铁律: 组件样式禁止硬编码十六进制。所有颜色必须从 theme.palette.foundation 取。
推荐:在 <Name>.styles.ts 写工厂函数:
// MyCard.styles.ts
import type { SxProps, Theme } from '@mui/material';
export const myCardStyles = (theme: Theme): Record<string, SxProps<Theme>> => {
const fp = theme.palette.foundation; // ← 语义调色板
return {
root: {
backgroundColor: fp.bg.surface,
border: `1px solid ${fp.divider}`,
color: fp.text.primary,
borderRadius: 1,
},
accent: { color: fp.accent },
};
};
// MyCard.tsx
import { useTheme } from '@mui/material';
import { myCardStyles } from './MyCard.styles';
export const MyCard = () => {
const theme = useTheme();
const styles = myCardStyles(theme);
return <Box sx={styles.root}>...</Box>;
};
可用槽位见 FoundationPalette:
| 槽位 | 用途 |
|---|---|
bg.base | 标题栏 / 最外层 |
bg.sidebar | 侧边栏 |
bg.content | 主内容区 |
bg.surface | 卡片 / Paper |
bg.elevated | 输入框 / Tooltip 内层 |
bg.hover / bg.active | 半透明 hover/active 覆盖 |
text.primary / text.secondary / text.muted | 文字三级 |
divider | 分隔线 |
accent / accentHover | 品牌强调色(按钮主色) |
status.danger / success / warning | 状态色 |
// src/styles/themes/presets/brand.ts
import type { FoundationThemePreset } from '../types';
export const brandPreset: FoundationThemePreset = {
name: 'brand-purple',
label: 'Brand · Purple',
mode: 'light',
palette: {
bg: {
base: '#f4f3ff',
sidebar: '#ffffff',
content: '#ffffff',
surface: '#ffffff',
elevated: '#faf9ff',
hover: 'rgba(99, 102, 241, 0.06)',
active: 'rgba(99, 102, 241, 0.12)',
},
text: { primary: '#1e1b4b', secondary: '#475569', muted: '#94a3b8' },
divider: 'rgba(30, 27, 75, 0.08)',
accent: '#6366f1',
accentHover: '#4f46e5',
status: { danger: '#dc2626', success: '#16a34a', warning: '#d97706' },
},
};
注册(推荐在应用启动时和 registerFoundationThemes() 一起):
import { themeRegistry } from '@/styles/themes';
import { brandPreset } from '@/styles/themes/presets/brand';
themeRegistry.register(brandPreset, { default: true }); // 设为默认
register是幂等的:相同name会覆盖。如果不指定default,注册的第一个主题自动成为默认。
任意组件里:
import { useFoundationTheme } from '@/styles/themes';
const ThemeSwitcher = () => {
const { current, available, setTheme } = useFoundationTheme();
return (
<select value={current.name} onChange={(e) => setTheme(e.target.value)}>
{available.map((p) => (
<option key={p.name} value={p.name}>{p.label}</option>
))}
</select>
);
};
<FoundationThemeProvider> 订阅了 themeRegistry.subscribe,新增 / 移除主题时 available 列表会自动刷新。
FoundationThemePreset.muiOverrides 字段会被 createTheme(base, muiOverrides) 深合并:
export const denseLight: FoundationThemePreset = {
...lightPreset,
name: 'foundation-light-dense',
label: 'Light · Dense',
muiOverrides: {
components: {
MuiButton: { defaultProps: { size: 'small' } },
},
typography: { fontSize: 13 },
},
};
❌ 在组件里直接写颜色:
<Box sx={{ backgroundColor: '#ffffff', color: '#0f172a' }} />
❌ 重新建立独立的 ThemeProvider:
<ThemeProvider theme={createTheme({ palette: { mode: 'dark' } })}>
❌ 旁路注册中心,直接 import 预设给 ThemeProvider:
import { lightPreset } from '@/styles/themes';
<ThemeProvider theme={buildMuiTheme(lightPreset)}>
✅ 永远走 <FoundationThemeProvider> + themeRegistry。
borderRadius: 6(方形圆角,不是圆形);hover/active 必有 transition;borderRadius: 8;borderRadius: 6,hover 用 bg.hover;bg.base,下方分隔线用 divider;bg.sidebar,激活项背景用 bg.active;后端 internal/app/window_<os>.go 里的 BackgroundColour 控制 webview 在 React 接管前的初始底色。当默认主题变更时,需要同步修改这个值,避免启动闪白 / 闪黑:
// 默认 light 主题:白色底
BackgroundColour: application.NewRGB(255, 255, 255),
如果你把默认主题切到深色,这里也要改成对应深色 RGB。
Foundation 脚手架的子窗口系统使用指南:ChildWindowService(Open/Close/List)、事件总线通信(定向 / 广播)、预设类型(confirm / message / blank)、新增子窗口类型标准操作,以及"子窗口 MVVM 与主窗口一致、通信只走事件总线"等铁律。
MUI 9 数据展示类组件在 Foundation 项目中的详尽用法。当使用 Typography/Avatar/Badge/Chip/Divider/List/Table/Tooltip 时参考。
MUI 9 反馈类组件在 Foundation 项目中的详尽用法。当使用 Alert/Dialog/Progress/Skeleton/Snackbar/Backdrop 时参考。
Foundation 项目 @mui/icons-material 图标库详尽用法指南。Icon 铁律:只用 *Rounded 系列,禁止 emoji/Unicode/第三方 icon 包。
MUI 9 输入类组件在 Foundation 项目中的详尽用法。当使用 Button/TextField/Select/Checkbox/Switch/Slider/Radio/Rating/Autocomplete/ToggleButton/FAB 时参考。
MUI 9 布局类组件在 Foundation 项目中的详尽用法。当使用 Box/Container/Grid/Stack/ImageList 时参考。