Backstage 组件设计指南:基于 Material UI 主题的布局、色彩与排版实践 Backstage 组件设计指南基于 Material UI 主题的布局、色彩与排版实践【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage无论你是想为 Backstage 提交一个全新组件还是在插件内开发页面级组件都需要遵循统一的设计规范让组件与整个开发者门户的视觉体系保持一致。本篇指南以 docs/dls/component-design-guidelines.md 为骨架系统讲解决定组件观感的三大主题维度——布局Layout、色彩Color palette、排版Typography并结合本仓库backstage/theme包的源码实现说明这些规范背后的主题机制。读完本文你将掌握如何选用布局组件、如何从主题调色板取色、如何在自定义组件中正确使用排版从而写出主题感知theme-aware、能随浅色/深色主题自动适配的 Backstage 组件。规范总览三大维度都建立在 Material UI 主题之上Backstage 的组件设计规范围绕三个核心主题展开它们全部构建在 Material UI 主题特性之上布局Layout决定内容如何组织与堆叠色彩Color palette决定组件用什么颜色排版Typography决定文字的字族、字号、字重与对比度。三者共同定义了组件的通用观感。规范的核心原则是尽可能复用现成组件、尽可能引用主题theme而非写死数值这样当应用更换主题时你的布局、颜色和文字会自动响应变化无需修改组件代码。布局Layout优先复用其次回退最后自建组件选用的三级策略关于如何组织内容规范给出了明确的优先级优先使用 Backstage 的现成组件——可通过 Backstage 组件 Storybook 查看组件清单与在线演示回退使用 Material UI 组件——可参考 Material UI 官方组件文档如果以上都不满足布局需求再自建组件。其中最关键的一条约束是不建议直接用裸 HTML CSS 实现布局。因为直接使用 CSS 会导致布局无法感知主题变化。正确做法是使用 Material UI 的布局组件让布局主题感知——一旦有人修改了主题你的布局能自动响应这些变化而不需要同步更新组件代码。核心布局组件与 theme.spacing()规范重点推荐了以下直接使用theme.spacing()函数控制 margin、padding 与定位同时继承调色板与排版的布局组件组件典型用途Container大多用于页面级的内容容器限制内容最大宽度Box类似div可通过 props 高度定制样式Grid用于灵活的栅格布局Paper卡片的基础提供背景色与边缘内边距Card完整卡片支持标题、描述、按钮、图片等这些组件的间距之所以推荐用theme.spacing()是因为间距值会随主题的 spacing 配置统一缩放。仓库中 defaultComponentThemes.ts 就是一个实例默认给MuiGrid设置了spacing: 2作为默认 props保证全局栅格间距一致同时通过MuiCssBaseline的styleOverrides将滚动条、a标签、body 的fontSize: 0.875rem等基础样式主题化见 defaultComponentThemes.ts说明 Backstage 连最基础的布局底座都统一挂到了主题上。// 主题感知布局的示意间距来自 theme.spacing() import { makeStyles } from material-ui/core; const useStyles makeStyles((theme: Theme) ({ page: { padding: theme.spacing(3), // 随主题间距体系自动缩放 }, }));色彩Color palette永远引用主题调色板两类场景两种做法复用已有组件、想全局调整它的颜色如 padding、margin、颜色使用Custom Theme自定义主题对指定组件的样式做 override。Backstage 自定义主题的完整方法见 docs/conf/user-interface/index.md。从零编写组件尽可能引用主题使用主题自带的调色板。大多数 Backstage 组件与全部 Material UI 组件默认都会使用主题调色板因此除非你需要显式控制某个组件的颜色例如组件设计时用的是primary色而你希望换成secondary色否则最便捷的方式就是按 Backstage 推荐的方式Override the Component Styles覆盖组件样式。自定义组件取色的标准写法覆盖主题颜色在 Material UI 组件中并不常见但假设你有一个自定义 Sidebar 组件内含一个Paper希望用不同颜色高亮侧边栏内容可以像下面这样通过makeStyles访问主题调色板import { makeStyles, Paper } from material-ui/core; const useStyles makeStyles((theme: Theme) ({ sidebarPaper: { backgroundColor: theme.palette.primary.main, color: theme.palette.primary.contrastText, }, })); export function Sidebar({ children }) { const { sidebarPaper } useStyles(); return Paper className{sidebarPaper}{children}/Paper; }这里的关键是颜色 token 是固定的与 token 关联的具体色值则随应用主题的调色板变化。同一个theme.palette.primary.main在浅色主题下是深蓝在深色主题下会自动切换为适合暗底的浅蓝——这正是主题感知的体现。内置调色板 token 与默认值源码实证仓库中 packages/theme/src/base/palettes.ts 定义了 Backstage 内置的浅色与深色两套调色板token 完全一致、色值不同。以下为浅色主题palettes.light的关键默认值Token 分组Token浅色主题默认值深色主题默认值backgrounddefault/paper#F8F8F8/#FFFFFF#333333/#424242primarymain#1F5493#9CC9FFsecondarymain未单独定义#FF88B2statusok#1DB954#71CF88statuswarning#FF9800#FFB84Dstatuserror#E22134#F84C55statusrunning#1F5493#3488E3statuspending#FFED51#FEF071statusaborted#757575#9E9E9Enavigationbackground/indicator#171717/#9BF0E1#424242/#9BF0E1texttextSubtle/textContrast#6E6E6E/#000000#CCCCCC/#FFFFFFlinklink/linkHover#0A6EBE/#2196F3#9CC9FF/#82BAFDbannerinfo/error/warning#2E77D0/#E22134/#FF9800同左不变这些额外调色板 slot 的类型定义见 packages/theme/src/base/types.ts 中的BackstagePaletteAdditions除上述内容外还包括border、textVerySubtle、highlight、errorBackground、warningBackground、infoBackground、errorText、infoText、warningText、gold、tabbar.indicator、pinSidebarButton等其中bursts段已被标记为deprecated将在未来版本移除新代码不应再依赖它。除了调色板主题还包含页面主题Page Theme——即页面头部彩色爆发burst背景。见 packages/theme/src/base/pageTheme.tshome、documentation、tool、service、website、library、other、app、apis、card各有预置的渐变色colorVariants如teal、pinkSea、purpleSky与 SVG 形状shapes.wave、wave2、round、square。由于这些背景形状与颜色属于装饰性元素代码将其作为 CSSbackground-image放置在页面上而不是单独的 HTML 元素见 pageTheme.ts 的genPageTheme实现。自定义主题覆盖颜色的实操在应用层创建自定义主题时可用createUnifiedTheme配合createBaseThemeOptions覆盖调色板实现品牌化示例源自 docs/conf/user-interface/index.mdimport { createBaseThemeOptions, createUnifiedTheme, genPageTheme, palettes, shapes, } from backstage/theme; export const myTheme createUnifiedTheme({ ...createBaseThemeOptions({ palette: { ...palettes.light, primary: { main: #343b58 }, secondary: { main: #565a6e }, error: { main: #8c4351 }, background: { default: #d5d6db, paper: #d5d6db }, navigation: { background: #343b58, indicator: #8f5e15, color: #d5d6db, selectedColor: #ffffff, }, }, }), defaultPageTheme: home, fontFamily: Comic Sans MS, pageTheme: { home: genPageTheme({ colors: [#8c4351, #343b58], shape: shapes.wave }), tool: genPageTheme({ colors: [#8c4351, #343b58], shape: shapes.round }), }, });排版Typography交给 Typography 组件与主题Typography 组件如何工作绝大多数情况下Material UI 组件内部都会使用Typography /组件渲染文字它会自动读取主题的 typography 属性字族、字号、字重以及调色板中适合当前上下文的前景色。规范特别举例说明这种上下文自适应contained按钮使用白色字体非outlined按钮通过 props 传入对应颜色以保证对比度深色主题下按钮会自动改用深色字体而非白色从而保证可读性。何时必须显式使用 Typography当内容的父组件不负责处理文本时——典型场景是父组件是布局类组件如Grid、Box、Paper——你就应该使用Typography /组件而不是原生 HTML 标签。它通常用于标题和段落但适用于任何类型的文本。这样文字才能继承主题的字族、字号、字重与调色板颜色而不是依赖浏览器的默认样式。默认排版参数源码实证packages/theme/src/base/createBaseThemeOptions.ts 定义了 Backstage 默认排版Token默认值htmlFontSize16fontFamilyHelvetica Neue, Helvetica, Roboto, Arial, sans-serifh1fontSize: 54, fontWeight: 700, marginBottom: 10h2fontSize: 40, fontWeight: 700, marginBottom: 8h3fontSize: 32, fontWeight: 700, marginBottom: 6h4fontSize: 28, fontWeight: 700, marginBottom: 6h5fontSize: 24, fontWeight: 700, marginBottom: 4h6fontSize: 20, fontWeight: 700, marginBottom: 2自定义排版整体替换与局部覆盖如果只想覆盖其中一部分例如只改h1可先展开defaultTypography再局部覆盖避免丢失其余默认值示例源自 docs/conf/user-interface/index.mdimport { createBaseThemeOptions, createUnifiedTheme, defaultTypography, palettes, } from backstage/theme; export const myTheme createUnifiedTheme({ ...createBaseThemeOptions({ palette: palettes.light, typography: { ...defaultTypography, // 继承默认值 htmlFontSize: 16, fontFamily: Roboto, sans-serif, h1: { fontSize: 72, fontWeight: 700, marginBottom: 10 }, // 局部覆盖 }, defaultPageTheme: home, }), });类型层面BackstageTypography见 packages/theme/src/base/types.ts要求htmlFontSize、fontFamily以及h1~h6各自具备fontSize、fontWeight、marginBottom字段自定义排版时必须满足该结构。另外Material UI 官方排版文档关于**无障碍accessibility**的建议同样适用于 Backstage 组件。仓库中也提供了无障碍设计专题文档 docs/accessibility/index.md在开发新组件时建议一并参考。主题机制在仓库中的落地从 token 到运行时上述规范之所以能落地依赖的是backstage/theme包的主题实现其核心在 packages/theme/src 目录内置主题themes.light与themes.dark由createUnifiedTheme({ palette: palettes.light/dark })生成见 packages/theme/src/unified/themes.ts主题工厂createUnifiedTheme接受调色板、pageTheme、fontFamily、htmlFontSize、typography等输入见 packages/theme/src/base/createBaseThemeOptions.ts并内置了默认页面主题home的兜底逻辑双版本支持UnifiedTheme.getTheme(version)同时支持 Material UIv4与v5两种主题对象见 packages/theme/src/unified/types.tsv4 版本通过 overrides.ts 中的transformV5ComponentThemesToV4将 v5 组件样式转换为 v4overrides并处理了 spacing 函数的差异__v5Spacing旧 API 弃用早期使用的createTheme/createThemeOptions/createThemeOverrides已标记为deprecated见 packages/theme/src/v4/baseTheme.ts新代码应使用createUnifiedTheme。在应用侧主题通过createApp的themes数组注册并由UnifiedThemeProvider注入给 MUI 组件注册方式详见 docs/conf/user-interface/index.md 中的App.tsx示例。这也解释了为什么组件规范反复强调引用主题而非写死数值theme.spacing()、theme.palette.*、theme.typography.*最终都会由运行时主题统一供给。小结Backstage 组件设计规范可以浓缩为三条行动准则布局Backstage 组件 → Material UI 组件 → 自建组件的优先级自建时务必使用theme.spacing()与布局组件保持布局主题感知色彩复用组件改色走自定义主题 override自建组件一律从theme.palette取色token 固定、色值随主题切换排版凡是父组件不负责渲染文本的地方统一使用Typography /让字族、字号、字重与对比度全部交由主题决定。围绕这三条准则本文还从 packages/theme/src/base/palettes.ts、packages/theme/src/base/createBaseThemeOptions.ts、packages/theme/src/base/pageTheme.ts 等源码中还原了默认调色板、默认排版与页面主题的具体数值你可以直接以这些 token 为基准开展组件开发也可以参考 docs/conf/user-interface/index.md 在应用层构建符合自身品牌的自定义主题。【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考