ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ant-design Menu 组件 Token 定制详解:通过组件级 Token 调试与重构菜单样式

ant-design Menu 组件 Token 定制详解:通过组件级 Token 调试与重构菜单样式 ant-design Menu 组件 Token 定制详解通过组件级 Token 调试与重构菜单样式【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design本文基于 ant-design 仓库中components/menu/demo/component-token这组调试示例Component Token debug讲解 Menu 组件级 TokenComponent Token的完整用法哪些 Token 可被覆盖、它们的默认值从何而来、暗色主题下 Token 如何被二次合并以及废弃 Token 到新版命名的迁移映射。读完本文你可以独立在ConfigProvider中精确控制 Menu 的背景、文字、圆角、指示条与暗色配色并能对照源码定位任意一个 Token 的生效位置。这个 demo 在做什么Menu 文档页index.zh-CN.md中有一行专门用于 Token 调试的示例code src./demo/component-token.tsx debug组件 Token/code对应的说明文件 component-token.md 非常简短标题就是“组件 Token debug / Debug Component Token”。它的实际价值在于配套的示例代码 component-token.tsx用三组独立的ConfigProvider分别演示了三类典型的组件级 Token 覆盖场景——弹出层背景popupBg、darkPopupBg水平菜单 dark 算法横向菜单交互态horizontalItemBorderRadius、horizontalItemHoverBg、popupBg暗色内联菜单配色darkItemColor、darkItemBg、darkSubMenuItemBg、darkItemSelectedColor、darkItemSelectedBg。下面是示例代码的完整结构摘自 component-token.tsxconst items: MenuItem[] [ { label: Navigation One, key: mail, icon: MailOutlined / }, { label: Navigation Two, key: app, icon: AppstoreOutlined /, disabled: true }, { label: Navigation Three - Submenu, key: SubMenu, icon: SettingOutlined /, children: [ { type: group, label: Item 1, children: [ { label: Option 1, key: setting:1 }, { label: Option 2, key: setting:2 }, ], }, // Item 2 分组略 ], }, { key: alipay, label: a href...Navigation Four - Link/a }, ]; // 场景一dark 算法 弹出层背景 Token ConfigProvider theme{{ algorithm: [theme.darkAlgorithm], components: { Menu: { popupBg: yellow, darkPopupBg: red, }, }, }} Menu onClick{onClick} selectedKeys{[current]} modehorizontal items{items} / Menu defaultSelectedKeys{[1]} defaultOpenKeys{[sub1]} modeinline themedark inlineCollapsed items{items2} style{{ width: 56 }} / /ConfigProvider // 场景二横向菜单圆角 / 悬浮背景 / 弹出背景 ConfigProvider theme{{ components: { Menu: { horizontalItemBorderRadius: 6, popupBg: red, horizontalItemHoverBg: #f5f5f5, }, }, }} Menu onClick{onClick} selectedKeys{[current]} modehorizontal items{items} / /ConfigProvider // 场景三暗色内联菜单的文字 / 背景 / 选中态 ConfigProvider theme{{ components: { Menu: { darkItemColor: #91daff, darkItemBg: #d48806, darkSubMenuItemBg: #faad14, darkItemSelectedColor: #ffccc7, darkItemSelectedBg: #52c41a, }, }, }} Menu defaultSelectedKeys{[1]} defaultOpenKeys{[sub1]} modeinline themedark items{items2} style{{ width: 256 }} / /ConfigProvider这套写法的关键点组件 Token 写在theme.components.Menu下只作用于该ConfigProvider子树内的 Menu不会污染全局场景一同时开启了theme.darkAlgorithm并搭配了themedark的 inline 菜单用于验证darkPopupBg在暗色算法 暗色组件双重条件下的表现场景二验证了横向菜单modehorizontal专属的三个 Token场景三验证了dark*前缀 Token 如何重写themedark内联菜单的整套配色。Menu 组件 Token 完整清单所有可在theme.components.Menu中传入的字段定义在 style/index.ts 的ComponentToken接口中。按功能分组整理如下默认值取自同文件的prepareComponentToken见下文弹出层与层级Token类型含义默认值dropdownWidthnumber \| string弹出菜单宽度160zIndexPopupnumber弹出菜单 z-indexzIndexPopupBase 50popupBgstring弹出框背景色colorBgElevateddarkPopupBgstring暗色模式下浮层菜单背景#001529collapsedWidthnumber \| string收起后的宽度controlHeightLG * 2itemWidthnumber \| string内部 tokeninternal按指示条自动计算calc(100% - itemMarginInline*2)或calc(100% activeBarBorderWidth)圆角与指示条active barToken含义默认值itemBorderRadius菜单项圆角旧名radiusItemborderRadiusLGsubMenuItemBorderRadius子菜单项圆角旧名radiusSubMenuItemborderRadiusSMhorizontalItemBorderRadius横向菜单项圆角0activeBarWidth指示条宽度旧名colorActiveBarWidth0activeBarHeight指示条高度旧名colorActiveBarHeightlineWidthBoldactiveBarBorderWidth指示条边框宽度旧名colorActiveBarBorderSizelineWidth文字颜色默认 / 悬浮 / 选中 / 禁用 / 危险Token含义默认值itemColor菜单项文字颜色colorTextitemHoverColor菜单项文字悬浮颜色colorTexthorizontalItemHoverColor水平菜单项文字悬浮颜色colorPrimaryitemSelectedColor菜单项文字选中颜色colorPrimarysubMenuItemSelectedColor子菜单内有选中项时的标题色colorPrimaryhorizontalItemSelectedColor水平菜单项文字选中颜色colorPrimaryitemDisabledColor菜单项文字禁用颜色colorTextDisableddangerItemColor/dangerItemHoverColor/dangerItemSelectedColor危险菜单项文字颜色三态均为colorError背景色Token含义默认值itemBg菜单项背景色colorBgContaineritemHoverBg菜单项悬浮态背景色colorBgTextHoveritemActiveBg菜单项激活态背景色controlItemBgActiveitemSelectedBg菜单项选中态背景色controlItemBgActivesubMenuItemBg子菜单项背景色colorFillAlterhorizontalItemHoverBg横向菜单项悬浮态背景色transparenthorizontalItemSelectedBg水平菜单项选中态背景色transparentdangerItemActiveBg/dangerItemSelectedBg危险菜单项激活 / 选中背景colorErrorBg布局与排版Token含义默认值itemHeight菜单项高度controlHeightLGitemMarginInline菜单项横向外间距marginXXSitemMarginBlock菜单项纵向外间距marginXXSitemPaddingInline菜单项横向内间距paddinghorizontalLineHeight横向菜单行高controlHeightLG * 1.15 pxgroupTitleColor分组标题文字颜色旧名colorGroupTitlecolorTextDescriptiongroupTitleLineHeight分组标题行高lineHeightgroupTitleFontSize分组标题字号fontSizeiconSize图标尺寸fontSizeiconMarginInlineEnd图标与文字间距controlHeightSM - fontSizecollapsedIconSize收起时图标尺寸fontSizeLG暗色模式专用dark*前缀Token含义默认值darkItemColor暗色下菜单项文字颜色colorTextLightSolid的 65% 不透明度darkItemBg暗色下菜单项背景#001529darkSubMenuItemBg暗色下子菜单项背景#000c17darkItemSelectedColor暗色下菜单项选中颜色colorTextLightSoliddarkItemSelectedBg暗色下菜单项选中背景colorPrimarydarkItemHoverBg暗色下菜单项悬浮背景transparentdarkItemHoverColor暗色下菜单项悬浮颜色colorTextLightSoliddarkItemDisabledColor暗色下菜单项禁用颜色colorTextLightSolid的 25% 不透明度darkGroupTitleColor暗色下分组标题颜色同darkItemColor的计算结果darkDangerItemColor/darkDangerItemHoverColor/darkDangerItemSelectedColor/darkDangerItemSelectedBg/darkDangerItemActiveBg暗色下危险项各态配色基于colorError/colorErrorHover默认值是如何计算的prepareComponentToken上面表中的“默认值”并非凭空而来而是 style/index.ts 中prepareComponentToken函数基于全局种子 Token推导出来的例如export const prepareComponentToken: GetDefaultTokenMenu (token) { const { colorPrimary, colorError, colorTextDisabled, /* ... */ } token; const activeBarWidth token.activeBarWidth ?? 0; const activeBarBorderWidth token.activeBarBorderWidth ?? lineWidth; const itemMarginInline token.itemMarginInline ?? token.marginXXS; const colorTextDark new FastColor(colorTextLightSolid).setA(0.65).toRgbString(); return { dropdownWidth: 160, zIndexPopup: token.zIndexPopupBase 50, itemBorderRadius: token.borderRadiusLG, itemColor: colorText, itemSelectedColor: colorPrimary, itemBg: colorBgContainer, itemHoverBg: colorBgTextHover, subMenuItemBg: colorFillAlter, horizontalItemSelectedBg: transparent, itemHeight: controlHeightLG, collapsedWidth: controlHeightLG * 2, popupBg: colorBgElevated, horizontalLineHeight: ${controlHeightLG * 1.15}px, iconSize: fontSize, iconMarginInlineEnd: controlHeightSM - fontSize, collapsedIconSize: fontSizeLG, // Dark darkItemBg: #001529, darkPopupBg: #001529, darkSubMenuItemBg: #000c17, darkItemSelectedBg: colorPrimary, // internal itemWidth: activeBarWidth ? calc(100% ${activeBarBorderWidth}px) : calc(100% - ${itemMarginInline * 2}px), }; };由此可以得到几条实用结论默认配色是“种子 Token 的函数”只要你在 ConfigProvider 里改了colorPrimary菜单的选中文字、暗色选中背景darkItemSelectedBg等会随之联动无需再传组件 Tokendark*默认值是硬编码深蓝#001529/#000c17这是 Menu 暗色主题的经典底色demo 场景三中把它们分别覆盖为#d48806/#faad14正是为了可视化验证 Token 覆盖生效itemWidth是内部计算 token当activeBarWidth大于 0 时选中项宽度会扩展以容纳指示条边框这解释了为什么改activeBarWidth后选中项布局会变化。暗色 Token 的二次合并机制dark*系列 Token 并不是直接写进 CSS 的而是在样式生成阶段被“投影”到普通 Token 上。在 style/index.ts 中可以看到menuDarkToken的构造const menuDarkToken mergeTokenMenuToken(menuToken, { itemColor: darkItemColor, itemHoverColor: darkItemHoverColor, groupTitleColor: darkGroupTitleColor, itemSelectedColor: darkItemSelectedColor, subMenuItemSelectedColor: darkItemSelectedColor, itemBg: darkItemBg, popupBg: darkPopupBg, subMenuItemBg: darkSubMenuItemBg, itemActiveBg: transparent, itemSelectedBg: darkItemSelectedBg, activeBarHeight: 0, activeBarBorderWidth: 0, itemHoverBg: darkItemHoverBg, itemDisabledColor: darkItemDisabledColor, dangerItemColor: darkDangerItemColor, /* ... */ menuSubMenuBg: darkSubMenuItemBg, horizontalItemSelectedColor: darkItemSelectedColor, horizontalItemSelectedBg: darkItemSelectedBg, });随后getThemeStyle(menuToken, light)与getThemeStyle(menuDarkToken, dark)分别生成明暗两套规则style/index.ts。这解释了两个现象为什么 demo 场景三只需传 5 个dark*Token就能同时改变暗色菜单的文字色、底色、子菜单底色、选中文字、选中背景——它们在暗色规则集里被统一投影成了itemColor、itemBg、subMenuItemBg、itemSelectedColor、itemSelectedBg为什么dark*Token 在themelight的菜单上不生效——它们只参与 dark 规则集的合并而 demo 场景一中的darkPopupBg也是同理它被投影为暗色规则下的popupBg。废弃 Token 的迁移映射Menu 的组件 Token 经历了一次命名规范化color*/radius*前缀 → 语义化命名。style/index.ts 的deprecatedTokens选项登记了全部映射旧 Token 仍然可用会走废弃告警链路废弃 Token替代 TokencolorGroupTitlegroupTitleColorradiusItemitemBorderRadiusradiusSubMenuItemsubMenuItemBorderRadiuscolorItemText/colorItemTextHoveritemColor/itemHoverColorcolorItemTextHoverHorizontalhorizontalItemHoverColorcolorItemTextSelecteditemSelectedColorcolorItemTextSelectedHorizontalhorizontalItemSelectedColorcolorItemTextDisableditemDisabledColorcolorDangerItemText/colorDangerItemTextHover/colorDangerItemTextSelecteddangerItemColor/dangerItemHoverColor/dangerItemSelectedColorcolorDangerItemBgActive/colorDangerItemBgSelecteddangerItemActiveBg/dangerItemSelectedBgcolorItemBg/colorItemBgHover/colorSubItemBgitemBg/itemHoverBg/subMenuItemBgcolorItemBgActiveitemActiveBgcolorItemBgSelected/colorItemBgSelectedHorizontalitemSelectedBg/horizontalItemSelectedBgcolorActiveBarWidth/colorActiveBarHeight/colorActiveBarBorderSizeactiveBarWidth/activeBarHeight/activeBarBorderWidth如果你维护的是 5.x 早期版本的配置可以直接照这张表做批量替换行为保持不变。最小实战用法与验证方式综合以上生产环境中最常见的用法就是把场景三的模式抽出来ConfigProvider theme{{ components: { Menu: { itemSelectedBg: rgba(22, 119, 255, 0.1), darkItemBg: #141414, darkSubMenuItemBg: #1f1f1f, }, }, }} App / /ConfigProvider需要注意的前提组件 Token 依赖ConfigProvider的theme机制作用域仅限其子树dark*Token 只对themedark的 Menu 生效zIndexPopup、itemWidth等偏内部用途的字段一般无需手动覆盖。这套行为在仓库中有自动化保障示例的渲染结果被快照测试锁定在 demo.test.tsx.snap 中含renders components/menu/demo/component-token.tsx correctly断言且扩展上下文场景也有对应快照demo-extend.test.ts.snap当 Token 默认值或合并逻辑变更时这些快照会第一时间暴露差异。小结Menu 组件 Token 的完整契约定义在 components/menu/style/index.ts 的ComponentToken接口中调试入口是 demo/component-token.tsx默认值由prepareComponentToken从种子 Token 推导改全局colorPrimary等即可联动默认配色dark*Token 在样式生成时经mergeToken投影为暗色规则集的普通 Token只影响themedark的菜单与浮层旧版color*/radius*Token 均有替代项迁移对照以上映射表即可。【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表