fix(menu): menu-title-content style (#51425)

* fix(dropdown): dropdown menu title content style

* chore: update rc-mentions to version 2.17.0 and rc-tabs to version 15.4.0

* test: add extra style debug

* test: snap

* test: snap

* Refactor menu demo: remove extra-style-debug component and rename extra-style-debug files to extra-style

* Refactor menu demo: remove extra-style-debug component and rename extra-style-debug files to extra-style

* Refactor dropdown and menu styles: Add width to extra-style elements

* test: snap

* fix: Add Space component to menu demo

The Space component was missing from the import statement in the menu demo file. This caused a compilation error. The fix adds the Space component to the import statement, resolving the issue.

Refactor the menu demo to use Space component for vertical spacing between menus. This improves the visual layout and readability of the menus.

Fixes #51492

* test: snap

* refactor: Update dropdown and menu title content class names

---------

Co-authored-by: afc163 <afc163@gmail.com>
This commit is contained in:
ice 2024-11-07 20:00:06 +08:00 committed by GitHub
parent d6f1b1e063
commit 6a62d9e7ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 616 additions and 17 deletions

View File

@ -3981,7 +3981,7 @@ Array [
tabindex="-1"
>
<span
class="ant-dropdown-menu-title-content"
class="ant-dropdown-menu-title-content ant-dropdown-menu-title-content-with-extra"
>
Profile
<span
@ -4015,7 +4015,7 @@ Array [
tabindex="-1"
>
<span
class="ant-dropdown-menu-title-content"
class="ant-dropdown-menu-title-content ant-dropdown-menu-title-content-with-extra"
>
Billing
<span
@ -4068,7 +4068,7 @@ Array [
</svg>
</span>
<span
class="ant-dropdown-menu-title-content"
class="ant-dropdown-menu-title-content ant-dropdown-menu-title-content-with-extra"
>
Settings
<span

View File

@ -360,6 +360,9 @@ describe('Dropdown', () => {
</Dropdown>,
);
expect(
container.querySelector('.ant-dropdown-menu-title-content-with-extra'),
).toBeInTheDocument();
expect(container.querySelector('.ant-dropdown-menu-item-extra')?.textContent).toBe(text);
});
});

View File

@ -242,10 +242,14 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
},
[`${menuCls}-title-content`]: {
display: 'flex',
alignItems: 'center',
flex: 'auto',
'&-with-extra': {
display: 'inline-flex',
alignItems: 'center',
width: '100%',
},
'> a': {
color: 'inherit',
transition: `all ${motionDurationMid}`,

View File

@ -36,7 +36,7 @@ type GenericComponent = Omit<MenuItemComponent, ''> &
) => ReturnType<MenuItemComponent>);
const MenuItem: GenericComponent = (props) => {
const { className, children, icon, title, danger } = props;
const { className, children, icon, title, danger, extra } = props;
const {
prefixCls,
firstLevel,
@ -47,7 +47,15 @@ const MenuItem: GenericComponent = (props) => {
const renderItemChildren = (inlineCollapsed: boolean) => {
const label = (children as React.ReactNode[])?.[0];
const wrapNode = <span className={`${prefixCls}-title-content`}>{children}</span>;
const wrapNode = (
<span
className={classNames(`${prefixCls}-title-content`, {
[`${prefixCls}-title-content-with-extra`]: !!extra || extra === 0,
})}
>
{children}
</span>
);
// inline-collapsed.md demo 依赖 span 来隐藏文字,有 icon 属性,则内部包裹一个 span
// ref: https://github.com/ant-design/ant-design/pull/23456
if (!icon || (React.isValidElement(children) && children.type === 'span')) {

View File

@ -1700,6 +1700,357 @@ exports[`renders components/menu/demo/component-token.tsx extend context correct
exports[`renders components/menu/demo/component-token.tsx extend context correctly 2`] = `[]`;
exports[`renders components/menu/demo/extra-style.tsx extend context correctly 1`] = `
<div
class="ant-space ant-space-vertical ant-space-gap-row-small ant-space-gap-col-small"
>
<div
class="ant-space-item"
>
<ul
class="ant-menu ant-menu-root ant-menu-inline ant-menu-light"
data-menu-list="true"
role="menu"
style="width: 256px;"
tabindex="0"
>
<li
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected"
role="none"
>
<div
aria-controls="rc-menu-uuid-test-sub1-popup"
aria-expanded="true"
aria-haspopup="true"
class="ant-menu-submenu-title"
data-menu-id="rc-menu-uuid-test-sub1"
role="menuitem"
style="padding-left: 24px;"
tabindex="-1"
>
<span
aria-label="mail"
class="anticon anticon-mail ant-menu-item-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="mail"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M928 160H96c-17.7 0-32 14.3-32 32v640c0 17.7 14.3 32 32 32h832c17.7 0 32-14.3 32-32V192c0-17.7-14.3-32-32-32zm-40 110.8V792H136V270.8l-27.6-21.5 39.3-50.5 42.8 33.3h643.1l42.8-33.3 39.3 50.5-27.7 21.5zM833.6 232L512 482 190.4 232l-42.8-33.3-39.3 50.5 27.6 21.5 341.6 265.6a55.99 55.99 0 0068.7 0L888 270.8l27.6-21.5-39.3-50.5-42.7 33.2z"
/>
</svg>
</span>
<span
class="ant-menu-title-content"
>
Navigation One
</span>
<i
class="ant-menu-submenu-arrow"
/>
</div>
<div
class="ant-menu-submenu ant-menu-submenu-popup ant-menu ant-menu-light"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<ul
class="ant-menu ant-menu-sub ant-menu-inline"
data-menu-list="true"
id="rc-menu-uuid-test-sub1-popup"
role="menu"
>
<li
class="ant-menu-item ant-menu-item-selected ant-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-1"
role="menuitem"
style="padding-left: 48px;"
tabindex="-1"
>
<span
class="ant-menu-title-content"
>
<div
class="ant-flex ant-flex-justify-space-between"
>
<span>
Option 1
</span>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</div>
</span>
</li>
<div
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-menu-inline-collapsed-tooltip ant-tooltip-placement-right"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; top: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
/>
</div>
</div>
<li
class="ant-menu-item"
data-menu-id="rc-menu-uuid-test-2"
role="menuitem"
style="padding-left: 48px;"
tabindex="-1"
>
<span
class="ant-menu-title-content ant-menu-title-content-with-extra"
>
Option 2
<span
class="ant-menu-item-extra"
>
⌘P
</span>
</span>
</li>
<div
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-menu-inline-collapsed-tooltip ant-tooltip-placement-right"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; top: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
/>
</div>
</div>
</ul>
</div>
<ul
class="ant-menu ant-menu-sub ant-menu-inline"
data-menu-list="true"
id="rc-menu-uuid-test-sub1-popup"
role="menu"
>
<li
class="ant-menu-item ant-menu-item-selected ant-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-1"
role="menuitem"
style="padding-left: 48px;"
tabindex="-1"
>
<span
class="ant-menu-title-content"
>
<div
class="ant-flex ant-flex-justify-space-between"
>
<span>
Option 1
</span>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</div>
</span>
</li>
<div
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-menu-inline-collapsed-tooltip ant-tooltip-placement-right"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; top: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
/>
</div>
</div>
<li
class="ant-menu-item"
data-menu-id="rc-menu-uuid-test-2"
role="menuitem"
style="padding-left: 48px;"
tabindex="-1"
>
<span
class="ant-menu-title-content ant-menu-title-content-with-extra"
>
Option 2
<span
class="ant-menu-item-extra"
>
⌘P
</span>
</span>
</li>
<div
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-menu-inline-collapsed-tooltip ant-tooltip-placement-right"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; top: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
/>
</div>
</div>
</ul>
</li>
</ul>
<div
aria-hidden="true"
style="display: none;"
/>
</div>
<div
class="ant-space-item"
>
<ul
class="ant-menu ant-menu-root ant-menu-vertical ant-menu-dark"
data-menu-list="true"
role="menu"
style="width: 256px;"
tabindex="0"
>
<li
class="ant-menu-item"
data-menu-id="rc-menu-uuid-test-1"
role="menuitem"
tabindex="-1"
>
<span
class="ant-menu-title-content ant-menu-title-content-with-extra"
>
Users
<span
class="ant-menu-item-extra"
>
⌘U
</span>
</span>
</li>
<div
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-menu-inline-collapsed-tooltip ant-tooltip-placement-right"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; top: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
/>
</div>
</div>
<li
class="ant-menu-item"
data-menu-id="rc-menu-uuid-test-2"
role="menuitem"
tabindex="-1"
>
<span
class="ant-menu-title-content ant-menu-title-content-with-extra"
>
Profile
<span
class="ant-menu-item-extra"
>
⌘P
</span>
</span>
</li>
<div
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-menu-inline-collapsed-tooltip ant-tooltip-placement-right"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; top: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
/>
</div>
</div>
</ul>
<div
aria-hidden="true"
style="display: none;"
/>
</div>
</div>
`;
exports[`renders components/menu/demo/extra-style.tsx extend context correctly 2`] = `[]`;
exports[`renders components/menu/demo/horizontal.tsx extend context correctly 1`] = `
Array [
<ul

View File

@ -780,6 +780,178 @@ exports[`renders components/menu/demo/component-token.tsx correctly 1`] = `
</div>
`;
exports[`renders components/menu/demo/extra-style.tsx correctly 1`] = `
<div
class="ant-space ant-space-vertical ant-space-gap-row-small ant-space-gap-col-small"
>
<div
class="ant-space-item"
>
<ul
class="ant-menu ant-menu-root ant-menu-inline ant-menu-light"
data-menu-list="true"
role="menu"
style="width:256px"
tabindex="0"
>
<li
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open"
role="none"
>
<div
aria-expanded="true"
aria-haspopup="true"
class="ant-menu-submenu-title"
role="menuitem"
style="padding-left:24px"
tabindex="-1"
>
<span
aria-label="mail"
class="anticon anticon-mail ant-menu-item-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="mail"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M928 160H96c-17.7 0-32 14.3-32 32v640c0 17.7 14.3 32 32 32h832c17.7 0 32-14.3 32-32V192c0-17.7-14.3-32-32-32zm-40 110.8V792H136V270.8l-27.6-21.5 39.3-50.5 42.8 33.3h643.1l42.8-33.3 39.3 50.5-27.7 21.5zM833.6 232L512 482 190.4 232l-42.8-33.3-39.3 50.5 27.6 21.5 341.6 265.6a55.99 55.99 0 0068.7 0L888 270.8l27.6-21.5-39.3-50.5-42.7 33.2z"
/>
</svg>
</span>
<span
class="ant-menu-title-content"
>
Navigation One
</span>
<i
class="ant-menu-submenu-arrow"
/>
</div>
<ul
class="ant-menu ant-menu-sub ant-menu-inline"
data-menu-list="true"
role="menu"
>
<li
class="ant-menu-item ant-menu-item-selected ant-menu-item-only-child"
role="menuitem"
style="padding-left:48px"
tabindex="-1"
>
<span
class="ant-menu-title-content"
>
<div
class="ant-flex ant-flex-justify-space-between"
>
<span>
Option 1
</span>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</div>
</span>
</li>
<li
class="ant-menu-item"
role="menuitem"
style="padding-left:48px"
tabindex="-1"
>
<span
class="ant-menu-title-content ant-menu-title-content-with-extra"
>
Option 2
<span
class="ant-menu-item-extra"
>
⌘P
</span>
</span>
</li>
</ul>
</li>
</ul>
<div
aria-hidden="true"
style="display:none"
/>
</div>
<div
class="ant-space-item"
>
<ul
class="ant-menu ant-menu-root ant-menu-vertical ant-menu-dark"
data-menu-list="true"
role="menu"
style="width:256px"
tabindex="0"
>
<li
class="ant-menu-item"
role="menuitem"
tabindex="-1"
>
<span
class="ant-menu-title-content ant-menu-title-content-with-extra"
>
Users
<span
class="ant-menu-item-extra"
>
⌘U
</span>
</span>
</li>
<li
class="ant-menu-item"
role="menuitem"
tabindex="-1"
>
<span
class="ant-menu-title-content ant-menu-title-content-with-extra"
>
Profile
<span
class="ant-menu-item-extra"
>
⌘P
</span>
</span>
</li>
</ul>
<div
aria-hidden="true"
style="display:none"
/>
</div>
</div>
`;
exports[`renders components/menu/demo/horizontal.tsx correctly 1`] = `
Array [
<ul

View File

@ -1162,6 +1162,7 @@ describe('Menu', () => {
const text = '⌘P';
const { container } = render(<Menu items={[{ label: 'profile', key: '1', extra: text }]} />);
expect(container.querySelector('.ant-menu-title-content-with-extra')).toBeInTheDocument();
expect(container.querySelector('.ant-menu-item-extra')?.textContent).toBe(text);
});
});

View File

@ -0,0 +1,7 @@
## zh-CN
调试使用
## en-US
Debug usage

View File

@ -0,0 +1,50 @@
import React from 'react';
import { DownOutlined, MailOutlined } from '@ant-design/icons';
import type { MenuProps } from 'antd';
import { Flex, Menu, Space } from 'antd';
type MenuItem = Required<MenuProps>['items'][number];
const items1: MenuItem[] = [
{
key: 'sub1',
icon: <MailOutlined />,
label: 'Navigation One',
children: [
{
key: '1',
label: (
<Flex justify="space-between">
<span>Option 1</span>
<DownOutlined />
</Flex>
),
},
{
key: '2',
label: 'Option 2',
extra: '⌘P',
},
],
},
];
const items2: MenuItem[] = [
{ key: '1', label: 'Users', extra: '⌘U' },
{ key: '2', label: 'Profile', extra: '⌘P' },
];
const App: React.FC = () => (
<Space direction="vertical">
<Menu
mode="inline"
defaultOpenKeys={['sub1']}
defaultSelectedKeys={['1']}
style={{ width: 256 }}
items={items1}
/>
<Menu theme="dark" style={{ width: 256 }} items={items2} />
</Space>
);
export default App;

View File

@ -33,6 +33,7 @@ More layouts with navigation: [Layout](/components/layout).
<code src="./demo/style-debug.tsx" debug>Style debug</code>
<code src="./demo/menu-v4.tsx" debug>Menu v4</code>
<code src="./demo/component-token.tsx" debug>Component Token</code>
<code src="./demo/extra-style.tsx" debug>Extra Style debug</code>
## API

View File

@ -34,6 +34,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*Vn4XSqJFAxcAAA
<code src="./demo/style-debug.tsx" debug>Style debug</code>
<code src="./demo/menu-v4.tsx" debug>v4 版本 Menu</code>
<code src="./demo/component-token.tsx" debug>组件 Token</code>
<code src="./demo/extra-style.tsx" debug>Extra Style debug</code>
## API

View File

@ -635,12 +635,12 @@ const getBaseStyle: GenerateStyle<MenuToken> = (token) => {
},
[`${componentCls}-title-content`]: {
display: 'inline-flex',
alignItems: 'center',
transition: `color ${motionDurationSlow}`,
'> a:first-child': {
flexGrow: 1,
'&-with-extra': {
display: 'inline-flex',
alignItems: 'center',
width: '100%',
},
// https://github.com/ant-design/ant-design/issues/41143
@ -653,7 +653,6 @@ const getBaseStyle: GenerateStyle<MenuToken> = (token) => {
marginInlineStart: 'auto',
paddingInlineStart: token.padding,
fontSize: token.fontSizeSM,
color: token.colorTextDescription,
},
},

View File

@ -61,8 +61,10 @@ const getThemeStyle = (token: MenuToken, themeSuffix: string): CSSInterpolation
},
// ======================== Item ========================
[`${componentCls}-item-group-title`]: {
color: groupTitleColor,
[`${componentCls}-item`]: {
'&-group-title, &-extra': {
color: groupTitleColor,
},
},
[`${componentCls}-submenu-selected`]: {

View File

@ -130,8 +130,8 @@
"rc-image": "~7.11.0",
"rc-input": "~1.6.3",
"rc-input-number": "~9.2.0",
"rc-mentions": "~2.16.1",
"rc-menu": "~9.15.1",
"rc-mentions": "~2.17.0",
"rc-menu": "~9.16.0",
"rc-motion": "^2.9.3",
"rc-notification": "~5.6.2",
"rc-pagination": "~4.3.0",
@ -145,7 +145,7 @@
"rc-steps": "~6.0.1",
"rc-switch": "~4.1.0",
"rc-table": "~7.47.5",
"rc-tabs": "~15.3.0",
"rc-tabs": "~15.4.0",
"rc-textarea": "~1.8.2",
"rc-tooltip": "~6.2.1",
"rc-tree": "~5.9.0",