返回顶部
d

design-system-patterns设计系统模式

Foundational design system architecture — token hierarchies, theming infrastructure, token pipelines, and governance. Use when creating design tokens, implementing theme switching, setting up Style Dictionary, or establishing multi-brand theming. Triggers on design tokens, theme provider, Style Dictionary, token pipeline, multi-brand theming, CSS custom properties architecture.

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 1.0.0
安全检测
已通过
1,137
下载量
免费
免费
2
收藏
概述
安装方式
版本历史

design-system-patterns

设计系统模式

可扩展设计系统的基础架构:令牌层级、主题基础设施、令牌流水线和治理模式。



使用场景

  • - 定义令牌架构(原始层 → 语义层 → 组件层)
  • 使用 React 实现亮色/暗色/系统主题切换
  • 搭建 Style Dictionary 或 Figma 到代码的令牌流水线
  • 构建多品牌主题系统
  • 建立令牌命名规范和治理机制
  • 防止服务端渲染中未样式内容的闪烁(FOUC)

模式 1:令牌层级

三层令牌架构将原始值与含义及使用场景分离。

css
/ 第一层:原始令牌——原始值,绝不直接在组件中使用 /
:root {
--color-blue-500: #3b82f6;
--color-blue-600: #2563eb;
--color-gray-50: #fafafa;
--color-gray-900: #171717;

--space-1: 0.25rem;
--space-2: 0.5rem;
--space-4: 1rem;

--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--radius-sm: 0.25rem;
--radius-md: 0.5rem;
}

/ 第二层:语义令牌——上下文含义,感知主题 /
:root {
--text-primary: var(--color-gray-900);
--text-secondary: var(--color-gray-600);
--surface-default: white;
--surface-elevated: var(--color-gray-50);
--border-default: var(--color-gray-200);
--interactive-primary: var(--color-blue-500);
--interactive-primary-hover: var(--color-blue-600);
}

/ 第三层:组件令牌——特定用途,可选 /
:root {
--button-bg: var(--interactive-primary);
--button-bg-hover: var(--interactive-primary-hover);
--button-text: white;
--button-radius: var(--radius-md);
--button-padding-x: var(--space-4);
--button-padding-y: var(--space-2);
}

语义令牌是最重要的层级——它们实现了主题化。组件令牌是可选的,适用于复杂组件库。


模式 2:使用 React 进行主题切换

关键能力:theme(用户选择)、resolvedTheme(实际亮色/暗色)、setTheme、系统偏好检测、localStorage 持久化、DOM 属性应用。

tsx
type Theme = light | dark | system;

export function ThemeProvider({ children, defaultTheme = system, storageKey = theme,
attribute = data-theme }: { children: React.ReactNode; defaultTheme?: Theme;
storageKey?: string; attribute?: class | data-theme }) {
const [theme, setThemeState] = useState(() =>
typeof window === undefined ? defaultTheme
: (localStorage.getItem(storageKey) as Theme) || defaultTheme);
const [resolvedTheme, setResolvedTheme] = useState(light);

const getSystem = useCallback(() =>
matchMedia((prefers-color-scheme: dark)).matches ? dark : light as const, []);

const apply = useCallback((r: light | dark) => {
const root = document.documentElement;
attribute === class
? (root.classList.remove(light, dark), root.classList.add(r))
: root.setAttribute(attribute, r);
root.style.colorScheme = r;
setResolvedTheme(r);
}, [attribute]);

useEffect(() => { apply(theme === system ? getSystem() : theme); }, [theme, apply, getSystem]);

useEffect(() => { // 监听系统偏好变化
if (theme !== system) return;
const mq = matchMedia((prefers-color-scheme: dark));
const handler = () => apply(getSystem());
mq.addEventListener(change, handler);
return () => mq.removeEventListener(change, handler);
}, [theme, apply, getSystem]);

const setTheme = useCallback((t: Theme) => {
localStorage.setItem(storageKey, t); setThemeState(t);
}, [storageKey]);

return
{children}
;
}

完整的实现,包括 toggleTheme、disableTransitionOnChange 和测试模式,请参阅 references/theming-architecture.md

防止服务端渲染中的 FOUC(Next.js)

在 中的内联脚本在渲染前执行:

tsx
const themeScript = (function(){
var t=localStorage.getItem(theme)||system;
var d=t===dark||(t===system&&matchMedia((prefers-color-scheme:dark)).matches);
document.documentElement.setAttribute(data-theme,d?dark:light);
document.documentElement.style.colorScheme=d?dark:light;
})();

// 在 layout.tsx 中


Archiver·手机版·闲社网·闲社论坛·羊毛社区· 多链控股集团有限公司 · 苏ICP备2025199260号-1

Powered by Discuz! X5.0   © 2024-2025 闲社网·线报更新论坛·羊毛分享社区·http://xianshe.com

p2p_official_large