diff --git a/components/menu/demo/menu-v4.md b/components/menu/demo/menu-v4.md new file mode 100644 index 0000000000..f7c013a71d --- /dev/null +++ b/components/menu/demo/menu-v4.md @@ -0,0 +1,7 @@ +## zh-CN + +V4 样式的 Menu 组件。 + +## en-US + +Menu with v4 style. diff --git a/components/menu/demo/menu-v4.tsx b/components/menu/demo/menu-v4.tsx new file mode 100644 index 0000000000..303ea0f583 --- /dev/null +++ b/components/menu/demo/menu-v4.tsx @@ -0,0 +1,91 @@ +import React, { useState } from 'react'; +import { + AppstoreOutlined, + CalendarOutlined, + LinkOutlined, + MailOutlined, + SettingOutlined, +} from '@ant-design/icons'; +import { Menu, Switch, ConfigProvider } from 'antd'; +import type { MenuProps } from 'antd/es/menu'; + +type MenuItem = Required['items'][number]; + +function getItem( + label: React.ReactNode, + key?: React.Key | null, + icon?: React.ReactNode, + children?: MenuItem[], +): MenuItem { + return { + key, + icon, + children, + label, + } as MenuItem; +} + +const items: MenuItem[] = [ + getItem('Navigation One', '1', ), + getItem('Navigation Two', '2', ), + getItem('Navigation Two', 'sub1', , [ + getItem('Option 3', '3'), + getItem('Option 4', '4'), + getItem('Submenu', 'sub1-2', null, [getItem('Option 5', '5'), getItem('Option 6', '6')]), + ]), + getItem('Navigation Three', 'sub2', , [ + getItem('Option 7', '7'), + getItem('Option 8', '8'), + getItem('Option 9', '9'), + getItem('Option 10', '10'), + ]), + getItem( + + Ant Design + , + 'link', + , + ), +]; + +const App: React.FC = () => { + const [mode, setMode] = useState<'vertical' | 'inline'>('inline'); + + const changeMode = (value: boolean) => { + setMode(value ? 'vertical' : 'inline'); + }; + + return ( + <> + Change Mode +
+
+ + + + + ); +}; + +export default App; diff --git a/components/menu/demo/submenu-theme.tsx b/components/menu/demo/submenu-theme.tsx index 10b756a76c..c40bf55de5 100644 --- a/components/menu/demo/submenu-theme.tsx +++ b/components/menu/demo/submenu-theme.tsx @@ -58,7 +58,7 @@ const App: React.FC = () => { Sub-menu theme Switch the menu type Style debug +V4 Menu ## API diff --git a/components/menu/index.zh-CN.md b/components/menu/index.zh-CN.md index f7fe07513a..e20b3fc5e2 100644 --- a/components/menu/index.zh-CN.md +++ b/components/menu/index.zh-CN.md @@ -63,6 +63,7 @@ return ; 子菜单主题 切换菜单类型 Style debug +V4 Menu ## API diff --git a/components/menu/style/index.tsx b/components/menu/style/index.tsx index 43b9e8c16e..e15ba63025 100644 --- a/components/menu/style/index.tsx +++ b/components/menu/style/index.tsx @@ -18,12 +18,15 @@ export interface ComponentToken { // radius radiusItem: number; + radiusSubMenuItem: number; // Item Text // > Default colorItemText: string; colorItemTextHover: string; + colorItemTextHoverHorizontal: string; colorItemTextSelected: string; + colorItemTextSelectedHorizontal: string; // > Disabled colorItemTextDisabled: string; @@ -37,6 +40,7 @@ export interface ComponentToken { // Item Bg colorItemBg: string; + colorItemBgHover: string; colorSubItemBg: string; // > Default @@ -48,6 +52,8 @@ export interface ComponentToken { colorActiveBarWidth: number; colorActiveBarHeight: number; colorActiveBarBorderSize: number; + + itemMarginInline: number; } export interface MenuToken extends FullToken<'Menu'> { @@ -78,6 +84,8 @@ const getBaseStyle: GenerateStyle = token => { iconCls, zIndexPopup, radiusBase, + radiusLG, + radiusSubMenuItem, menuArrowSize, controlHeightSM, menuArrowOffset, @@ -132,7 +140,7 @@ const getBaseStyle: GenerateStyle = token => { flex: 'none', }, }, - [`${componentCls}-item,${componentCls}-submenu,`]: { + [`${componentCls}-item, ${componentCls}-submenu`]: { borderRadius: token.radiusItem, }, @@ -279,7 +287,7 @@ const getBaseStyle: GenerateStyle = token => { position: 'absolute', zIndex: zIndexPopup, background: 'transparent', - borderRadius: radiusBase, + borderRadius: radiusLG, boxShadow: 'none', transformOrigin: '0 0', @@ -302,7 +310,11 @@ const getBaseStyle: GenerateStyle = token => { }, [`> ${componentCls}`]: { - borderRadius: radiusBase, + borderRadius: radiusLG, + + [`> ${componentCls}-item`]: { + borderRadius: radiusSubMenuItem, + }, [`${componentCls}-submenu-title::after`]: { transition: `transform ${motionDurationSlow} ${motionEaseInOut}`, @@ -480,25 +492,31 @@ export default (prefixCls: string, injectStyle: boolean): UseComponentStyleResul colorTextDescription, colorBgContainer, colorFillAlter, - controlItemBgActive, + colorFillContent, lineWidth, lineWidthBold, + controlItemBgActiveHover, + colorBgTextHover, } = token; return { dropdownWidth: 160, zIndexPopup: token.zIndexPopupBase + 50, - radiusItem: 0, + radiusItem: token.radiusLG, + radiusSubMenuItem: token.radiusSM, colorItemText: colorText, - colorItemTextHover: colorPrimary, + colorItemTextHover: colorText, + colorItemTextHoverHorizontal: colorPrimary, colorGroupTitle: colorTextDescription, - colorItemTextSelected: colorPrimary, + colorItemTextSelected: colorText, + colorItemTextSelectedHorizontal: colorPrimary, colorItemBg: colorBgContainer, + colorItemBgHover: colorBgTextHover, + colorItemBgActive: colorFillContent, colorSubItemBg: colorFillAlter, - colorItemBgActive: controlItemBgActive, - colorItemBgSelected: controlItemBgActive, + colorItemBgSelected: controlItemBgActiveHover, colorItemBgSelectedHorizontal: 'transparent', - colorActiveBarWidth: lineWidthBold + lineWidth, + colorActiveBarWidth: 0, colorActiveBarHeight: lineWidthBold, colorActiveBarBorderSize: lineWidth, @@ -511,6 +529,8 @@ export default (prefixCls: string, injectStyle: boolean): UseComponentStyleResul colorDangerItemTextSelected: colorError, colorDangerItemBgActive: colorErrorBg, colorDangerItemBgSelected: colorErrorBg, + + itemMarginInline: token.marginXXS, }; }, ); diff --git a/components/menu/style/theme.tsx b/components/menu/style/theme.tsx index 6a89e7b612..9ea92e89a0 100644 --- a/components/menu/style/theme.tsx +++ b/components/menu/style/theme.tsx @@ -11,10 +11,10 @@ const getThemeStyle = (token: MenuToken, themeSuffix: string): CSSInterpolation componentCls, colorItemText, colorItemTextSelected, + colorItemTextSelectedHorizontal, colorGroupTitle, colorItemBg, colorSubItemBg, - colorItemBgActive, colorItemBgSelectedHorizontal, colorItemBgSelected, colorActiveBarHeight, @@ -24,10 +24,12 @@ const getThemeStyle = (token: MenuToken, themeSuffix: string): CSSInterpolation motionEaseInOut, motionEaseOut, menuItemPaddingInline, + itemMarginInline, motionDurationFast, colorItemTextHover, lineType, colorSplit, + colorItemBgActive, // Disabled colorItemTextDisabled, @@ -38,6 +40,10 @@ const getThemeStyle = (token: MenuToken, themeSuffix: string): CSSInterpolation colorDangerItemTextSelected, colorDangerItemBgActive, colorDangerItemBgSelected, + + radiusItem, + + colorItemBgHover, } = token; return { @@ -72,9 +78,54 @@ const getThemeStyle = (token: MenuToken, themeSuffix: string): CSSInterpolation }, }, - // Active - [`${componentCls}-item:active, ${componentCls}-submenu-title:active`]: { - background: colorItemBgActive, + [`&:not(${componentCls}-horizontal)`]: { + [`${componentCls}-item:not(${componentCls}-item-selected)`]: { + '&:hover': { + backgroundColor: colorItemBgHover, + }, + + '&:active::before': { + content: '""', + position: 'absolute', + insetInlineStart: 0, + top: 0, + width: `100%`, + height: '100%', + flex: 1, + borderRadius: radiusItem, + backgroundColor: colorItemBgActive, + transition: `background-color ${motionDurationFast}`, + }, + }, + [`${componentCls}-submenu-title`]: { + '&::before': { + content: '""', + position: 'absolute', + insetInlineStart: itemMarginInline, + top: 0, + width: `calc(100% - ${itemMarginInline * 2}px)`, + height: '100%', + borderRadius: radiusItem, + backgroundColor: 'transparent', + transition: `background-color ${motionDurationFast}`, + }, + + '&:hover::before': { + backgroundColor: colorItemBgHover, + }, + + '&:active::after': { + content: '""', + position: 'absolute', + insetInlineStart: itemMarginInline, + top: 0, + width: `calc(100% - ${itemMarginInline * 2}px)`, + height: '100%', + borderRadius: radiusItem, + backgroundColor: colorItemBgActive, + transition: `background-color ${motionDurationFast}`, + }, + }, }, // Danger - only Item has @@ -152,18 +203,18 @@ const getThemeStyle = (token: MenuToken, themeSuffix: string): CSSInterpolation }, [`&:hover, &-active, &-open`]: { - color: colorItemTextSelected, + color: colorItemTextSelectedHorizontal, '&::after': { borderWidth: `${colorActiveBarHeight}px`, - borderBottomColor: colorItemTextSelected, + borderBottomColor: colorItemTextSelectedHorizontal, }, }, [`&-selected`]: { - color: colorItemTextSelected, + color: colorItemTextSelectedHorizontal, backgroundColor: colorItemBgSelectedHorizontal, '&::after': { borderWidth: `${colorActiveBarHeight}px`, - borderBottomColor: colorItemTextSelected, + borderBottomColor: colorItemTextSelectedHorizontal, }, }, }, @@ -185,11 +236,12 @@ const getThemeStyle = (token: MenuToken, themeSuffix: string): CSSInterpolation }, // Item - [`${componentCls}-item, ${componentCls}-submenu-title`]: colorActiveBarBorderSize - ? { - width: `calc(100% + ${colorActiveBarBorderSize}px)`, - } - : {}, + [`${componentCls}-item, ${componentCls}-submenu-title`]: + colorActiveBarBorderSize && colorActiveBarWidth + ? { + width: `calc(100% + ${colorActiveBarBorderSize}px)`, + } + : {}, [`${componentCls}-item`]: { position: 'relative', diff --git a/components/menu/style/vertical.tsx b/components/menu/style/vertical.tsx index 858f289e7b..70486199b9 100644 --- a/components/menu/style/vertical.tsx +++ b/components/menu/style/vertical.tsx @@ -3,8 +3,15 @@ import type { MenuToken } from '.'; import type { GenerateStyle } from '../../theme'; const getVerticalInlineStyle: GenerateStyle = token => { - const { componentCls, menuItemHeight, menuItemMarginInline, padding, menuArrowSize, fontSize } = - token; + const { + componentCls, + menuItemHeight, + menuItemMarginInline, + itemMarginInline, + padding, + menuArrowSize, + fontSize, + } = token; const paddingWithArrow = menuArrowSize + fontSize; @@ -16,12 +23,21 @@ const getVerticalInlineStyle: GenerateStyle = token => { [`${componentCls}-item, ${componentCls}-submenu-title`]: { height: menuItemHeight, lineHeight: `${menuItemHeight}px`, - marginBlock: menuItemMarginInline, paddingInline: padding, overflow: 'hidden', textOverflow: 'ellipsis', }, + [`${componentCls}-item`]: { + marginInline: itemMarginInline, + marginBlock: menuItemMarginInline, + width: `calc(100% - ${itemMarginInline * 2}px)`, + }, + + [`${componentCls}-submenu-title`]: { + marginBlock: menuItemMarginInline, + }, + // disable margin collapsed [`${componentCls}-submenu`]: { paddingBottom: 0.02, diff --git a/scripts/tmp-mv-dumi-site.js b/scripts/tmp-mv-dumi-site.js index e138911860..a0e6c4ad8d 100755 --- a/scripts/tmp-mv-dumi-site.js +++ b/scripts/tmp-mv-dumi-site.js @@ -9,8 +9,7 @@ const path = require('path'); const tmpFolder = `~demo`; -glob('components/*/demo/*', (er, files) => { - // console.log(files); +glob('components/**/*.md', (er, files) => { fs.ensureDirSync(tmpFolder); fs.emptyDirSync(tmpFolder);