Skip to main content

主题定制

Summary

主题由文档根元素的 data-theme 和共享 CSS 变量决定,颜色、字体、圆角、间距与阴影均可按需覆盖。独立应用使用 ThemeProvider 管理主题,ThemeControl 提供三种偏好选择,ThemeButton 提供受控的一键深浅切换。已有主题管理器的站点继续由宿主控制。样式覆盖放在组件库之后,优先采用公开变量和属性,生成的 CSS Module 类名不作为稳定接口。

参考资料​

主题变量​

先导入 theme.css 和 styles.css,再加载应用覆盖样式。常用变量如下,完整清单以源码为准。

用途变量
强调色--lk-color-primary、--lk-color-primary-dark、--lk-color-primary-light
背景--lk-background-color、--lk-card-background-color
文字--lk-font-color-base、--lk-font-color-secondary、--lk-heading-color
中性色--lk-color-emphasis-100 至 --lk-color-emphasis-900
分割线--lk-divider-color、--lk-divider-width
状态色--lk-color-success、--lk-color-warning、--lk-color-danger
字体--lk-font-family、--lk-font-mono、--lk-font-size、--lk-line-height
圆角--lk-radius-control、--lk-radius-overlay、--lk-radius-sm、--lk-radius-md、--lk-radius-lg
间距--lk-space-1、--lk-space-2、--lk-space-3、--lk-space-4、--lk-space-6、--lk-space-8 等
阴影与焦点--lk-shadow-sm、--lk-shadow-md、--lk-shadow-lg、--lk-focus-ring
264 Bcss
:root,
:root[data-theme] {
--lk-color-primary: #1d9bf0;
--lk-color-primary-dark: #0f8ee3;
--lk-color-primary-light: #36a6f2;
--lk-radius-control: 10px;
}

:root[data-theme='dark'] {
--lk-background-color: #111214;
--lk-card-background-color: #1c1e21;
}

显式指定根元素 data-theme="light" 或 data-theme="dark";没有指定时,默认变量跟随系统偏好。主题按整份文档管理,不把嵌套的深浅色容器当作隔离边界。

--lk-divider-color 默认使用当前主题的 --lk-color-emphasis-200,--lk-divider-width 默认为 1px。Divider、面板内部分区与顶部栏边界共用这两个变量;间距仍由所在布局控制。可在根元素统一调整,或在局部容器中覆盖。

间距与交互变量​

变量用途
--lk-page-padding-block页面内容上下留白,默认 clamp(2rem, 4vw, 3rem)
--lk-page-padding-inline页面水平留白,默认 clamp(1rem, 3vw, 2rem)
--lk-space-section内容分区之间的间隔,默认 clamp(2rem, 4vw, 3rem)
--lk-space-section-header分区标题到正文的间隔,默认 1.25rem
--lk-font-size-meta分区附加信息字号,默认 0.875rem
--lk-radius-xs紧凑圆角,默认 4px
--lk-transition短交互过渡,默认 160ms ease

Page、SectionHeader 与表单组件使用这些变量。应用应按内容角色选择变量,保留不同布局需要的间距;专门的展开、滚动和图形动画可以继续使用自己的时长。

主题偏好​

推荐提供「跟随系统、浅色、深色」三个互斥选项。它们是三种偏好,实际显示仍只有浅色和深色两套配色。

选择行为
跟随系统默认选择;立即采用系统外观,并随系统变化继续更新
浅色保存为固定浅色,直到用户再次修改
深色保存为固定深色,直到用户再次修改

系统外观变化不会覆盖手动选择,即使系统一度变成相同的配色也保留原有偏好。例如,用户固定选择深色后,系统从浅色变成深色、再变回浅色,网站仍保持深色;只有用户选回「跟随系统」才恢复同步。

刷新页面和同源标签页共享保存的选择,切换界面语言也不改变偏好。非法保存值或存储不可用时默认跟随系统;存储不可用不应阻止当前页面手动切换。首次绘制脚本与挂载后的主题管理器读取相同偏好,同时设置原生控件的 color-scheme 和已有的 theme-color,避免页面初始化时闪烁。

导航栏可使用紧凑三项菜单,设置页可使用分段选择器。已有框架提供三态循环按钮时,也可以保留该入口并在设置页明确展示三个选项。图标表示所选偏好:「跟随系统」显示系统图标,当前实际配色变化不会将其变成固定浅色或深色。

独立应用​

313 Btsx
import { ThemeControl, ThemeProvider } from '@lailai0916/ui';

export function ThemeSettings() {
return (
<ThemeProvider storageKey="my-app.theme">
<ThemeControl
variant="compact"
labels={{ system: '跟随系统', light: '浅色', dark: '深色' }}
/>
</ThemeProvider>
);
}

ThemeProvider 作用于整份文档,在应用根部挂载一次即可。

接口行为
storageKey默认 lailai.theme;需要独立偏好时使用其他键
mode默认 preference 保存偏好;system 跟随系统并允许当前页临时切换
themeColors可选 { light, dark },更新已有的 theme-color meta 标签
useTheme().preferencesystem、light 或 dark
useTheme().resolvedTheme当前实际使用的 light 或 dark
useTheme().setPreference更新偏好;仅 preference 模式在可用时保存到本地存储

Provider 挂载后读取保存值,监听系统偏好和其他标签页的存储变化。本地存储被禁用时,当前页仍可切换。themeColors 不会创建 meta 标签,应用需要自行提供该标签。

ThemeControl.labels 必须包含三种模式的文案。variant 默认为 segmented,也可使用 compact。紧凑菜单支持方向键、Home、End、Escape,选择后返回触发按钮;Tab 正常离开菜单。

一键深浅切换​

ThemeButton 是受控按钮,传入 theme="light" | "dark" 与 onThemeChange。太阳或月亮显示当前主题,点击请求另一种主题;默认提示文案跟随 LaikitProvider 的语言,可用 label 覆盖。按钮支持原生属性和 ref,桌面为 32 px,小于等于 980 px 或触摸设备增至 44 px,尊重减少动态效果设置。

示例只展示按钮状态,不改变本文的主题。独立应用可在已有的根部 Provider 内连接真实主题:

228 Btsx
import { ThemeButton, useTheme } from '@lailai0916/ui';

export function AppearanceAction() {
const { resolvedTheme, setPreference } = useTheme();
return <ThemeButton theme={resolvedTheme} onThemeChange={setPreference} />;
}

ThemeProvider mode="system" 是用于兼容临时覆盖需求的可选模式:忽略保存的偏好,当前页允许临时切换,系统变化或重新打开页面后恢复跟随系统。它不符合上方的持久三态偏好约定;普通网站保留默认的 preference 模式。

ThemeButton 只提供深浅切换,不能单独表达「跟随系统」。用它控制整站外观时,需要另有明确的三项偏好入口。

已有 Docusaurus 等主题管理器时,直接将其状态与切换回调传给 ThemeButton,不用添加第二个 Provider。

宿主主题​

已有主题管理器的应用继续使用原有机制,通过 CSS 变量连接组件库。以下以 Docusaurus 为例,将其主题变量映射到 --lk-*:

413 Bcss
:root,
:root[data-theme] {
--lk-color-primary: var(--ifm-color-primary);
--lk-color-primary-dark: var(--ifm-color-primary-dark);
--lk-color-primary-light: var(--ifm-color-primary-light);
--lk-background-color: var(--ifm-background-color);
--lk-card-background-color: var(--ifm-card-background-color);
--lk-font-color-base: var(--ifm-font-color-base);
--lk-font-family: var(--ifm-font-family-base);
}

这是一组最小映射,完整宿主适配还应覆盖需要跟随设置变化的文字、中性色和字号。页面首次绘制前的偏好恢复由宿主自己的初始化脚本处理;服务端与客户端初始 React 内容保持一致。

局部样式​

按顺序考虑组件属性、className、主题变量,再使用公开的 data-lk 标记。支持的标记为 button、avatar、brand、brand-logo、divider、field-control、panel、theme-menu。

59 Bcss
.settings [data-lk='field-control'] {
max-width: 28rem;
}

不要选择构建生成的哈希类名。组件库包含减少动态效果的系统偏好适配;应用额外添加的动画也应遵守同一偏好。