feat: Menu.Item support icon (#23629)

* feat: Menu.Item support icon

* docs: update menu item usage

* docs: remove span wrap,when use icon

* fix: Collapsed depends on the span

*  fix demo snapshot

* do not wrap children when it is span

* Menu.SubMenu support icon prop

* fix sub menu title

* fix eslint

* update dropdown demo

* fix extra icon attribute on li

Co-authored-by: MengZhaoFly <1424254461@qq.com>
This commit is contained in:
偏右 2020-04-26 23:16:15 +08:00 committed by GitHub
parent c53329a27d
commit 8934bbfffa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 724 additions and 807 deletions

View File

@ -29,16 +29,13 @@ function handleMenuClick(e) {
const menu = (
<Menu onClick={handleMenuClick}>
<Menu.Item key="1">
<UserOutlined />
<Menu.Item key="1" icon={<UserOutlined />}>
1st menu item
</Menu.Item>
<Menu.Item key="2">
<UserOutlined />
<Menu.Item key="2" icon={<UserOutlined />}>
2nd menu item
</Menu.Item>
<Menu.Item key="3">
<UserOutlined />
<Menu.Item key="3" icon={<UserOutlined />}>
3rd item
</Menu.Item>
</Menu>

View File

@ -30,15 +30,7 @@ const menu = (
<Menu.Item key="01">Option 0</Menu.Item>
<Menu.Item key="02">Option 0</Menu.Item>
</Menu.ItemGroup>
<SubMenu
key="sub1"
title={
<span>
<MailOutlined />
<span>Navigation One</span>
</span>
}
>
<SubMenu key="sub1" icon={<MailOutlined />} title="Navigation One">
<Menu.ItemGroup key="g1" title="Item 1">
<Menu.Item key="1">Option 1</Menu.Item>
<Menu.Item key="2">Option 2</Menu.Item>
@ -48,15 +40,7 @@ const menu = (
<Menu.Item key="4">Option 4</Menu.Item>
</Menu.ItemGroup>
</SubMenu>
<SubMenu
key="sub2"
title={
<span>
<AppstoreOutlined />
<span>Navigation Two</span>
</span>
}
>
<SubMenu key="sub2" icon={<AppstoreOutlined />} title="Navigation Two">
<Menu.Item key="5">Option 5</Menu.Item>
<Menu.Item key="6">Option 6</Menu.Item>
<SubMenu key="sub3" title="Submenu">
@ -64,15 +48,7 @@ const menu = (
<Menu.Item key="8">Option 8</Menu.Item>
</SubMenu>
</SubMenu>
<SubMenu
key="sub4"
title={
<span>
<SettingOutlined />
<span>Navigation Three</span>
</span>
}
>
<SubMenu key="sub4" icon={<SettingOutlined />} title="Navigation Three">
<Menu.Item key="9">Option 9</Menu.Item>
<Menu.Item key="10">Option 10</Menu.Item>
<Menu.Item key="11">Option 11</Menu.Item>

View File

@ -42,42 +42,22 @@ class SiderDemo extends React.Component {
<Sider trigger={null} collapsible collapsed={this.state.collapsed}>
<div className="logo" />
<Menu theme="dark" mode="inline" defaultSelectedKeys={['3']} defaultOpenKeys={['sub1']}>
<Menu.Item key="1">
<PieChartOutlined />
<span>Option 1</span>
<Menu.Item key="1" icon={<PieChartOutlined />}>
Option 1
</Menu.Item>
<Menu.Item key="2">
<DesktopOutlined />
<span>Option 2</span>
<Menu.Item key="2" icon={<DesktopOutlined />}>
Option 2
</Menu.Item>
<SubMenu
key="sub1"
title={
<span>
<UserOutlined />
<span>User</span>
</span>
}
>
<SubMenu key="sub1" icon={<UserOutlined />} title="User">
<Menu.Item key="3">Tom</Menu.Item>
<Menu.Item key="4">Bill</Menu.Item>
<Menu.Item key="5">Alex</Menu.Item>
</SubMenu>
<SubMenu
key="sub2"
title={
<span>
<TeamOutlined />
<span>Team</span>
</span>
}
>
<SubMenu key="sub2" icon={<TeamOutlined />} title="Team">
<Menu.Item key="6">Team 1</Menu.Item>
<Menu.Item key="8">Team 2</Menu.Item>
</SubMenu>
<Menu.Item key="9">
<FileOutlined />
</Menu.Item>
<Menu.Item key="9" icon={<FileOutlined />} />
</Menu>
</Sider>
<Layout>

View File

@ -15,6 +15,7 @@ export interface MenuItemProps
rootPrefixCls?: string;
disabled?: boolean;
level?: number;
icon?: React.ReactNode;
title?: React.ReactNode;
children?: React.ReactNode;
className?: string;
@ -37,9 +38,19 @@ export default class MenuItem extends React.Component<MenuItemProps> {
this.menuItem = menuItem;
};
renderItemChildren() {
const { icon, children } = this.props;
// 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')) {
return children;
}
return <span>{children}</span>;
}
renderItem = ({ siderCollapsed }: SiderContextProps) => {
const { level, className, children, rootPrefixCls } = this.props;
const { title, ...rest } = this.props;
const { title, icon, ...rest } = this.props;
return (
<MenuContext.Consumer>
@ -60,6 +71,7 @@ export default class MenuItem extends React.Component<MenuItemProps> {
// ref: https://github.com/ant-design/ant-design/issues/16742
tooltipProps.visible = false;
}
const childrenLength = toArray(children).length;
return (
<Tooltip
{...tooltipProps}
@ -69,11 +81,15 @@ export default class MenuItem extends React.Component<MenuItemProps> {
<Item
{...rest}
className={classNames(className, {
[`${rootPrefixCls}-item-only-child`]: toArray(children).length === 1,
[`${rootPrefixCls}-item-only-child`]:
(icon ? childrenLength + 1 : childrenLength) === 1,
})}
title={title}
ref={this.saveMenuItem}
/>
>
{icon}
{this.renderItemChildren()}
</Item>
</Tooltip>
);
}}

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import * as PropTypes from 'prop-types';
import { SubMenu as RcSubMenu } from 'rc-menu';
import classNames from 'classnames';
import omit from 'omit.js';
import MenuContext, { MenuContextProps } from './MenuContext';
interface TitleEventEntity {
@ -15,6 +15,7 @@ export interface SubMenuProps {
className?: string;
disabled?: boolean;
title?: React.ReactNode;
icon?: React.ReactNode;
style?: React.CSSProperties;
onTitleClick?: (e: TitleEventEntity) => void;
onTitleMouseEnter?: (e: TitleEventEntity) => void;
@ -41,13 +42,30 @@ class SubMenu extends React.Component<SubMenuProps, any> {
this.subMenu = subMenu;
};
renderTitle() {
const { icon, title } = this.props;
if (!icon) {
return title;
}
// inline-collapsed.md demo 依赖 span 来隐藏文字,有 icon 属性,则内部包裹一个 span
// ref: https://github.com/ant-design/ant-design/pull/23456
const titleIsSpan = React.isValidElement(title) && title.type === 'span';
return (
<>
{icon}
{titleIsSpan ? title : <span>{title}</span>}
</>
);
}
render() {
const { rootPrefixCls, popupClassName } = this.props;
return (
<MenuContext.Consumer>
{({ antdMenuTheme }: MenuContextProps) => (
<RcSubMenu
{...this.props}
{...omit(this.props, ['icon'])}
title={this.renderTitle()}
ref={this.saveSubMenu}
popupClassName={classNames(
rootPrefixCls,

View File

@ -48,7 +48,9 @@ exports[`renders ./components/menu/demo/horizontal.md correctly 1`] = `
/>
</svg>
</span>
<span>
Navigation One
</span>
</li>
<li
class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu"
@ -94,7 +96,9 @@ exports[`renders ./components/menu/demo/horizontal.md correctly 1`] = `
/>
</svg>
</span>
<span>
Navigation Two
</span>
</li>
<li
class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu"
@ -145,7 +149,9 @@ exports[`renders ./components/menu/demo/horizontal.md correctly 1`] = `
/>
</svg>
</span>
<span>
Navigation Three - Submenu
</span>
<i
class="ant-menu-submenu-arrow"
/>
@ -325,7 +331,6 @@ exports[`renders ./components/menu/demo/inline.md correctly 1`] = `
role="button"
style="padding-left:24px"
>
<span>
<span
aria-label="appstore"
class="anticon anticon-appstore"
@ -349,7 +354,6 @@ exports[`renders ./components/menu/demo/inline.md correctly 1`] = `
<span>
Navigation Two
</span>
</span>
<i
class="ant-menu-submenu-arrow"
/>
@ -534,7 +538,6 @@ exports[`renders ./components/menu/demo/inline-collapsed.md correctly 1`] = `
role="button"
style="padding-left:24px"
>
<span>
<span
aria-label="mail"
class="anticon anticon-mail"
@ -558,7 +561,6 @@ exports[`renders ./components/menu/demo/inline-collapsed.md correctly 1`] = `
<span>
Navigation One
</span>
</span>
<i
class="ant-menu-submenu-arrow"
/>
@ -609,7 +611,6 @@ exports[`renders ./components/menu/demo/inline-collapsed.md correctly 1`] = `
role="button"
style="padding-left:24px"
>
<span>
<span
aria-label="appstore"
class="anticon anticon-appstore"
@ -633,7 +634,6 @@ exports[`renders ./components/menu/demo/inline-collapsed.md correctly 1`] = `
<span>
Navigation Two
</span>
</span>
<i
class="ant-menu-submenu-arrow"
/>
@ -737,7 +737,6 @@ exports[`renders ./components/menu/demo/sider-current.md correctly 1`] = `
role="button"
style="padding-left:24px"
>
<span>
<span
aria-label="appstore"
class="anticon anticon-appstore"
@ -761,7 +760,6 @@ exports[`renders ./components/menu/demo/sider-current.md correctly 1`] = `
<span>
Navigation Two
</span>
</span>
<i
class="ant-menu-submenu-arrow"
/>
@ -779,7 +777,6 @@ exports[`renders ./components/menu/demo/sider-current.md correctly 1`] = `
role="button"
style="padding-left:24px"
>
<span>
<span
aria-label="setting"
class="anticon anticon-setting"
@ -803,7 +800,6 @@ exports[`renders ./components/menu/demo/sider-current.md correctly 1`] = `
<span>
Navigation Three
</span>
</span>
<i
class="ant-menu-submenu-arrow"
/>
@ -814,7 +810,7 @@ exports[`renders ./components/menu/demo/sider-current.md correctly 1`] = `
`;
exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
<div>
Array [
<button
aria-checked="false"
class="ant-switch"
@ -824,12 +820,12 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
<span
class="ant-switch-inner"
/>
</button>
Change Mode
<span
class="ant-divider"
style="margin:0 1em"
/>
</button>,
" Change Mode",
<div
class="ant-divider ant-divider-vertical"
role="separator"
/>,
<button
aria-checked="false"
class="ant-switch"
@ -839,10 +835,10 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
<span
class="ant-switch-inner"
/>
</button>
Change Style
<br />
<br />
</button>,
" Change Style",
<br />,
<br />,
<ul
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
role="menu"
@ -873,7 +869,9 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
/>
</svg>
</span>
<span>
Navigation One
</span>
</li>
<li
class="ant-menu-item"
@ -900,7 +898,9 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
/>
</svg>
</span>
<span>
Navigation Two
</span>
</li>
<li
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open"
@ -914,7 +914,6 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
role="button"
style="padding-left:24px"
>
<span>
<span
aria-label="appstore"
class="anticon anticon-appstore"
@ -936,8 +935,7 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
</svg>
</span>
<span>
Navigation Three
</span>
Navigation Two
</span>
<i
class="ant-menu-submenu-arrow"
@ -994,7 +992,6 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
role="button"
style="padding-left:24px"
>
<span>
<span
aria-label="setting"
class="anticon anticon-setting"
@ -1016,8 +1013,7 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
</svg>
</span>
<span>
Navigation Four
</span>
Navigation Three
</span>
<i
class="ant-menu-submenu-arrow"
@ -1025,12 +1021,12 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
</div>
<div />
</li>
</ul>
</div>
</ul>,
]
`;
exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
<div>
Array [
<button
aria-checked="true"
checked=""
@ -1043,9 +1039,9 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
>
Dark
</span>
</button>
<br />
<br />
</button>,
<br />,
<br />,
<ul
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
role="menu"
@ -1063,7 +1059,6 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
role="button"
style="padding-left:24px"
>
<span>
<span
aria-label="mail"
class="anticon anticon-mail"
@ -1087,7 +1082,6 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
<span>
Navigation One
</span>
</span>
<i
class="ant-menu-submenu-arrow"
/>
@ -1138,7 +1132,6 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
role="button"
style="padding-left:24px"
>
<span>
<span
aria-label="appstore"
class="anticon anticon-appstore"
@ -1162,7 +1155,6 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
<span>
Navigation Two
</span>
</span>
<i
class="ant-menu-submenu-arrow"
/>
@ -1180,7 +1172,6 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
role="button"
style="padding-left:24px"
>
<span>
<span
aria-label="setting"
class="anticon anticon-setting"
@ -1204,15 +1195,14 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
<span>
Navigation Three
</span>
</span>
<i
class="ant-menu-submenu-arrow"
/>
</div>
<div />
</li>
</ul>
</div>
</ul>,
]
`;
exports[`renders ./components/menu/demo/vertical.md correctly 1`] = `
@ -1231,7 +1221,6 @@ exports[`renders ./components/menu/demo/vertical.md correctly 1`] = `
class="ant-menu-submenu-title"
role="button"
>
<span>
<span
aria-label="mail"
class="anticon anticon-mail"
@ -1255,7 +1244,6 @@ exports[`renders ./components/menu/demo/vertical.md correctly 1`] = `
<span>
Navigation One
</span>
</span>
<i
class="ant-menu-submenu-arrow"
/>
@ -1311,7 +1299,6 @@ exports[`renders ./components/menu/demo/vertical.md correctly 1`] = `
class="ant-menu-submenu-title"
role="button"
>
<span>
<span
aria-label="setting"
class="anticon anticon-setting"
@ -1335,7 +1322,6 @@ exports[`renders ./components/menu/demo/vertical.md correctly 1`] = `
<span>
Navigation Three
</span>
</span>
<i
class="ant-menu-submenu-arrow"
/>

View File

@ -1,5 +1,145 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Menu Menu.Item with icon children auto wrap span 1`] = `
<ul
class="ant-menu ant-menu-light ant-menu-root ant-menu-vertical"
role="menu"
>
<li
class="ant-menu-item"
role="menuitem"
>
<span
aria-label="mail"
class="anticon anticon-mail"
role="img"
>
<svg
aria-hidden="true"
class=""
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>
Navigation One
</span>
</li>
<li
class="ant-menu-item"
role="menuitem"
>
<span
aria-label="mail"
class="anticon anticon-mail"
role="img"
>
<svg
aria-hidden="true"
class=""
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>
Navigation One
</span>
</li>
<li
class="ant-menu-submenu ant-menu-submenu-vertical"
role="menuitem"
>
<div
aria-expanded="false"
aria-haspopup="true"
class="ant-menu-submenu-title"
role="button"
>
<span
aria-label="mail"
class="anticon anticon-mail"
role="img"
>
<svg
aria-hidden="true"
class=""
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>
Navigation One
</span>
<i
class="ant-menu-submenu-arrow"
/>
</div>
</li>
<li
class="ant-menu-submenu ant-menu-submenu-vertical"
role="menuitem"
>
<div
aria-expanded="false"
aria-haspopup="true"
class="ant-menu-submenu-title"
role="button"
>
<span
aria-label="mail"
class="anticon anticon-mail"
role="img"
>
<svg
aria-hidden="true"
class=""
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>
Navigation One
</span>
<i
class="ant-menu-submenu-arrow"
/>
</div>
</li>
</ul>
`;
exports[`Menu rtl render component should be rendered correctly in RTL direction 1`] = `
<ul
class="ant-menu ant-menu-light ant-menu-root ant-menu-rtl ant-menu-vertical"
@ -49,6 +189,26 @@ exports[`Menu should controlled collapse work 1`] = `
role="menuitem"
style="padding-left: 24px;"
>
<span
aria-label="pie-chart"
class="anticon anticon-pie-chart"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="pie-chart"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M864 518H506V160c0-4.4-3.6-8-8-8h-26a398.46 398.46 0 00-282.8 117.1 398.19 398.19 0 00-85.7 127.1A397.61 397.61 0 0072 552a398.46 398.46 0 00117.1 282.8c36.7 36.7 79.5 65.6 127.1 85.7A397.61 397.61 0 00472 952a398.46 398.46 0 00282.8-117.1c36.7-36.7 65.6-79.5 85.7-127.1A397.61 397.61 0 00872 552v-26c0-4.4-3.6-8-8-8zM705.7 787.8A331.59 331.59 0 01470.4 884c-88.1-.4-170.9-34.9-233.2-97.2C174.5 724.1 140 640.7 140 552c0-88.7 34.5-172.1 97.2-234.8 54.6-54.6 124.9-87.9 200.8-95.5V586h364.3c-7.7 76.3-41.3 147-96.6 201.8zM952 462.4l-2.6-28.2c-8.5-92.1-49.4-179-115.2-244.6A399.4 399.4 0 00589 74.6L560.7 72c-4.7-.4-8.7 3.2-8.7 7.9V464c0 4.4 3.6 8 8 8l384-1c4.7 0 8.4-4 8-8.6zm-332.2-58.2V147.6a332.24 332.24 0 01166.4 89.8c45.7 45.6 77 103.6 90 166.1l-256.4.7z"
/>
</svg>
</span>
<span>
Option 1
</span>
@ -66,6 +226,26 @@ exports[`Menu should controlled collapse work 2`] = `
role="menuitem"
style="padding-left: 24px;"
>
<span
aria-label="pie-chart"
class="anticon anticon-pie-chart"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="pie-chart"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M864 518H506V160c0-4.4-3.6-8-8-8h-26a398.46 398.46 0 00-282.8 117.1 398.19 398.19 0 00-85.7 127.1A397.61 397.61 0 0072 552a398.46 398.46 0 00117.1 282.8c36.7 36.7 79.5 65.6 127.1 85.7A397.61 397.61 0 00472 952a398.46 398.46 0 00282.8-117.1c36.7-36.7 65.6-79.5 85.7-127.1A397.61 397.61 0 00872 552v-26c0-4.4-3.6-8-8-8zM705.7 787.8A331.59 331.59 0 01470.4 884c-88.1-.4-170.9-34.9-233.2-97.2C174.5 724.1 140 640.7 140 552c0-88.7 34.5-172.1 97.2-234.8 54.6-54.6 124.9-87.9 200.8-95.5V586h364.3c-7.7 76.3-41.3 147-96.6 201.8zM952 462.4l-2.6-28.2c-8.5-92.1-49.4-179-115.2-244.6A399.4 399.4 0 00589 74.6L560.7 72c-4.7-.4-8.7 3.2-8.7 7.9V464c0 4.4 3.6 8 8 8l384-1c4.7 0 8.4-4 8-8.6zm-332.2-58.2V147.6a332.24 332.24 0 01166.4 89.8c45.7 45.6 77 103.6 90 166.1l-256.4.7z"
/>
</svg>
</span>
<span>
Option 1
</span>

View File

@ -1,7 +1,13 @@
import React from 'react';
import { mount } from 'enzyme';
import {
MailOutlined,
InboxOutlined,
AppstoreOutlined,
PieChartOutlined,
UserOutlined,
} from '@ant-design/icons';
import Menu from '..';
import Icon from '../../icon';
import Layout from '../../layout';
import Tooltip from '../../tooltip';
import mountTest from '../../../tests/shared/mountTest';
@ -62,12 +68,7 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(
wrapper
.find('.ant-menu-sub')
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
});
it('should accept defaultOpenKeys in mode inline', () => {
@ -80,12 +81,7 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(
wrapper
.find('.ant-menu-sub')
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
});
it('should accept defaultOpenKeys in mode vertical', () => {
@ -98,12 +94,7 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(
wrapper
.find('.ant-menu-sub')
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
});
it('horizontal', () => {
@ -116,31 +107,17 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
wrapper.setProps({ openKeys: [] });
wrapper.update();
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
wrapper.setProps({ openKeys: ['1'] });
wrapper.update();
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
});
it('inline', () => {
@ -153,31 +130,17 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
wrapper.setProps({ openKeys: [] });
wrapper.update();
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
wrapper.setProps({ openKeys: ['1'] });
wrapper.update();
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
});
it('vertical', () => {
@ -190,31 +153,17 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
wrapper.setProps({ openKeys: [] });
wrapper.update();
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
wrapper.setProps({ openKeys: ['1'] });
wrapper.update();
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
});
// https://github.com/ant-design/ant-design/pulls/4677
@ -243,33 +192,18 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(
wrapper
.find('ul.ant-menu-sub')
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(false);
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
wrapper.setProps({ mode: 'vertical' });
expect(
wrapper
.find('ul.ant-menu-sub')
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(false);
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
wrapper.setProps({ mode: 'inline' });
expect(
wrapper
.find('ul.ant-menu-sub')
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(false);
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
});
it('should always follow openKeys when inlineCollapsed is switched', () => {
const wrapper = mount(
<Menu defaultOpenKeys={['1']} mode="inline">
<Menu.Item key="menu1">
<Icon type="inbox" />
<InboxOutlined />
<span>Option</span>
</Menu.Item>
<SubMenu key="1" title="submenu1">
@ -278,18 +212,8 @@ describe('Menu', () => {
</SubMenu>
</Menu>,
);
expect(
wrapper
.find('ul.ant-menu-sub')
.at(0)
.hasClass('ant-menu-inline'),
).toBe(true);
expect(
wrapper
.find('ul.ant-menu-sub')
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(false);
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-inline')).toBe(true);
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
wrapper.setProps({ inlineCollapsed: true });
// 动画结束后套样式;
@ -297,37 +221,22 @@ describe('Menu', () => {
wrapper.update();
wrapper.simulate('transitionEnd', { propertyName: 'width' });
expect(
wrapper
.find('ul.ant-menu-root')
.at(0)
.hasClass('ant-menu-vertical'),
).toBe(true);
expect(wrapper.find('ul.ant-menu-root').at(0).hasClass('ant-menu-vertical')).toBe(true);
expect(wrapper.find('ul.ant-menu-sub').length).toBe(0);
wrapper.setProps({ inlineCollapsed: false });
jest.runAllTimers();
wrapper.update();
expect(
wrapper
.find('ul.ant-menu-sub')
.at(0)
.hasClass('ant-menu-inline'),
).toBe(true);
expect(
wrapper
.find('ul.ant-menu-sub')
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(false);
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-inline')).toBe(true);
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
});
it('inlineCollapsed should works well when specify a not existed default openKeys', () => {
const wrapper = mount(
<Menu defaultOpenKeys={['not-existed']} mode="inline">
<Menu.Item key="menu1">
<Icon type="inbox" />
<InboxOutlined />
<span>Option</span>
</Menu.Item>
<SubMenu key="1" title="submenu1">
@ -341,36 +250,15 @@ describe('Menu', () => {
jest.runAllTimers();
wrapper.update();
wrapper.simulate('transitionEnd', { propertyName: 'width' });
wrapper
.find('.ant-menu-submenu-title')
.at(0)
.simulate('mouseEnter');
wrapper.find('.ant-menu-submenu-title').at(0).simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
expect(
wrapper
.find('.ant-menu-submenu')
.at(0)
.hasClass('ant-menu-submenu-vertical'),
).toBe(true);
expect(
wrapper
.find('.ant-menu-submenu')
.at(0)
.hasClass('ant-menu-submenu-open'),
).toBe(true);
expect(
wrapper
.find('ul.ant-menu-sub')
.at(0)
.hasClass('ant-menu-vertical'),
).toBe(true);
expect(
wrapper
.find('ul.ant-menu-sub')
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(false);
expect(wrapper.find('.ant-menu-submenu').at(0).hasClass('ant-menu-submenu-vertical')).toBe(
true,
);
expect(wrapper.find('.ant-menu-submenu').at(0).hasClass('ant-menu-submenu-open')).toBe(true);
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-vertical')).toBe(true);
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
});
it('inlineCollapsed Menu.Item Tooltip can be removed', () => {
@ -399,48 +287,12 @@ describe('Menu', () => {
</Menu.Item>
</Menu>,
);
expect(
wrapper
.find(Menu.Item)
.at(0)
.find(Tooltip)
.props().title,
).toBe('item');
expect(
wrapper
.find(Menu.Item)
.at(1)
.find(Tooltip)
.props().title,
).toBe('title');
expect(
wrapper
.find(Menu.Item)
.at(2)
.find(Tooltip)
.props().title,
).toBe('item');
expect(
wrapper
.find(Menu.Item)
.at(3)
.find(Tooltip)
.props().title,
).toBe(null);
expect(
wrapper
.find(Menu.Item)
.at(4)
.find(Tooltip)
.props().title,
).toBe('');
expect(
wrapper
.find(Menu.Item)
.at(4)
.find(Tooltip)
.props().title,
).toBe('');
expect(wrapper.find(Menu.Item).at(0).find(Tooltip).props().title).toBe('item');
expect(wrapper.find(Menu.Item).at(1).find(Tooltip).props().title).toBe('title');
expect(wrapper.find(Menu.Item).at(2).find(Tooltip).props().title).toBe('item');
expect(wrapper.find(Menu.Item).at(3).find(Tooltip).props().title).toBe(null);
expect(wrapper.find(Menu.Item).at(4).find(Tooltip).props().title).toBe('');
expect(wrapper.find(Menu.Item).at(4).find(Tooltip).props().title).toBe('');
});
describe('open submenu when click submenu title', () => {
@ -453,10 +305,7 @@ describe('Menu', () => {
});
const toggleMenu = (wrapper, index, event) => {
wrapper
.find('.ant-menu-submenu-title')
.at(index)
.simulate(event);
wrapper.find('.ant-menu-submenu-title').at(index).simulate(event);
jest.runAllTimers();
wrapper.update();
};
@ -474,21 +323,13 @@ describe('Menu', () => {
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'click');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
toggleMenu(wrapper, 0, 'click');
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(
true,
);
});
it('vertical', () => {
@ -504,21 +345,13 @@ describe('Menu', () => {
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'mouseenter');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
toggleMenu(wrapper, 0, 'mouseleave');
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(
true,
);
});
it('horizontal', () => {
@ -535,21 +368,13 @@ describe('Menu', () => {
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'mouseenter');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).not.toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
toggleMenu(wrapper, 0, 'mouseleave');
expect(
wrapper
.find('.ant-menu-sub')
.hostNodes()
.at(0)
.hasClass('ant-menu-hidden'),
).toBe(true);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(
true,
);
});
});
@ -558,7 +383,7 @@ describe('Menu', () => {
const wrapper = mount(
<Menu mode="inline" inlineCollapsed>
<Menu.Item key="1" title="bamboo lucky">
<Icon type="pie-chart" />
<PieChartOutlined />
<span>
Option 1
<img
@ -600,7 +425,7 @@ describe('Menu', () => {
key="sub1"
title={
<span>
<Icon type="user" />
<UserOutlined />
<span>User</span>
</span>
}
@ -631,10 +456,7 @@ describe('Menu', () => {
<Menu.Item key="test2">Navigation Two</Menu.Item>
</Menu>,
);
wrapper
.find('Menu')
.at(1)
.simulate('mouseenter');
wrapper.find('Menu').at(1).simulate('mouseenter');
expect(onMouseEnter).toHaveBeenCalled();
});
@ -642,12 +464,9 @@ describe('Menu', () => {
it('get correct animation type when switched from inline', () => {
const wrapper = mount(<Menu mode="inline" />);
wrapper.setProps({ mode: 'horizontal' });
expect(
wrapper
.find('InternalMenu')
.instance()
.getOpenMotionProps(''),
).toEqual({ motion: { motionName: '' } });
expect(wrapper.find('InternalMenu').instance().getOpenMotionProps('')).toEqual({
motion: { motionName: '' },
});
});
it('warning if use `openAnimation` as object', () => {
@ -664,22 +483,14 @@ describe('Menu', () => {
it('motion object', () => {
const motion = { test: true };
const wrapper = mount(<Menu motion={motion} />);
expect(
wrapper
.find('InternalMenu')
.instance()
.getOpenMotionProps(''),
).toEqual({ motion });
expect(wrapper.find('InternalMenu').instance().getOpenMotionProps('')).toEqual({ motion });
});
it('legacy openTransitionName', () => {
const wrapper = mount(<Menu openTransitionName="legacy" />);
expect(
wrapper
.find('InternalMenu')
.instance()
.getOpenMotionProps(''),
).toEqual({ openTransitionName: 'legacy' });
expect(wrapper.find('InternalMenu').instance().getOpenMotionProps('')).toEqual({
openTransitionName: 'legacy',
});
});
});
@ -687,11 +498,11 @@ describe('Menu', () => {
const wrapper = mount(
<Menu defaultSelectedKeys={['mail']} defaultOpenKeys={['mail']} mode="horizontal">
<Menu.Item key="mail">
<Icon type="mail" />
<MailOutlined />
Navigation One
</Menu.Item>
<Menu.Item key="app">
<Icon type="appstore" />
<AppstoreOutlined />
Navigation Two
</Menu.Item>
<Menu.Item key="alipay">
@ -701,20 +512,28 @@ describe('Menu', () => {
</Menu.Item>
</Menu>,
);
wrapper
.find('MenuItem')
.first()
.simulate('mouseenter');
wrapper.find('MenuItem').first().simulate('mouseenter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.ant-tooltip-inner').length).toBe(0);
});
it('MenuItem should render icon and icon should be the first child when icon exists', () => {
const wrapper = mount(
<Menu>
<Menu.Item key="mail" icon={<MailOutlined />}>
Navigation One
</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-item .anticon').hasClass('anticon-mail')).toBe(true);
});
it('should controlled collapse work', () => {
const wrapper = mount(
<Menu mode="inline" inlineCollapsed={false}>
<Menu.Item key="1">
<Icon type="pie-chart" />
<PieChartOutlined />
<span>Option 1</span>
</Menu.Item>
</Menu>,
@ -732,7 +551,7 @@ describe('Menu', () => {
const wrapper = mount(
<Menu mode="inline" inlineCollapsed={false}>
<Menu.Item key="1">
<Icon type="pie-chart" />
<PieChartOutlined />
<span>Option 1</span>
</Menu.Item>
</Menu>,
@ -790,10 +609,7 @@ describe('Menu', () => {
</Menu>,
);
expect(wrapper.find('.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 1');
wrapper
.find('.ant-menu-item')
.at(1)
.simulate('click');
wrapper.find('.ant-menu-item').at(1).simulate('click');
expect(wrapper.find('.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 2');
wrapper.setProps({ inlineCollapsed: true });
jest.runAllTimers();
@ -808,4 +624,20 @@ describe('Menu', () => {
expect(wrapper.find('.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 2');
jest.useRealTimers();
});
it('Menu.Item with icon children auto wrap span', () => {
const wrapper = mount(
<Menu>
<Menu.Item key="1" icon={<MailOutlined />}>
Navigation One
</Menu.Item>
<Menu.Item key="2" icon={<MailOutlined />}>
<span>Navigation One</span>
</Menu.Item>
<Menu.SubMenu key="3" icon={<MailOutlined />} title="Navigation One" />
<Menu.SubMenu key="4" icon={<MailOutlined />} title={<span>Navigation One</span>} />
</Menu>,
);
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -34,22 +34,13 @@ class App extends React.Component {
render() {
return (
<Menu onClick={this.handleClick} selectedKeys={[this.state.current]} mode="horizontal">
<Menu.Item key="mail">
<MailOutlined />
<Menu.Item key="mail" icon={<MailOutlined />}>
Navigation One
</Menu.Item>
<Menu.Item key="app" disabled>
<AppstoreOutlined />
<Menu.Item key="app" disabled icon={<AppstoreOutlined />}>
Navigation Two
</Menu.Item>
<SubMenu
title={
<>
<SettingOutlined />
Navigation Three - Submenu
</>
}
>
<SubMenu icon={<SettingOutlined />} title="Navigation Three - Submenu">
<Menu.ItemGroup title="Item 1">
<Menu.Item key="setting:1">Option 1</Menu.Item>
<Menu.Item key="setting:2">Option 2</Menu.Item>

View File

@ -55,41 +55,22 @@ class App extends React.Component {
theme="dark"
inlineCollapsed={this.state.collapsed}
>
<Menu.Item key="1">
<PieChartOutlined />
<span>Option 1</span>
<Menu.Item key="1" icon={<PieChartOutlined />}>
Option 1
</Menu.Item>
<Menu.Item key="2">
<DesktopOutlined />
<span>Option 2</span>
<Menu.Item key="2" icon={<DesktopOutlined />}>
Option 2
</Menu.Item>
<Menu.Item key="3">
<ContainerOutlined />
<span>Option 3</span>
<Menu.Item key="3" icon={<ContainerOutlined />}>
Option 3
</Menu.Item>
<SubMenu
key="sub1"
title={
<span>
<MailOutlined />
<span>Navigation One</span>
</span>
}
>
<SubMenu key="sub1" icon={<MailOutlined />} title="Navigation One">
<Menu.Item key="5">Option 5</Menu.Item>
<Menu.Item key="6">Option 6</Menu.Item>
<Menu.Item key="7">Option 7</Menu.Item>
<Menu.Item key="8">Option 8</Menu.Item>
</SubMenu>
<SubMenu
key="sub2"
title={
<span>
<AppstoreOutlined />
<span>Navigation Two</span>
</span>
}
>
<SubMenu key="sub2" icon={<AppstoreOutlined />} title="Navigation Two">
<Menu.Item key="9">Option 9</Menu.Item>
<Menu.Item key="10">Option 10</Menu.Item>
<SubMenu key="sub3" title="Submenu">

View File

@ -51,15 +51,7 @@ class Sider extends React.Component {
<Menu.Item key="4">Option 4</Menu.Item>
</Menu.ItemGroup>
</SubMenu>
<SubMenu
key="sub2"
title={
<span>
<AppstoreOutlined />
<span>Navigation Two</span>
</span>
}
>
<SubMenu key="sub2" icon={<AppstoreOutlined />} title="Navigation Two">
<Menu.Item key="5">Option 5</Menu.Item>
<Menu.Item key="6">Option 6</Menu.Item>
<SubMenu key="sub3" title="Submenu">

View File

@ -60,15 +60,7 @@ class Sider extends React.Component {
<Menu.Item key="3">Option 3</Menu.Item>
<Menu.Item key="4">Option 4</Menu.Item>
</SubMenu>
<SubMenu
key="sub2"
title={
<span>
<AppstoreOutlined />
<span>Navigation Two</span>
</span>
}
>
<SubMenu key="sub2" icon={<AppstoreOutlined />} title="Navigation Two">
<Menu.Item key="5">Option 5</Menu.Item>
<Menu.Item key="6">Option 6</Menu.Item>
<SubMenu key="sub3" title="Submenu">
@ -76,15 +68,7 @@ class Sider extends React.Component {
<Menu.Item key="8">Option 8</Menu.Item>
</SubMenu>
</SubMenu>
<SubMenu
key="sub4"
title={
<span>
<SettingOutlined />
<span>Navigation Three</span>
</span>
}
>
<SubMenu key="sub4" icon={<SettingOutlined />} title="Navigation Three">
<Menu.Item key="9">Option 9</Menu.Item>
<Menu.Item key="10">Option 10</Menu.Item>
<Menu.Item key="11">Option 11</Menu.Item>

View File

@ -14,7 +14,7 @@ title:
Show the dynamic switching mode (between 'inline' and 'vertical').
```jsx
import { Menu, Switch } from 'antd';
import { Menu, Switch, Divider } from 'antd';
import {
MailOutlined,
CalendarOutlined,
@ -44,9 +44,9 @@ class Sider extends React.Component {
render() {
return (
<div>
<>
<Switch onChange={this.changeMode} /> Change Mode
<span className="ant-divider" style={{ margin: '0 1em' }} />
<Divider type="vertical" />
<Switch onChange={this.changeTheme} /> Change Style
<br />
<br />
@ -57,23 +57,13 @@ class Sider extends React.Component {
mode={this.state.mode}
theme={this.state.theme}
>
<Menu.Item key="1">
<MailOutlined />
<Menu.Item key="1" icon={<MailOutlined />}>
Navigation One
</Menu.Item>
<Menu.Item key="2">
<CalendarOutlined />
<Menu.Item key="2" icon={<CalendarOutlined />}>
Navigation Two
</Menu.Item>
<SubMenu
key="sub1"
title={
<span>
<AppstoreOutlined />
<span>Navigation Three</span>
</span>
}
>
<SubMenu key="sub1" icon={<AppstoreOutlined />} title="Navigation Two">
<Menu.Item key="3">Option 3</Menu.Item>
<Menu.Item key="4">Option 4</Menu.Item>
<SubMenu key="sub1-2" title="Submenu">
@ -81,22 +71,14 @@ class Sider extends React.Component {
<Menu.Item key="6">Option 6</Menu.Item>
</SubMenu>
</SubMenu>
<SubMenu
key="sub2"
title={
<span>
<SettingOutlined />
<span>Navigation Four</span>
</span>
}
>
<SubMenu key="sub2" icon={<SettingOutlined />} title="Navigation Three">
<Menu.Item key="7">Option 7</Menu.Item>
<Menu.Item key="8">Option 8</Menu.Item>
<Menu.Item key="9">Option 9</Menu.Item>
<Menu.Item key="10">Option 10</Menu.Item>
</SubMenu>
</Menu>
</div>
</>
);
}
}

View File

@ -40,7 +40,7 @@ class Sider extends React.Component {
render() {
return (
<div>
<>
<Switch
checked={this.state.theme === 'dark'}
onChange={this.changeTheme}
@ -57,29 +57,13 @@ class Sider extends React.Component {
selectedKeys={[this.state.current]}
mode="inline"
>
<SubMenu
key="sub1"
title={
<span>
<MailOutlined />
<span>Navigation One</span>
</span>
}
>
<SubMenu key="sub1" icon={<MailOutlined />} title="Navigation One">
<Menu.Item key="1">Option 1</Menu.Item>
<Menu.Item key="2">Option 2</Menu.Item>
<Menu.Item key="3">Option 3</Menu.Item>
<Menu.Item key="4">Option 4</Menu.Item>
</SubMenu>
<SubMenu
key="sub2"
title={
<span>
<AppstoreOutlined />
<span>Navigation Two</span>
</span>
}
>
<SubMenu key="sub2" icon={<AppstoreOutlined />} title="Navigation Two">
<Menu.Item key="5">Option 5</Menu.Item>
<Menu.Item key="6">Option 6</Menu.Item>
<SubMenu key="sub3" title="Submenu">
@ -87,22 +71,14 @@ class Sider extends React.Component {
<Menu.Item key="8">Option 8</Menu.Item>
</SubMenu>
</SubMenu>
<SubMenu
key="sub4"
title={
<span>
<SettingOutlined />
<span>Navigation Three</span>
</span>
}
>
<SubMenu key="sub4" icon={<SettingOutlined />} title="Navigation Three">
<Menu.Item key="9">Option 9</Menu.Item>
<Menu.Item key="10">Option 10</Menu.Item>
<Menu.Item key="11">Option 11</Menu.Item>
<Menu.Item key="12">Option 12</Menu.Item>
</SubMenu>
</Menu>
</div>
</>
);
}
}

View File

@ -25,15 +25,7 @@ function handleClick(e) {
ReactDOM.render(
<Menu onClick={handleClick} style={{ width: 256 }} mode="vertical">
<SubMenu
key="sub1"
title={
<span>
<MailOutlined />
<span>Navigation One</span>
</span>
}
>
<SubMenu key="sub1" icon={<MailOutlined />} title="Navigation One">
<Menu.ItemGroup title="Item 1">
<Menu.Item key="1">Option 1</Menu.Item>
<Menu.Item key="2">Option 2</Menu.Item>
@ -59,15 +51,7 @@ ReactDOM.render(
<Menu.Item key="8">Option 8</Menu.Item>
</SubMenu>
</SubMenu>
<SubMenu
key="sub4"
title={
<span>
<SettingOutlined />
<span>Navigation Three</span>
</span>
}
>
<SubMenu key="sub4" icon={<SettingOutlined />} title="Navigation Three">
<Menu.Item key="9">Option 9</Menu.Item>
<Menu.Item key="10">Option 10</Menu.Item>
<Menu.Item key="11">Option 11</Menu.Item>

View File

@ -53,10 +53,30 @@ More layouts with navigation: [Layout](/components/layout).
### Menu.Item
| Param | Description | Type | Default value | Version |
| -------- | ------------------------------------ | ------- | ------------- | ------- |
| -------- | ------------------------------------ | --------- | ------------- | ------- |
| disabled | Whether menu item is disabled | boolean | false | |
| key | Unique ID of the menu item | string | | |
| title | Set display title for collapsed item | string | | |
| icon | icon of the menu item | ReactNode | | 4.2.0 |
> Note: `icon` is a newly added prop in`4.2.0`. For previous versions, please use the following method to define the icon.
>
> ```jsx
> <Menu.Item>
> <PieChartOutlined />
> <span>Option 1</span>
> </Menu.Item>
> <Menu.SubMenu
> title={
> <>
> <PieChartOutlined />
> <span>Option 2</span>
> </>
> }
> >
> ...
> </Menu.SubMenu>
> ```
### Menu.SubMenu
@ -66,7 +86,8 @@ More layouts with navigation: [Layout](/components/layout).
| children | Sub-menus or sub-menu items | Array&lt;MenuItem\|SubMenu> | | |
| disabled | Whether sub-menu is disabled | boolean | false | |
| key | Unique ID of the sub-menu | string | | |
| title | Title of the sub-menu | string\|ReactNode | | |
| title | Title of sub menu | string\|ReactNode | | |
| icon | Icon of sub menu | ReactNode | | 4.2.0 |
| onTitleClick | Callback executed when the sub-menu title is clicked | function({ key, domEvent }) | | |
### Menu.ItemGroup

View File

@ -54,20 +54,41 @@ subtitle: 导航菜单
### Menu.Item
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| -------- | ------------------------ | ------- | ------ | ---- |
| -------- | ------------------------ | --------- | ------ | ----- |
| disabled | 是否禁用 | boolean | false | |
| key | item 的唯一标志 | string | | |
| title | 设置收缩时展示的悬浮标题 | string | | |
| icon | 菜单图标 | ReactNode | | 4.2.0 |
> 注意:`icon` 是 `4.2.0` 新增的属性,之前的版本请使用下面的方式定义图标。
>
> ```jsx
> <Menu.Item>
> <PieChartOutlined />
> <span>Option 1</span>
> </Menu.Item>
> <Menu.SubMenu
> title={
> <>
> <PieChartOutlined />
> <span>Option 2</span>
> </>
> }
> >
> ...
> </Menu.SubMenu>
> ```
### Menu.SubMenu
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| -------------- | -------------- | --------------------------- | ------ | ---- |
| -------------- | -------------- | --------------------------- | ------ | ----- |
| popupClassName | 子菜单样式 | string | | |
| children | 子菜单的菜单项 | Array&lt;MenuItem\|SubMenu> | | |
| disabled | 是否禁用 | boolean | false | |
| key | 唯一标志 | string | | |
| title | 子菜单项值 | string\|ReactNode | | |
| icon | 菜单图标 | ReactNode | | 4.2.0 |
| onTitleClick | 点击子菜单标题 | function({ key, domEvent }) | | |
### Menu.ItemGroup