mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 01:13:58 +08:00
feat: Menu support items
(#34559)
* docs: Update Menu cn doc * chore: update ts def * chore: support convert * docs: more demo * docs: more demo * docs: all menu demos * docs: dropdown demo * docs: dropdown all demos * docs: update demo * test: coverage * docs: more demo * docs: layout demo * docs: all demo * chore: fix ts lint * docs: fix doc * docs: all docs
This commit is contained in:
parent
78705e34f0
commit
a67d39cd6c
@ -97,13 +97,12 @@ const Breadcrumb: BreadcrumbInterface = ({
|
||||
let overlay;
|
||||
if (route.children && route.children.length) {
|
||||
overlay = (
|
||||
<Menu>
|
||||
{route.children.map(child => (
|
||||
<Menu.Item key={child.path || child.breadcrumbName}>
|
||||
{itemRender(child, params, routes, addChildPath(paths, child.path, params))}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
<Menu
|
||||
items={route.children.map(child => ({
|
||||
key: child.path || child.breadcrumbName,
|
||||
label: itemRender(child, params, routes, addChildPath(paths, child.path, params)),
|
||||
}))}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -144,9 +143,7 @@ const Breadcrumb: BreadcrumbInterface = ({
|
||||
|
||||
return (
|
||||
<nav className={breadcrumbClassName} style={style} {...restProps}>
|
||||
<ol>
|
||||
{crumbs}
|
||||
</ol>
|
||||
<ol>{crumbs}</ol>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
@ -17,23 +17,31 @@ Breadcrumbs support drop down menu.
|
||||
import { Breadcrumb, Menu } from 'antd';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">
|
||||
General
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">
|
||||
Layout
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">
|
||||
Navigation
|
||||
</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">
|
||||
General
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">
|
||||
Layout
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">
|
||||
Navigation
|
||||
</a>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -13,19 +13,31 @@ title:
|
||||
|
||||
If you need several buttons, we recommend that you use 1 primary button + n secondary buttons, and if there are more than three operations, you can group some of them into [Dropdown.Button](/components/dropdown/#components-dropdown-demo-dropdown-button).
|
||||
|
||||
```jsx
|
||||
import { Button, Menu, Dropdown } from 'antd';
|
||||
```tsx
|
||||
import { Button, Menu, Dropdown, MenuProps } from 'antd';
|
||||
|
||||
function handleMenuClick(e) {
|
||||
const onMenuClick: MenuProps['onClick'] = e => {
|
||||
console.log('click', e);
|
||||
}
|
||||
};
|
||||
|
||||
const menu = (
|
||||
<Menu onClick={handleMenuClick}>
|
||||
<Menu.Item key="1">1st item</Menu.Item>
|
||||
<Menu.Item key="2">2nd item</Menu.Item>
|
||||
<Menu.Item key="3">3rd item</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
onClick={onMenuClick}
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label: '1st item',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: '2nd item',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: '3rd item',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -61,6 +61,35 @@ import {
|
||||
|
||||
const SplitSpace = props => <Space split={<Divider type="vertical" />} size={4} {...props} />;
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
key: 'mail',
|
||||
icon: <MailOutlined />,
|
||||
label: 'Mail',
|
||||
},
|
||||
{
|
||||
key: 'SubMenu',
|
||||
icon: <SettingOutlined />,
|
||||
label: 'Submenu',
|
||||
children: [
|
||||
{
|
||||
type: 'group',
|
||||
label: 'Item 1',
|
||||
children: [
|
||||
{
|
||||
key: 'setting:1',
|
||||
label: 'Option 1',
|
||||
},
|
||||
{
|
||||
key: 'setting:2',
|
||||
label: 'Option 2',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const inputProps = {
|
||||
style: { width: 128 },
|
||||
};
|
||||
@ -281,10 +310,17 @@ const FormSizeDemo = () => {
|
||||
{/* Dropdown */}
|
||||
<Dropdown
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.Item>1st menu item</Menu.Item>
|
||||
<Menu.Item danger>a danger item</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: '1st menu item',
|
||||
},
|
||||
{
|
||||
label: 'a danger item',
|
||||
danger: true,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
|
||||
@ -299,60 +335,25 @@ const FormSizeDemo = () => {
|
||||
{/* Menu - horizontal */}
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Menu mode="horizontal" defaultSelectedKeys={['mail']}>
|
||||
<Menu.Item key="mail" icon={<MailOutlined />}>
|
||||
Mail
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu key="SubMenu" icon={<SettingOutlined />} title="Submenu">
|
||||
<Menu.ItemGroup title="Item 1">
|
||||
<Menu.Item key="setting:1">Option 1</Menu.Item>
|
||||
<Menu.Item key="setting:2">Option 2</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
<Menu mode="horizontal" defaultSelectedKeys={['mail']} items={menuItems} />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Menu mode="horizontal" theme="dark" defaultSelectedKeys={['mail']}>
|
||||
<Menu.Item key="mail" icon={<MailOutlined />}>
|
||||
Mail
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu key="SubMenu" icon={<SettingOutlined />} title="Submenu">
|
||||
<Menu.ItemGroup title="Item 1">
|
||||
<Menu.Item key="setting:1">Option 1</Menu.Item>
|
||||
<Menu.Item key="setting:2">Option 2</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
<Menu
|
||||
mode="horizontal"
|
||||
theme="dark"
|
||||
defaultSelectedKeys={['mail']}
|
||||
items={menuItems}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* Menu - vertical */}
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Menu mode="inline" defaultSelectedKeys={['mail']}>
|
||||
<Menu.Item key="mail" icon={<MailOutlined />}>
|
||||
Mail
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu key="SubMenu" icon={<SettingOutlined />} title="Submenu">
|
||||
<Menu.ItemGroup title="Item 1">
|
||||
<Menu.Item key="setting:1">Option 1</Menu.Item>
|
||||
<Menu.Item key="setting:2">Option 2</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
<Menu mode="inline" defaultSelectedKeys={['mail']} items={menuItems} />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Menu mode="vertical" theme="dark" defaultSelectedKeys={['mail']}>
|
||||
<Menu.Item key="mail" icon={<MailOutlined />}>
|
||||
Mail
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu key="SubMenu" icon={<SettingOutlined />} title="Submenu">
|
||||
<Menu.ItemGroup title="Item 1">
|
||||
<Menu.Item key="setting:1">Option 1</Menu.Item>
|
||||
<Menu.Item key="setting:2">Option 2</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
<Menu mode="vertical" theme="dark" defaultSelectedKeys={['mail']} items={menuItems} />
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
|
@ -17,23 +17,31 @@ By specifying `arrow` prop with `{ pointAtCenter: true }`, the arrow will point
|
||||
import { Menu, Dropdown, Button } from 'antd';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
|
||||
3rd menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
|
||||
3rd menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -17,23 +17,31 @@ You could display an arrow.
|
||||
import { Menu, Dropdown, Button } from 'antd';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
|
||||
3rd menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
|
||||
3rd menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -18,24 +18,38 @@ import { Menu, Dropdown } from 'antd';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item icon={<DownOutlined />} disabled>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu item (disabled)
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item disabled>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
|
||||
3rd menu item (disabled)
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item danger>a danger item</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu item (disabled)
|
||||
</a>
|
||||
),
|
||||
icon: <DownOutlined />,
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
|
||||
3rd menu item (disabled)
|
||||
</a>
|
||||
),
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
danger: true,
|
||||
label: 'a danger item',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -17,11 +17,22 @@ The default trigger mode is `hover`, you can change it to `contextMenu`.
|
||||
import { Menu, Dropdown } from 'antd';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item key="1">1st menu item</Menu.Item>
|
||||
<Menu.Item key="2">2nd menu item</Menu.Item>
|
||||
<Menu.Item key="3">3rd menu item</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: '1st menu item',
|
||||
key: '1',
|
||||
},
|
||||
{
|
||||
label: '2nd menu item',
|
||||
key: '2',
|
||||
},
|
||||
{
|
||||
label: '3rd menu item',
|
||||
key: '3',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -28,17 +28,26 @@ function handleMenuClick(e) {
|
||||
}
|
||||
|
||||
const menu = (
|
||||
<Menu onClick={handleMenuClick}>
|
||||
<Menu.Item key="1" icon={<UserOutlined />}>
|
||||
1st menu item
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2" icon={<UserOutlined />}>
|
||||
2nd menu item
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3" icon={<UserOutlined />}>
|
||||
3rd menu item
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
onClick={handleMenuClick}
|
||||
items={[
|
||||
{
|
||||
label: '1st menu item',
|
||||
key: '1',
|
||||
icon: <UserOutlined />,
|
||||
},
|
||||
{
|
||||
label: '2nd menu item',
|
||||
key: '2',
|
||||
icon: <UserOutlined />,
|
||||
},
|
||||
{
|
||||
label: '3rd menu item',
|
||||
key: '3',
|
||||
icon: <UserOutlined />,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -22,11 +22,23 @@ const onClick = ({ key }) => {
|
||||
};
|
||||
|
||||
const menu = (
|
||||
<Menu onClick={onClick}>
|
||||
<Menu.Item key="1">1st menu item</Menu.Item>
|
||||
<Menu.Item key="2">2nd menu item</Menu.Item>
|
||||
<Menu.Item key="3">3rd menu item</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
onClick={onClick}
|
||||
items={[
|
||||
{
|
||||
label: '1st menu item',
|
||||
key: '1',
|
||||
},
|
||||
{
|
||||
label: '2nd menu item',
|
||||
key: '2',
|
||||
},
|
||||
{
|
||||
label: '3rd menu item',
|
||||
key: '3',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -18,22 +18,34 @@ import { Menu, Dropdown } from 'antd';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item key="0">
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="1">
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item key="3" disabled>
|
||||
3rd menu item(disabled)
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu item
|
||||
</a>
|
||||
),
|
||||
key: '0',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu item
|
||||
</a>
|
||||
),
|
||||
key: '1',
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
label: '3rd menu item(disabled)',
|
||||
key: '3',
|
||||
disabled: true,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -18,9 +18,14 @@ import { Menu, Dropdown, Space } from 'antd';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item key="1">Submit and continue</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: 'Submit and continue',
|
||||
key: '1',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
|
@ -18,44 +18,56 @@ This demo was created for debugging Menu styles inside Dropdown.
|
||||
|
||||
[#19150](https://github.com/ant-design/ant-design/pull/19150)
|
||||
|
||||
```jsx
|
||||
import { Menu, Dropdown } from 'antd';
|
||||
```tsx
|
||||
import { Menu, Dropdown, MenuProps } from 'antd';
|
||||
import { MailOutlined, AppstoreOutlined, SettingOutlined, DownOutlined } from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
const menu = (
|
||||
<Menu selectedKeys={['1']} openKeys={['sub1']}>
|
||||
<Menu.ItemGroup key="group" title="Item Group">
|
||||
<Menu.Item key="01">Option 0</Menu.Item>
|
||||
<Menu.Item key="02">Option 0</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
<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>
|
||||
</Menu.ItemGroup>
|
||||
<Menu.ItemGroup key="g2" title="Item 2">
|
||||
<Menu.Item key="3">Option 3</Menu.Item>
|
||||
<Menu.Item key="4">Option 4</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
</SubMenu>
|
||||
<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">
|
||||
<Menu.Item key="7">Option 7</Menu.Item>
|
||||
<Menu.Item key="8">Option 8</Menu.Item>
|
||||
</SubMenu>
|
||||
</SubMenu>
|
||||
<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>
|
||||
);
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
icon?: React.ReactNode,
|
||||
children?: MenuItem[],
|
||||
type?: 'group',
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
type,
|
||||
} as MenuItem;
|
||||
}
|
||||
|
||||
const items: MenuItem[] = [
|
||||
getItem(
|
||||
'Item Group',
|
||||
'group',
|
||||
null,
|
||||
[getItem('Option 0', '01'), getItem('Option 0', '02')],
|
||||
'group',
|
||||
),
|
||||
getItem('Navigation One', 'sub1', <MailOutlined />, [
|
||||
getItem('Item 1', 'g1', null, [getItem('Option 1', '1'), getItem('Option 2', '2')], 'group'),
|
||||
getItem('Item 2', 'g2', null, [getItem('Option 3', '3'), getItem('Option 4', '4')], 'group'),
|
||||
]),
|
||||
getItem('Navigation Two', 'sub2', <AppstoreOutlined />, [
|
||||
getItem('Option 5', '5'),
|
||||
getItem('Option 6', '6'),
|
||||
getItem('Submenu', 'sub3', null, [getItem('Option 7', '7'), getItem('Option 8', '8')]),
|
||||
]),
|
||||
getItem('Navigation Three', 'sub4', <SettingOutlined />, [
|
||||
getItem('Option 9', '9'),
|
||||
getItem('Option 10', '10'),
|
||||
getItem('Option 11', '11'),
|
||||
getItem('Option 12', '12'),
|
||||
]),
|
||||
// Not crash
|
||||
null as any,
|
||||
];
|
||||
|
||||
const menu = <Menu selectedKeys={['1']} openKeys={['sub1']} items={items} />;
|
||||
|
||||
ReactDOM.render(
|
||||
<Dropdown overlay={menu}>
|
||||
|
@ -34,11 +34,23 @@ class OverlayVisible extends React.Component {
|
||||
|
||||
render() {
|
||||
const menu = (
|
||||
<Menu onClick={this.handleMenuClick}>
|
||||
<Menu.Item key="1">Clicking me will not close the menu.</Menu.Item>
|
||||
<Menu.Item key="2">Clicking me will not close the menu also.</Menu.Item>
|
||||
<Menu.Item key="3">Clicking me will close the menu.</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
onClick={this.handleMenuClick}
|
||||
items={[
|
||||
{
|
||||
label: 'Clicking me will not close the menu.',
|
||||
key: '1',
|
||||
},
|
||||
{
|
||||
label: 'Clicking me will not close the menu also.',
|
||||
key: '2',
|
||||
},
|
||||
{
|
||||
label: 'Clicking me will close the menu.',
|
||||
key: '3',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<Dropdown
|
||||
|
@ -17,23 +17,31 @@ Support 6 placements.
|
||||
import { Menu, Dropdown, Button, Space } from 'antd';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
|
||||
3rd menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
|
||||
3rd menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -20,20 +20,45 @@ import { DownOutlined } from '@ant-design/icons';
|
||||
const { SubMenu } = Menu;
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.ItemGroup title="Group title">
|
||||
<Menu.Item>1st menu item</Menu.Item>
|
||||
<Menu.Item>2nd menu item</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
<SubMenu title="sub menu">
|
||||
<Menu.Item>3rd menu item</Menu.Item>
|
||||
<Menu.Item>4th menu item</Menu.Item>
|
||||
</SubMenu>
|
||||
<SubMenu title="disabled sub menu" disabled>
|
||||
<Menu.Item>5d menu item</Menu.Item>
|
||||
<Menu.Item>6th menu item</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
type: 'group',
|
||||
label: 'Group title',
|
||||
children: [
|
||||
{
|
||||
label: '1st menu item',
|
||||
},
|
||||
{
|
||||
label: '2nd menu item',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'sub menu',
|
||||
children: [
|
||||
{
|
||||
label: '3rd menu item',
|
||||
},
|
||||
{
|
||||
label: '4th menu item',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'disabled sub menu',
|
||||
disabled: true,
|
||||
children: [
|
||||
{
|
||||
label: '5d menu item',
|
||||
},
|
||||
{
|
||||
label: '6th menu item',
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -13,21 +13,30 @@ title:
|
||||
|
||||
The default trigger mode is `hover`, you can change it to `click`.
|
||||
|
||||
```jsx
|
||||
```tsx
|
||||
import { Menu, Dropdown } from 'antd';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item key="0">
|
||||
<a href="https://www.antgroup.com">1st menu item</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="1">
|
||||
<a href="https://www.aliyun.com">2nd menu item</a>
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item key="3">3rd menu item</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: <a href="https://www.antgroup.com">1st menu item</a>,
|
||||
key: '0',
|
||||
},
|
||||
{
|
||||
label: <a href="https://www.aliyun.com">2nd menu item</a>,
|
||||
key: '1',
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
label: '3rd menu item',
|
||||
key: '3',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -10,8 +10,8 @@ debug: true
|
||||
|
||||
修改内容前,请尝试此 Demo 查看样式是否抖动。
|
||||
|
||||
```jsx
|
||||
import { Layout, Menu } from 'antd';
|
||||
```tsx
|
||||
import { Layout, Menu, MenuProps } from 'antd';
|
||||
import {
|
||||
TeamOutlined,
|
||||
UserOutlined,
|
||||
@ -23,7 +23,57 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
|
||||
const { Header, Sider, Content } = Layout;
|
||||
const { SubMenu } = Menu;
|
||||
|
||||
const items: MenuProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
icon: <PieChartOutlined />,
|
||||
label: 'Option 1',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
icon: <DesktopOutlined />,
|
||||
label: 'Option 2',
|
||||
},
|
||||
{
|
||||
key: 'sub1',
|
||||
icon: <UserOutlined />,
|
||||
label: 'User',
|
||||
children: [
|
||||
{
|
||||
key: '3',
|
||||
label: 'Tom',
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
label: 'Bill',
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
label: 'Alex',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'sub2',
|
||||
icon: <TeamOutlined />,
|
||||
label: 'Team',
|
||||
children: [
|
||||
{
|
||||
key: '6',
|
||||
label: 'Team 1',
|
||||
},
|
||||
{
|
||||
key: '7',
|
||||
label: 'Team 2',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: '9',
|
||||
icon: <FileOutlined />,
|
||||
},
|
||||
];
|
||||
|
||||
class SiderDemo extends React.Component {
|
||||
state = {
|
||||
@ -41,24 +91,13 @@ class SiderDemo extends React.Component {
|
||||
<Layout>
|
||||
<Sider trigger={null} collapsible collapsed={this.state.collapsed}>
|
||||
<div className="logo" />
|
||||
<Menu theme="dark" mode="inline" defaultSelectedKeys={['3']} defaultOpenKeys={['sub1']}>
|
||||
<Menu.Item key="1" icon={<PieChartOutlined />}>
|
||||
Option 1
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2" icon={<DesktopOutlined />}>
|
||||
Option 2
|
||||
</Menu.Item>
|
||||
<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" 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" icon={<FileOutlined />} />
|
||||
</Menu>
|
||||
<Menu
|
||||
theme="dark"
|
||||
mode="inline"
|
||||
defaultSelectedKeys={['3']}
|
||||
defaultOpenKeys={['sub1']}
|
||||
items={items}
|
||||
/>
|
||||
</Sider>
|
||||
<Layout>
|
||||
<Header className="site-layout-background" style={{ padding: 0 }}>
|
||||
|
@ -41,17 +41,28 @@ class SiderDemo extends React.Component {
|
||||
<Layout>
|
||||
<Sider trigger={null} collapsible collapsed={this.state.collapsed}>
|
||||
<div className="logo" />
|
||||
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
|
||||
<Menu.Item key="1" icon={<UserOutlined />}>
|
||||
nav 1
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2" icon={<VideoCameraOutlined />}>
|
||||
nav 2
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3" icon={<UploadOutlined />}>
|
||||
nav 3
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
theme="dark"
|
||||
mode="inline"
|
||||
defaultSelectedKeys={['1']}
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
icon: <UserOutlined />,
|
||||
label: 'nav 1',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
icon: <VideoCameraOutlined />,
|
||||
label: 'nav 2',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
icon: <UploadOutlined />,
|
||||
label: 'nav 3',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Sider>
|
||||
<Layout className="site-layout">
|
||||
<Header className="site-layout-background" style={{ padding: 0 }}>
|
||||
|
@ -14,8 +14,8 @@ title:
|
||||
|
||||
When dealing with long content, a fixed sider can provide a better user experience.
|
||||
|
||||
```jsx
|
||||
import { Layout, Menu } from 'antd';
|
||||
```tsx
|
||||
import { Layout, Menu, MenuProps } from 'antd';
|
||||
import {
|
||||
AppstoreOutlined,
|
||||
BarChartOutlined,
|
||||
@ -29,6 +29,21 @@ import {
|
||||
|
||||
const { Header, Content, Footer, Sider } = Layout;
|
||||
|
||||
const items: MenuProps['items'] = [
|
||||
UserOutlined,
|
||||
VideoCameraOutlined,
|
||||
UploadOutlined,
|
||||
BarChartOutlined,
|
||||
CloudOutlined,
|
||||
AppstoreOutlined,
|
||||
TeamOutlined,
|
||||
ShopOutlined,
|
||||
].map((icon, index) => ({
|
||||
key: String(index + 1),
|
||||
icon: React.createElement(icon),
|
||||
label: `nav ${index + 1}`,
|
||||
}));
|
||||
|
||||
ReactDOM.render(
|
||||
<Layout hasSider>
|
||||
<Sider
|
||||
@ -42,32 +57,7 @@ ReactDOM.render(
|
||||
}}
|
||||
>
|
||||
<div className="logo" />
|
||||
<Menu theme="dark" mode="inline" defaultSelectedKeys={['4']}>
|
||||
<Menu.Item key="1" icon={<UserOutlined />}>
|
||||
nav 1
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2" icon={<VideoCameraOutlined />}>
|
||||
nav 2
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3" icon={<UploadOutlined />}>
|
||||
nav 3
|
||||
</Menu.Item>
|
||||
<Menu.Item key="4" icon={<BarChartOutlined />}>
|
||||
nav 4
|
||||
</Menu.Item>
|
||||
<Menu.Item key="5" icon={<CloudOutlined />}>
|
||||
nav 5
|
||||
</Menu.Item>
|
||||
<Menu.Item key="6" icon={<AppstoreOutlined />}>
|
||||
nav 6
|
||||
</Menu.Item>
|
||||
<Menu.Item key="7" icon={<TeamOutlined />}>
|
||||
nav 7
|
||||
</Menu.Item>
|
||||
<Menu.Item key="8" icon={<ShopOutlined />}>
|
||||
nav 8
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu theme="dark" mode="inline" defaultSelectedKeys={['4']} items={items} />
|
||||
</Sider>
|
||||
<Layout className="site-layout" style={{ marginLeft: 200 }}>
|
||||
<Header className="site-layout-background" style={{ padding: 0 }} />
|
||||
|
@ -14,7 +14,7 @@ title:
|
||||
|
||||
Fixed Header is generally used to fix the top navigation to facilitate page switching.
|
||||
|
||||
```jsx
|
||||
```tsx
|
||||
import { Layout, Menu, Breadcrumb } from 'antd';
|
||||
|
||||
const { Header, Content, Footer } = Layout;
|
||||
@ -23,11 +23,15 @@ ReactDOM.render(
|
||||
<Layout>
|
||||
<Header style={{ position: 'fixed', zIndex: 1, width: '100%' }}>
|
||||
<div className="logo" />
|
||||
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']}>
|
||||
<Menu.Item key="1">nav 1</Menu.Item>
|
||||
<Menu.Item key="2">nav 2</Menu.Item>
|
||||
<Menu.Item key="3">nav 3</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
theme="dark"
|
||||
mode="horizontal"
|
||||
defaultSelectedKeys={['2']}
|
||||
items={new Array(3).fill(null).map((_, index) => ({
|
||||
key: String(index + 1),
|
||||
label: `nav ${index + 1}`,
|
||||
}))}
|
||||
/>
|
||||
</Header>
|
||||
<Content className="site-layout" style={{ padding: '0 50px', marginTop: 64 }}>
|
||||
<Breadcrumb style={{ margin: '16px 0' }}>
|
||||
|
@ -36,20 +36,18 @@ ReactDOM.render(
|
||||
}}
|
||||
>
|
||||
<div className="logo" />
|
||||
<Menu theme="dark" mode="inline" defaultSelectedKeys={['4']}>
|
||||
<Menu.Item key="1" icon={<UserOutlined />}>
|
||||
nav 1
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2" icon={<VideoCameraOutlined />}>
|
||||
nav 2
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3" icon={<UploadOutlined />}>
|
||||
nav 3
|
||||
</Menu.Item>
|
||||
<Menu.Item key="4" icon={<UserOutlined />}>
|
||||
nav 4
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
theme="dark"
|
||||
mode="inline"
|
||||
defaultSelectedKeys={['4']}
|
||||
items={[UserOutlined, VideoCameraOutlined, UploadOutlined, UserOutlined].map(
|
||||
(icon, index) => ({
|
||||
key: String(index + 1),
|
||||
icon: React.createElement(icon),
|
||||
label: `nav ${index + 1}`,
|
||||
}),
|
||||
)}
|
||||
/>
|
||||
</Sider>
|
||||
<Layout>
|
||||
<Header className="site-layout-sub-header-background" style={{ padding: 0 }} />
|
||||
|
@ -22,8 +22,8 @@ Generally, the mainnav is placed on the left side of the page, and the secondary
|
||||
|
||||
The level of the aside navigation is scalable. The first, second, and third level navigations could be present more fluently and relevantly, and aside navigation can be fixed, allowing the user to quickly switch and spot the current position, improving the user experience. However, this navigation occupies some horizontal space of the contents.
|
||||
|
||||
```jsx
|
||||
import { Layout, Menu, Breadcrumb } from 'antd';
|
||||
```tsx
|
||||
import { Layout, Menu, Breadcrumb, MenuProps } from 'antd';
|
||||
import {
|
||||
DesktopOutlined,
|
||||
PieChartOutlined,
|
||||
@ -33,14 +33,41 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
|
||||
const { Header, Content, Footer, Sider } = Layout;
|
||||
const { SubMenu } = Menu;
|
||||
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
icon?: React.ReactNode,
|
||||
children?: MenuItem[],
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
} as MenuItem;
|
||||
}
|
||||
|
||||
const items: MenuItem[] = [
|
||||
getItem('Option 1', '1', <PieChartOutlined />),
|
||||
getItem('Option 2', '2', <DesktopOutlined />),
|
||||
getItem('User', 'sub1', <UserOutlined />, [
|
||||
getItem('Tom', '3'),
|
||||
getItem('Bill', '4'),
|
||||
getItem('Alex', '5'),
|
||||
]),
|
||||
getItem('Team', 'sub2', <TeamOutlined />, [getItem('Team 1', '6'), getItem('Team 2', '8')]),
|
||||
getItem('Files', '9', <FileOutlined />),
|
||||
];
|
||||
|
||||
class SiderDemo extends React.Component {
|
||||
state = {
|
||||
collapsed: false,
|
||||
};
|
||||
|
||||
onCollapse = collapsed => {
|
||||
onCollapse = (collapsed: boolean) => {
|
||||
console.log(collapsed);
|
||||
this.setState({ collapsed });
|
||||
};
|
||||
@ -51,26 +78,7 @@ class SiderDemo extends React.Component {
|
||||
<Layout style={{ minHeight: '100vh' }}>
|
||||
<Sider collapsible collapsed={collapsed} onCollapse={this.onCollapse}>
|
||||
<div className="logo" />
|
||||
<Menu theme="dark" defaultSelectedKeys={['1']} mode="inline">
|
||||
<Menu.Item key="1" icon={<PieChartOutlined />}>
|
||||
Option 1
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2" icon={<DesktopOutlined />}>
|
||||
Option 2
|
||||
</Menu.Item>
|
||||
<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" 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" icon={<FileOutlined />}>
|
||||
Files
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu theme="dark" defaultSelectedKeys={['1']} mode="inline" items={items} />
|
||||
</Sider>
|
||||
<Layout className="site-layout">
|
||||
<Header className="site-layout-background" style={{ padding: 0 }} />
|
||||
|
@ -13,22 +13,42 @@ title:
|
||||
|
||||
Both the top navigation and the sidebar, commonly used in application site.
|
||||
|
||||
```jsx
|
||||
import { Layout, Menu, Breadcrumb } from 'antd';
|
||||
```tsx
|
||||
import { Layout, Menu, Breadcrumb, MenuProps } from 'antd';
|
||||
import { UserOutlined, LaptopOutlined, NotificationOutlined } from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
const { Header, Content, Sider } = Layout;
|
||||
|
||||
const items1: MenuProps['items'] = ['1', '2', '3'].map(key => ({
|
||||
key,
|
||||
label: `nav ${key}`,
|
||||
}));
|
||||
|
||||
const items2: MenuProps['items'] = [UserOutlined, LaptopOutlined, NotificationOutlined].map(
|
||||
(icon, index) => {
|
||||
const key = String(index + 1);
|
||||
|
||||
return {
|
||||
key: `sub${key}`,
|
||||
icon: React.createElement(icon),
|
||||
label: `subnav ${key}`,
|
||||
|
||||
children: new Array(4).fill(null).map((_, j) => {
|
||||
const subKey = index * 4 + j + 1;
|
||||
return {
|
||||
key: subKey,
|
||||
label: `option${subKey}`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<Layout>
|
||||
<Header className="header">
|
||||
<div className="logo" />
|
||||
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']}>
|
||||
<Menu.Item key="1">nav 1</Menu.Item>
|
||||
<Menu.Item key="2">nav 2</Menu.Item>
|
||||
<Menu.Item key="3">nav 3</Menu.Item>
|
||||
</Menu>
|
||||
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']} items={items1} />
|
||||
</Header>
|
||||
<Layout>
|
||||
<Sider width={200} className="site-layout-background">
|
||||
@ -37,26 +57,8 @@ ReactDOM.render(
|
||||
defaultSelectedKeys={['1']}
|
||||
defaultOpenKeys={['sub1']}
|
||||
style={{ height: '100%', borderRight: 0 }}
|
||||
>
|
||||
<SubMenu key="sub1" icon={<UserOutlined />} title="subnav 1">
|
||||
<Menu.Item key="1">option1</Menu.Item>
|
||||
<Menu.Item key="2">option2</Menu.Item>
|
||||
<Menu.Item key="3">option3</Menu.Item>
|
||||
<Menu.Item key="4">option4</Menu.Item>
|
||||
</SubMenu>
|
||||
<SubMenu key="sub2" icon={<LaptopOutlined />} title="subnav 2">
|
||||
<Menu.Item key="5">option5</Menu.Item>
|
||||
<Menu.Item key="6">option6</Menu.Item>
|
||||
<Menu.Item key="7">option7</Menu.Item>
|
||||
<Menu.Item key="8">option8</Menu.Item>
|
||||
</SubMenu>
|
||||
<SubMenu key="sub3" icon={<NotificationOutlined />} title="subnav 3">
|
||||
<Menu.Item key="9">option9</Menu.Item>
|
||||
<Menu.Item key="10">option10</Menu.Item>
|
||||
<Menu.Item key="11">option11</Menu.Item>
|
||||
<Menu.Item key="12">option12</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
items={items2}
|
||||
/>
|
||||
</Sider>
|
||||
<Layout style={{ padding: '0 24px 24px' }}>
|
||||
<Breadcrumb style={{ margin: '16px 0' }}>
|
||||
|
@ -13,22 +13,42 @@ title:
|
||||
|
||||
Both the top navigation and the sidebar, commonly used in documentation site.
|
||||
|
||||
```jsx
|
||||
import { Layout, Menu, Breadcrumb } from 'antd';
|
||||
```tsx
|
||||
import { Layout, Menu, Breadcrumb, MenuProps } from 'antd';
|
||||
import { UserOutlined, LaptopOutlined, NotificationOutlined } from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
const { Header, Content, Footer, Sider } = Layout;
|
||||
|
||||
const items1: MenuProps['items'] = ['1', '2', '3'].map(key => ({
|
||||
key,
|
||||
label: `nav ${key}`,
|
||||
}));
|
||||
|
||||
const items2: MenuProps['items'] = [UserOutlined, LaptopOutlined, NotificationOutlined].map(
|
||||
(icon, index) => {
|
||||
const key = String(index + 1);
|
||||
|
||||
return {
|
||||
key: `sub${key}`,
|
||||
icon: React.createElement(icon),
|
||||
label: `subnav ${key}`,
|
||||
|
||||
children: new Array(4).fill(null).map((_, j) => {
|
||||
const subKey = index * 4 + j + 1;
|
||||
return {
|
||||
key: subKey,
|
||||
label: `option${subKey}`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<Layout>
|
||||
<Header className="header">
|
||||
<div className="logo" />
|
||||
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']}>
|
||||
<Menu.Item key="1">nav 1</Menu.Item>
|
||||
<Menu.Item key="2">nav 2</Menu.Item>
|
||||
<Menu.Item key="3">nav 3</Menu.Item>
|
||||
</Menu>
|
||||
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']} items={items1} />
|
||||
</Header>
|
||||
<Content style={{ padding: '0 50px' }}>
|
||||
<Breadcrumb style={{ margin: '16px 0' }}>
|
||||
@ -43,26 +63,8 @@ ReactDOM.render(
|
||||
defaultSelectedKeys={['1']}
|
||||
defaultOpenKeys={['sub1']}
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
<SubMenu key="sub1" icon={<UserOutlined />} title="subnav 1">
|
||||
<Menu.Item key="1">option1</Menu.Item>
|
||||
<Menu.Item key="2">option2</Menu.Item>
|
||||
<Menu.Item key="3">option3</Menu.Item>
|
||||
<Menu.Item key="4">option4</Menu.Item>
|
||||
</SubMenu>
|
||||
<SubMenu key="sub2" icon={<LaptopOutlined />} title="subnav 2">
|
||||
<Menu.Item key="5">option5</Menu.Item>
|
||||
<Menu.Item key="6">option6</Menu.Item>
|
||||
<Menu.Item key="7">option7</Menu.Item>
|
||||
<Menu.Item key="8">option8</Menu.Item>
|
||||
</SubMenu>
|
||||
<SubMenu key="sub3" icon={<NotificationOutlined />} title="subnav 3">
|
||||
<Menu.Item key="9">option9</Menu.Item>
|
||||
<Menu.Item key="10">option10</Menu.Item>
|
||||
<Menu.Item key="11">option11</Menu.Item>
|
||||
<Menu.Item key="12">option12</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
items={items2}
|
||||
/>
|
||||
</Sider>
|
||||
<Content style={{ padding: '0 24px', minHeight: 280 }}>Content</Content>
|
||||
</Layout>
|
||||
|
@ -28,12 +28,18 @@ ReactDOM.render(
|
||||
<Layout className="layout">
|
||||
<Header>
|
||||
<div className="logo" />
|
||||
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']}>
|
||||
{new Array(15).fill(null).map((_, index) => {
|
||||
<Menu
|
||||
theme="dark"
|
||||
mode="horizontal"
|
||||
defaultSelectedKeys={['2']}
|
||||
items={new Array(15).fill(null).map((_, index) => {
|
||||
const key = index + 1;
|
||||
return <Menu.Item key={key}>{`nav ${key}`}</Menu.Item>;
|
||||
return {
|
||||
key,
|
||||
label: `nav ${key}`,
|
||||
};
|
||||
})}
|
||||
</Menu>
|
||||
/>
|
||||
</Header>
|
||||
<Content style={{ padding: '0 50px' }}>
|
||||
<Breadcrumb style={{ margin: '16px 0' }}>
|
||||
|
@ -13,51 +13,77 @@ title:
|
||||
|
||||
Horizontal top navigation menu.
|
||||
|
||||
```jsx
|
||||
import { Menu } from 'antd';
|
||||
```tsx
|
||||
import { Menu, MenuProps } from 'antd';
|
||||
import { MailOutlined, AppstoreOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
const items: MenuProps['items'] = [
|
||||
{
|
||||
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',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'group',
|
||||
label: 'Item 2',
|
||||
children: [
|
||||
{
|
||||
label: 'Option 3',
|
||||
key: 'setting:3',
|
||||
},
|
||||
{
|
||||
label: 'Option 4',
|
||||
key: 'setting:4',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a href="https://ant.design" target="_blank" rel="noopener noreferrer">
|
||||
Navigation Four - Link
|
||||
</a>
|
||||
),
|
||||
key: 'alipay',
|
||||
},
|
||||
];
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
current: 'mail',
|
||||
};
|
||||
const App = () => {
|
||||
const [current, setCurrent] = React.useState('mail');
|
||||
|
||||
handleClick = e => {
|
||||
const onClick: MenuProps['onClick'] = e => {
|
||||
console.log('click ', e);
|
||||
this.setState({ current: e.key });
|
||||
setCurrent(e.key);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { current } = this.state;
|
||||
return (
|
||||
<Menu onClick={this.handleClick} selectedKeys={[current]} mode="horizontal">
|
||||
<Menu.Item key="mail" icon={<MailOutlined />}>
|
||||
Navigation One
|
||||
</Menu.Item>
|
||||
<Menu.Item key="app" disabled icon={<AppstoreOutlined />}>
|
||||
Navigation Two
|
||||
</Menu.Item>
|
||||
<SubMenu key="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>
|
||||
</Menu.ItemGroup>
|
||||
<Menu.ItemGroup title="Item 2">
|
||||
<Menu.Item key="setting:3">Option 3</Menu.Item>
|
||||
<Menu.Item key="setting:4">Option 4</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
</SubMenu>
|
||||
<Menu.Item key="alipay">
|
||||
<a href="https://ant.design" target="_blank" rel="noopener noreferrer">
|
||||
Navigation Four - Link
|
||||
</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
}
|
||||
return <Menu onClick={onClick} selectedKeys={[current]} mode="horizontal" items={items} />;
|
||||
};
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
```
|
||||
|
@ -17,8 +17,8 @@ Inline menu could be collapsed.
|
||||
|
||||
Here is [a complete demo](/components/layout/#components-layout-demo-side) with sider layout.
|
||||
|
||||
```jsx
|
||||
import { Menu, Button } from 'antd';
|
||||
```tsx
|
||||
import { Menu, Button, MenuProps } from 'antd';
|
||||
import {
|
||||
AppstoreOutlined,
|
||||
MenuUnfoldOutlined,
|
||||
@ -29,60 +29,67 @@ import {
|
||||
MailOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
collapsed: false,
|
||||
};
|
||||
|
||||
toggleCollapsed = () => {
|
||||
this.setState({
|
||||
collapsed: !this.state.collapsed,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{ width: 256 }}>
|
||||
<Button type="primary" onClick={this.toggleCollapsed} style={{ marginBottom: 16 }}>
|
||||
{React.createElement(this.state.collapsed ? MenuUnfoldOutlined : MenuFoldOutlined)}
|
||||
</Button>
|
||||
<Menu
|
||||
defaultSelectedKeys={['1']}
|
||||
defaultOpenKeys={['sub1']}
|
||||
mode="inline"
|
||||
theme="dark"
|
||||
inlineCollapsed={this.state.collapsed}
|
||||
>
|
||||
<Menu.Item key="1" icon={<PieChartOutlined />}>
|
||||
Option 1
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2" icon={<DesktopOutlined />}>
|
||||
Option 2
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3" icon={<ContainerOutlined />}>
|
||||
Option 3
|
||||
</Menu.Item>
|
||||
<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" 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">
|
||||
<Menu.Item key="11">Option 11</Menu.Item>
|
||||
<Menu.Item key="12">Option 12</Menu.Item>
|
||||
</SubMenu>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
icon?: React.ReactNode,
|
||||
children?: MenuItem[],
|
||||
type?: 'group',
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
type,
|
||||
} as MenuItem;
|
||||
}
|
||||
|
||||
const items: MenuItem[] = [
|
||||
getItem('Option 1', '1', <PieChartOutlined />),
|
||||
getItem('Option 2', '2', <DesktopOutlined />),
|
||||
getItem('Option 3', '3', <ContainerOutlined />),
|
||||
|
||||
getItem('Navigation One', 'sub1', <MailOutlined />, [
|
||||
getItem('Option 5', '5'),
|
||||
getItem('Option 6', '6'),
|
||||
getItem('Option 7', '7'),
|
||||
getItem('Option 8', '8'),
|
||||
]),
|
||||
|
||||
getItem('Navigation Two', 'sub2', <AppstoreOutlined />, [
|
||||
getItem('Option 9', '9'),
|
||||
getItem('Option 10', '10'),
|
||||
|
||||
getItem('Submenu', 'sub3', null, [getItem('Option 11', '11'), getItem('Option 12', '12')]),
|
||||
]),
|
||||
];
|
||||
|
||||
const App = () => {
|
||||
const [collapsed, setCollapsed] = React.useState(false);
|
||||
|
||||
const toggleCollapsed = () => {
|
||||
setCollapsed(!collapsed);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ width: 256 }}>
|
||||
<Button type="primary" onClick={toggleCollapsed} style={{ marginBottom: 16 }}>
|
||||
{collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||||
</Button>
|
||||
<Menu
|
||||
defaultSelectedKeys={['1']}
|
||||
defaultOpenKeys={['sub1']}
|
||||
mode="inline"
|
||||
theme="dark"
|
||||
inlineCollapsed={collapsed}
|
||||
items={items}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
```
|
||||
|
@ -13,54 +13,64 @@ title:
|
||||
|
||||
Vertical menu with inline submenus.
|
||||
|
||||
```jsx
|
||||
import { Menu } from 'antd';
|
||||
```tsx
|
||||
import { Menu, MenuProps } from 'antd';
|
||||
import { AppstoreOutlined, MailOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
class Sider extends React.Component {
|
||||
handleClick = e => {
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
icon?: React.ReactNode,
|
||||
children?: MenuItem[],
|
||||
type?: 'group',
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
type,
|
||||
} as MenuItem;
|
||||
}
|
||||
|
||||
const items: MenuProps['items'] = [
|
||||
getItem('Navigation One', 'sub1', <MailOutlined />, [
|
||||
getItem('Item 1', 'g1', null, [getItem('Option 1', '1'), getItem('Option 2', '2')], 'group'),
|
||||
getItem('Item 2', 'g2', null, [getItem('Option 3', '3'), getItem('Option 4', '4')], 'group'),
|
||||
]),
|
||||
|
||||
getItem('Navigation Two', 'sub2', <AppstoreOutlined />, [
|
||||
getItem('Option 5', '5'),
|
||||
getItem('Option 6', '6'),
|
||||
getItem('Submenu', 'sub3', null, [getItem('Option 7', '7'), getItem('Option 8', '8')]),
|
||||
]),
|
||||
|
||||
getItem('Navigation Three', 'sub4', <SettingOutlined />, [
|
||||
getItem('Option 9', '9'),
|
||||
getItem('Option 10', '10'),
|
||||
getItem('Option 11', '11'),
|
||||
getItem('Option 12', '12'),
|
||||
]),
|
||||
];
|
||||
|
||||
const Sider = () => {
|
||||
const onClick: MenuProps['onClick'] = e => {
|
||||
console.log('click ', e);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Menu
|
||||
onClick={this.handleClick}
|
||||
style={{ width: 256 }}
|
||||
defaultSelectedKeys={['1']}
|
||||
defaultOpenKeys={['sub1']}
|
||||
mode="inline"
|
||||
>
|
||||
<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>
|
||||
</Menu.ItemGroup>
|
||||
<Menu.ItemGroup key="g2" title="Item 2">
|
||||
<Menu.Item key="3">Option 3</Menu.Item>
|
||||
<Menu.Item key="4">Option 4</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
</SubMenu>
|
||||
<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">
|
||||
<Menu.Item key="7">Option 7</Menu.Item>
|
||||
<Menu.Item key="8">Option 8</Menu.Item>
|
||||
</SubMenu>
|
||||
</SubMenu>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Menu
|
||||
onClick={onClick}
|
||||
style={{ width: 256 }}
|
||||
defaultSelectedKeys={['1']}
|
||||
defaultOpenKeys={['sub1']}
|
||||
mode="inline"
|
||||
items={items}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.render(<Sider />, mountNode);
|
||||
```
|
||||
|
@ -13,11 +13,47 @@ title:
|
||||
|
||||
Click the menu and you will see that all the other menus gets collapsed to keep the entire menu compact.
|
||||
|
||||
```jsx
|
||||
import { Menu } from 'antd';
|
||||
```tsx
|
||||
import { Menu, MenuProps } from 'antd';
|
||||
import { AppstoreOutlined, MailOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
icon?: React.ReactNode,
|
||||
children?: MenuItem[],
|
||||
type?: 'group',
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
type,
|
||||
} as MenuItem;
|
||||
}
|
||||
|
||||
const items: MenuItem[] = [
|
||||
getItem('Navigation One', 'sub1', <MailOutlined />, [
|
||||
getItem('Option 1', '1'),
|
||||
getItem('Option 2', '2'),
|
||||
getItem('Option 3', '3'),
|
||||
getItem('Option 4', '4'),
|
||||
]),
|
||||
getItem('Navigation Two', 'sub2', <AppstoreOutlined />, [
|
||||
getItem('Option 5', '5'),
|
||||
getItem('Option 6', '6'),
|
||||
getItem('Submenu', 'sub3', null, [getItem('Option 7', '7'), getItem('Option 8', '8')]),
|
||||
]),
|
||||
getItem('Navigation Three', 'sub4', <SettingOutlined />, [
|
||||
getItem('Option 9', '9'),
|
||||
getItem('Option 10', '10'),
|
||||
getItem('Option 11', '11'),
|
||||
getItem('Option 12', '12'),
|
||||
]),
|
||||
];
|
||||
|
||||
// submenu keys of first level
|
||||
const rootSubmenuKeys = ['sub1', 'sub2', 'sub4'];
|
||||
@ -25,9 +61,9 @@ const rootSubmenuKeys = ['sub1', 'sub2', 'sub4'];
|
||||
const Sider = () => {
|
||||
const [openKeys, setOpenKeys] = React.useState(['sub1']);
|
||||
|
||||
const onOpenChange = keys => {
|
||||
const onOpenChange: MenuProps['onOpenChange'] = keys => {
|
||||
const latestOpenKey = keys.find(key => openKeys.indexOf(key) === -1);
|
||||
if (rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
|
||||
if (rootSubmenuKeys.indexOf(latestOpenKey!) === -1) {
|
||||
setOpenKeys(keys);
|
||||
} else {
|
||||
setOpenKeys(latestOpenKey ? [latestOpenKey] : []);
|
||||
@ -35,28 +71,13 @@ const Sider = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Menu mode="inline" openKeys={openKeys} onOpenChange={onOpenChange} style={{ width: 256 }}>
|
||||
<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" 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">
|
||||
<Menu.Item key="7">Option 7</Menu.Item>
|
||||
<Menu.Item key="8">Option 8</Menu.Item>
|
||||
</SubMenu>
|
||||
</SubMenu>
|
||||
<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>
|
||||
<Menu
|
||||
mode="inline"
|
||||
openKeys={openKeys}
|
||||
onOpenChange={onOpenChange}
|
||||
style={{ width: 256 }}
|
||||
items={items}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -19,91 +19,92 @@ import * as React from 'react';
|
||||
import { Menu, MenuProps, Switch } from 'antd';
|
||||
import { MailOutlined, AppstoreOutlined } from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
interface DemoState {
|
||||
theme: 'light' | 'dark';
|
||||
current: string;
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key?: React.Key | null,
|
||||
icon?: React.ReactNode,
|
||||
children?: MenuItem[],
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
} as MenuItem;
|
||||
}
|
||||
|
||||
class Demo extends React.Component<{}, DemoState> {
|
||||
state: DemoState = {
|
||||
theme: 'dark',
|
||||
current: '1',
|
||||
const items: MenuItem[] = [
|
||||
getItem('Navigation One Long Long Long Long', 'sub1', <MailOutlined />, [
|
||||
getItem('Option 1', '1'),
|
||||
getItem('Option 2', '2'),
|
||||
getItem('Option 3', '3'),
|
||||
getItem('Option 4', '4'),
|
||||
]),
|
||||
getItem('Navigation Two', 'sub2', <AppstoreOutlined />, [
|
||||
getItem('Option 5', '5'),
|
||||
getItem('Option 6', '6'),
|
||||
getItem('Submenu', 'sub3', null, [getItem('Option 7', '7'), getItem('Option 8', '8')]),
|
||||
]),
|
||||
getItem('Option 11', '11'),
|
||||
getItem('Option 12', '12'),
|
||||
];
|
||||
|
||||
const Demo = () => {
|
||||
const [theme, setTheme] = React.useState<'dark' | 'light'>('dark');
|
||||
const [current, setCurrent] = React.useState('1');
|
||||
|
||||
const changeTheme = (value: boolean) => {
|
||||
setTheme(value ? 'dark' : 'light');
|
||||
};
|
||||
|
||||
changeTheme = (value: boolean) => {
|
||||
this.setState({
|
||||
theme: value ? 'dark' : 'light',
|
||||
});
|
||||
};
|
||||
|
||||
handleClick: MenuProps['onClick'] = e => {
|
||||
const onClick: MenuProps['onClick'] = e => {
|
||||
console.log('click ', e);
|
||||
this.setState({
|
||||
current: e.key,
|
||||
});
|
||||
setCurrent(e.key);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<Switch
|
||||
checked={this.state.theme === 'dark'}
|
||||
onChange={this.changeTheme}
|
||||
checkedChildren="Dark"
|
||||
unCheckedChildren="Light"
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
<Menu
|
||||
theme={this.state.theme}
|
||||
onClick={this.handleClick}
|
||||
selectedKeys={[this.state.current]}
|
||||
mode="inline"
|
||||
inlineCollapsed
|
||||
// Test only. Remove in future.
|
||||
_internalRenderMenuItem={node =>
|
||||
React.cloneElement(node, {
|
||||
style: {
|
||||
...node.props.style,
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
})
|
||||
}
|
||||
// Test only. Remove in future.
|
||||
_internalRenderSubMenuItem={node =>
|
||||
React.cloneElement(node, {
|
||||
style: {
|
||||
...node.props.style,
|
||||
background: 'rgba(255,255,255,0.3)',
|
||||
},
|
||||
})
|
||||
}
|
||||
// Test only. Remove in future.
|
||||
_internalDisableMenuItemTitleTooltip
|
||||
>
|
||||
<SubMenu key="sub1" icon={<MailOutlined />} title="Navigation One Long Long Long Long">
|
||||
<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" 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">
|
||||
<Menu.Item key="7">Option 7</Menu.Item>
|
||||
<Menu.Item key="8">Option 8</Menu.Item>
|
||||
</SubMenu>
|
||||
</SubMenu>
|
||||
<Menu.Item key="11">Option 11</Menu.Item>
|
||||
<Menu.Item key="12">Option 12</Menu.Item>
|
||||
</Menu>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Switch
|
||||
checked={theme === 'dark'}
|
||||
onChange={changeTheme}
|
||||
checkedChildren="Dark"
|
||||
unCheckedChildren="Light"
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
<Menu
|
||||
theme={theme}
|
||||
onClick={onClick}
|
||||
selectedKeys={[current]}
|
||||
mode="inline"
|
||||
items={items}
|
||||
inlineCollapsed
|
||||
// Test only. Remove in future.
|
||||
_internalRenderMenuItem={node =>
|
||||
React.cloneElement(node, {
|
||||
style: {
|
||||
...node.props.style,
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
})
|
||||
}
|
||||
// Test only. Remove in future.
|
||||
_internalRenderSubMenuItem={node =>
|
||||
React.cloneElement(node, {
|
||||
style: {
|
||||
...node.props.style,
|
||||
background: 'rgba(255,255,255,0.3)',
|
||||
},
|
||||
})
|
||||
}
|
||||
// Test only. Remove in future.
|
||||
_internalDisableMenuItemTitleTooltip
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
```
|
||||
|
@ -13,24 +13,52 @@ title:
|
||||
|
||||
The Sub-menu will inherit the theme of `Menu`, but you can override this at the `SubMenu` level via the `theme` prop.
|
||||
|
||||
```jsx
|
||||
import { Menu, Switch } from 'antd';
|
||||
```tsx
|
||||
import { Menu, Switch, MenuProps } from 'antd';
|
||||
import { MailOutlined } from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key?: React.Key | null,
|
||||
icon?: React.ReactNode,
|
||||
children?: MenuItem[],
|
||||
theme?: 'light' | 'dark',
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
theme,
|
||||
} as MenuItem;
|
||||
}
|
||||
|
||||
const SubMenuTheme = () => {
|
||||
const [theme, setTheme] = React.useState('light');
|
||||
const [theme, setTheme] = React.useState<'light' | 'dark'>('light');
|
||||
const [current, setCurrent] = React.useState('1');
|
||||
|
||||
const changeTheme = value => {
|
||||
const changeTheme = (value: boolean) => {
|
||||
setTheme(value ? 'dark' : 'light');
|
||||
};
|
||||
|
||||
const handleClick = e => {
|
||||
const onClick: MenuProps['onClick'] = e => {
|
||||
setCurrent(e.key);
|
||||
};
|
||||
|
||||
const items: MenuItem[] = [
|
||||
getItem(
|
||||
'Navigation One',
|
||||
'sub1',
|
||||
<MailOutlined />,
|
||||
[getItem('Option 1', '1'), getItem('Option 2', '2'), getItem('Option 3', '3')],
|
||||
theme,
|
||||
),
|
||||
getItem('Option 5', '5'),
|
||||
getItem('Option 6', '6'),
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Switch
|
||||
@ -42,21 +70,14 @@ const SubMenuTheme = () => {
|
||||
<br />
|
||||
<br />
|
||||
<Menu
|
||||
onClick={handleClick}
|
||||
onClick={onClick}
|
||||
style={{ width: 256 }}
|
||||
defaultOpenKeys={['sub1']}
|
||||
selectedKeys={[current]}
|
||||
mode="vertical"
|
||||
theme="dark"
|
||||
>
|
||||
<SubMenu key="sub1" icon={<MailOutlined />} title="Navigation One" theme={theme}>
|
||||
<Menu.Item key="1">Option 1</Menu.Item>
|
||||
<Menu.Item key="2">Option 2</Menu.Item>
|
||||
<Menu.Item key="3">Option 3</Menu.Item>
|
||||
</SubMenu>
|
||||
<Menu.Item key="5">Option 5</Menu.Item>
|
||||
<Menu.Item key="6">Option 6</Menu.Item>
|
||||
</Menu>
|
||||
items={items}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -13,8 +13,8 @@ title:
|
||||
|
||||
Show the dynamic switching mode (between `inline` and `vertical`).
|
||||
|
||||
```jsx
|
||||
import { Menu, Switch, Divider } from 'antd';
|
||||
```tsx
|
||||
import { Menu, Switch, Divider, MenuProps } from 'antd';
|
||||
import {
|
||||
MailOutlined,
|
||||
CalendarOutlined,
|
||||
@ -23,17 +23,54 @@ import {
|
||||
LinkOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
type MenuItem = Required<MenuProps>['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', <MailOutlined />),
|
||||
getItem('Navigation Two', '2', <CalendarOutlined />),
|
||||
getItem('Navigation Two', 'sub1', <AppstoreOutlined />, [
|
||||
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', <SettingOutlined />, [
|
||||
getItem('Option 7', '7'),
|
||||
getItem('Option 8', '8'),
|
||||
getItem('Option 9', '9'),
|
||||
getItem('Option 10', '10'),
|
||||
]),
|
||||
getItem(
|
||||
<a href="https://ant.design" target="_blank" rel="noopener noreferrer">
|
||||
Ant Design
|
||||
</a>,
|
||||
'link',
|
||||
<LinkOutlined />,
|
||||
),
|
||||
];
|
||||
|
||||
const Demo = () => {
|
||||
const [mode, setMode] = React.useState('inline');
|
||||
const [theme, setTheme] = React.useState('light');
|
||||
const [mode, setMode] = React.useState<'inline' | 'vertical'>('inline');
|
||||
const [theme, setTheme] = React.useState<'dark' | 'light'>('light');
|
||||
|
||||
const changeMode = value => {
|
||||
const changeMode = (value: boolean) => {
|
||||
setMode(value ? 'vertical' : 'inline');
|
||||
};
|
||||
|
||||
const changeTheme = value => {
|
||||
const changeTheme = (value: boolean) => {
|
||||
setTheme(value ? 'dark' : 'light');
|
||||
};
|
||||
|
||||
@ -50,33 +87,8 @@ const Demo = () => {
|
||||
defaultOpenKeys={['sub1']}
|
||||
mode={mode}
|
||||
theme={theme}
|
||||
>
|
||||
<Menu.Item key="1" icon={<MailOutlined />}>
|
||||
Navigation One
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2" icon={<CalendarOutlined />}>
|
||||
Navigation Two
|
||||
</Menu.Item>
|
||||
<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">
|
||||
<Menu.Item key="5">Option 5</Menu.Item>
|
||||
<Menu.Item key="6">Option 6</Menu.Item>
|
||||
</SubMenu>
|
||||
</SubMenu>
|
||||
<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.Item key="link" icon={<LinkOutlined />}>
|
||||
<a href="https://ant.design" target="_blank" rel="noopener noreferrer">
|
||||
Ant Design
|
||||
</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
items={items}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -13,75 +13,85 @@ title:
|
||||
|
||||
There are two built-in themes: `light` and `dark`. The default value is `light`.
|
||||
|
||||
```jsx
|
||||
import { Menu, Switch } from 'antd';
|
||||
```tsx
|
||||
import { Menu, Switch, MenuProps } from 'antd';
|
||||
import { MailOutlined, AppstoreOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
class Sider extends React.Component {
|
||||
state = {
|
||||
theme: 'dark',
|
||||
current: '1',
|
||||
};
|
||||
|
||||
changeTheme = value => {
|
||||
this.setState({
|
||||
theme: value ? 'dark' : 'light',
|
||||
});
|
||||
};
|
||||
|
||||
handleClick = e => {
|
||||
console.log('click ', e);
|
||||
this.setState({
|
||||
current: e.key,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<Switch
|
||||
checked={this.state.theme === 'dark'}
|
||||
onChange={this.changeTheme}
|
||||
checkedChildren="Dark"
|
||||
unCheckedChildren="Light"
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
<Menu
|
||||
theme={this.state.theme}
|
||||
onClick={this.handleClick}
|
||||
style={{ width: 256 }}
|
||||
defaultOpenKeys={['sub1']}
|
||||
selectedKeys={[this.state.current]}
|
||||
mode="inline"
|
||||
>
|
||||
<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" 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">
|
||||
<Menu.Item key="7">Option 7</Menu.Item>
|
||||
<Menu.Item key="8">Option 8</Menu.Item>
|
||||
</SubMenu>
|
||||
</SubMenu>
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key?: React.Key | null,
|
||||
icon?: React.ReactNode,
|
||||
children?: MenuItem[],
|
||||
type?: 'group',
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
type,
|
||||
} as MenuItem;
|
||||
}
|
||||
|
||||
const items: MenuItem[] = [
|
||||
getItem('Navigation One', 'sub1', <MailOutlined />, [
|
||||
getItem('Option 1', '1'),
|
||||
getItem('Option 2', '2'),
|
||||
getItem('Option 3', '3'),
|
||||
getItem('Option 4', '4'),
|
||||
]),
|
||||
|
||||
getItem('Navigation Two', 'sub2', <AppstoreOutlined />, [
|
||||
getItem('Option 5', '5'),
|
||||
getItem('Option 6', '6'),
|
||||
getItem('Submenu', 'sub3', null, [getItem('Option 7', '7'), getItem('Option 8', '8')]),
|
||||
]),
|
||||
|
||||
getItem('Navigation Three', 'sub4', <SettingOutlined />, [
|
||||
getItem('Option 9', '9'),
|
||||
getItem('Option 10', '10'),
|
||||
getItem('Option 11', '11'),
|
||||
getItem('Option 12', '12'),
|
||||
]),
|
||||
];
|
||||
|
||||
const Sider = () => {
|
||||
const [theme, setTheme] = React.useState<'dark' | 'light'>('dark');
|
||||
const [current, setCurrent] = React.useState('1');
|
||||
|
||||
const changeTheme = (value: boolean) => {
|
||||
setTheme(value ? 'dark' : 'light');
|
||||
};
|
||||
|
||||
const onClick: MenuProps['onClick'] = e => {
|
||||
console.log('click ', e);
|
||||
setCurrent(e.key);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Switch
|
||||
checked={theme === 'dark'}
|
||||
onChange={changeTheme}
|
||||
checkedChildren="Dark"
|
||||
unCheckedChildren="Light"
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
<Menu
|
||||
theme={theme}
|
||||
onClick={onClick}
|
||||
style={{ width: 256 }}
|
||||
defaultOpenKeys={['sub1']}
|
||||
selectedKeys={[current]}
|
||||
mode="inline"
|
||||
items={items}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.render(<Sider />, mountNode);
|
||||
```
|
||||
|
@ -13,43 +13,54 @@ title:
|
||||
|
||||
Submenus open as pop-ups.
|
||||
|
||||
```jsx
|
||||
import { Menu } from 'antd';
|
||||
```tsx
|
||||
import { Menu, MenuProps } from 'antd';
|
||||
import { MailOutlined, AppstoreOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
function handleClick(e) {
|
||||
console.log('click', e);
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key?: React.Key | null,
|
||||
icon?: React.ReactNode,
|
||||
children?: MenuItem[],
|
||||
type?: 'group',
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
type,
|
||||
} as MenuItem;
|
||||
}
|
||||
|
||||
const items: MenuItem[] = [
|
||||
getItem('Navigation One', 'sub1', <MailOutlined />, [
|
||||
getItem('Item 1', null, null, [getItem('Option 1', '1'), getItem('Option 2', '2')], 'group'),
|
||||
getItem('Item 2', null, null, [getItem('Option 3', '3'), getItem('Option 4', '4')], 'group'),
|
||||
]),
|
||||
|
||||
getItem('Navigation Two', 'sub2', <AppstoreOutlined />, [
|
||||
getItem('Option 5', '5'),
|
||||
getItem('Option 6', '6'),
|
||||
getItem('Submenu', 'sub3', null, [getItem('Option 7', '7'), getItem('Option 8', '8')]),
|
||||
]),
|
||||
|
||||
getItem('Navigation Three', 'sub4', <SettingOutlined />, [
|
||||
getItem('Option 9', '9'),
|
||||
getItem('Option 10', '10'),
|
||||
getItem('Option 11', '11'),
|
||||
getItem('Option 12', '12'),
|
||||
]),
|
||||
];
|
||||
|
||||
const onClick: MenuProps['onClick'] = e => {
|
||||
console.log('click', e);
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<Menu onClick={handleClick} style={{ width: 256 }} mode="vertical">
|
||||
<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>
|
||||
</Menu.ItemGroup>
|
||||
<Menu.ItemGroup title="Item 2">
|
||||
<Menu.Item key="3">Option 3</Menu.Item>
|
||||
<Menu.Item key="4">Option 4</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
</SubMenu>
|
||||
<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">
|
||||
<Menu.Item key="7">Option 7</Menu.Item>
|
||||
<Menu.Item key="8">Option 8</Menu.Item>
|
||||
</SubMenu>
|
||||
</SubMenu>
|
||||
<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>,
|
||||
<Menu onClick={onClick} style={{ width: 256 }} mode="vertical" items={items} />,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
93
components/menu/hooks/useItems.tsx
Normal file
93
components/menu/hooks/useItems.tsx
Normal file
@ -0,0 +1,93 @@
|
||||
import * as React from 'react';
|
||||
import { ItemGroup } from 'rc-menu';
|
||||
import type {
|
||||
MenuItemType as RcMenuItemType,
|
||||
MenuDividerType as RcMenuDividerType,
|
||||
SubMenuType as RcSubMenuType,
|
||||
MenuItemGroupType as RcMenuItemGroupType,
|
||||
} from 'rc-menu/lib/interface';
|
||||
import SubMenu from '../SubMenu';
|
||||
import MenuDivider from '../MenuDivider';
|
||||
import MenuItem from '../MenuItem';
|
||||
|
||||
interface MenuItemType extends RcMenuItemType {
|
||||
danger?: boolean;
|
||||
icon?: React.ReactNode;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
interface SubMenuType extends Omit<RcSubMenuType, 'children'> {
|
||||
icon?: React.ReactNode;
|
||||
theme?: 'dark' | 'light';
|
||||
children: ItemType[];
|
||||
}
|
||||
|
||||
interface MenuItemGroupType extends Omit<RcMenuItemGroupType, 'children'> {
|
||||
children?: MenuItemType[];
|
||||
key?: React.Key;
|
||||
}
|
||||
|
||||
interface MenuDividerType extends RcMenuDividerType {
|
||||
dashed?: boolean;
|
||||
key?: React.Key;
|
||||
}
|
||||
|
||||
export type ItemType = MenuItemType | SubMenuType | MenuItemGroupType | MenuDividerType | null;
|
||||
|
||||
function convertItemsToNodes(list: ItemType[]) {
|
||||
return (list || [])
|
||||
.map((opt, index) => {
|
||||
if (opt && typeof opt === 'object') {
|
||||
const { label, children, key, type, ...restProps } = opt as any;
|
||||
const mergedKey = key ?? `tmp-${index}`;
|
||||
|
||||
// MenuItemGroup & SubMenuItem
|
||||
if (children || type === 'group') {
|
||||
if (type === 'group') {
|
||||
// Group
|
||||
return (
|
||||
<ItemGroup key={mergedKey} {...restProps} title={label}>
|
||||
{convertItemsToNodes(children)}
|
||||
</ItemGroup>
|
||||
);
|
||||
}
|
||||
|
||||
// Sub Menu
|
||||
return (
|
||||
<SubMenu key={mergedKey} {...restProps} title={label}>
|
||||
{convertItemsToNodes(children)}
|
||||
</SubMenu>
|
||||
);
|
||||
}
|
||||
|
||||
// MenuItem & Divider
|
||||
if (type === 'divider') {
|
||||
return <MenuDivider key={mergedKey} {...restProps} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<MenuItem key={mergedKey} {...restProps}>
|
||||
{label}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.filter(opt => opt);
|
||||
}
|
||||
|
||||
// FIXME: Move logic here in v5
|
||||
/**
|
||||
* We simply convert `items` to ReactNode for reuse origin component logic. But we need move all the
|
||||
* logic from component into this hooks when in v5
|
||||
*/
|
||||
export default function useItems(items?: ItemType[]) {
|
||||
return React.useMemo(() => {
|
||||
if (!items) {
|
||||
return items;
|
||||
}
|
||||
|
||||
return convertItemsToNodes(items);
|
||||
}, [items]);
|
||||
}
|
@ -22,12 +22,14 @@ More layouts with navigation: [Layout](/components/layout).
|
||||
## API
|
||||
|
||||
```jsx
|
||||
<Menu>
|
||||
<Menu.Item>Menu</Menu.Item>
|
||||
<SubMenu title="SubMenu">
|
||||
<Menu.Item>SubMenuItem</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
const items = [
|
||||
{ label: 'Menu' },
|
||||
{
|
||||
label: 'SubMenu',
|
||||
children: [{ label: 'SubMenuItem' }],
|
||||
},
|
||||
];
|
||||
<Menu items={items} />;
|
||||
```
|
||||
|
||||
### Menu
|
||||
@ -40,6 +42,7 @@ More layouts with navigation: [Layout](/components/layout).
|
||||
| forceSubMenuRender | Render submenu into DOM before it becomes visible | boolean | false | |
|
||||
| inlineCollapsed | Specifies the collapsed status when menu is inline mode | boolean | - | |
|
||||
| inlineIndent | Indent (in pixels) of inline menu items on each level | number | 24 | |
|
||||
| items | Menu item content | [ItemType\[\]](#ItemType) | - | 4.20.0 |
|
||||
| mode | Type of menu | `vertical` \| `horizontal` \| `inline` | `vertical` | |
|
||||
| multiple | Allows selection of multiple items | boolean | false | |
|
||||
| openKeys | Array with the keys of currently opened sub-menus | string\[] | - | |
|
||||
@ -58,14 +61,19 @@ More layouts with navigation: [Layout](/components/layout).
|
||||
|
||||
> More options in [rc-menu](https://github.com/react-component/menu#api)
|
||||
|
||||
### Menu.Item
|
||||
### ItemType
|
||||
|
||||
> type ItemType = [MenuItemType](#MenuItemType) | [SubMenuType](#SubMenuType) | [MenuItemGroupType](#MenuItemGroupType) | [MenuDividerType](#MenuDividerType);
|
||||
|
||||
#### MenuItemType
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| -------- | ------------------------------------ | --------- | ------------- | ------- |
|
||||
| danger | Display the danger style | boolean | false | 4.3.0 |
|
||||
| danger | Display the danger style | boolean | false | |
|
||||
| disabled | Whether menu item is disabled | boolean | false | |
|
||||
| icon | The icon of the menu item | ReactNode | - | 4.2.0 |
|
||||
| icon | The icon of the menu item | ReactNode | - | |
|
||||
| key | Unique ID of the menu item | string | - | |
|
||||
| label | Menu label | ReactNode | - | |
|
||||
| title | Set display title for collapsed item | string | - | |
|
||||
|
||||
> Note: `icon` is a newly added prop in `4.2.0`. For previous versions, please use the following method to define the icon.
|
||||
@ -87,34 +95,51 @@ More layouts with navigation: [Layout](/components/layout).
|
||||
> </Menu.SubMenu>
|
||||
> ```
|
||||
|
||||
### Menu.SubMenu
|
||||
#### SubMenuType
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| children | Sub-menus or sub-menu items | Array<MenuItem \| SubMenu> | - | |
|
||||
| children | Sub-menus or sub-menu items | [ItemType\[\]](#ItemType) | - | |
|
||||
| disabled | Whether sub-menu is disabled | boolean | false | |
|
||||
| icon | Icon of sub menu | ReactNode | - | 4.2.0 |
|
||||
| icon | Icon of sub menu | ReactNode | - | |
|
||||
| key | Unique ID of the sub-menu | string | - | |
|
||||
| label | Menu label | ReactNode | - | |
|
||||
| popupClassName | Sub-menu class name, not working when `mode="inline"` | string | - | |
|
||||
| popupOffset | Sub-menu offset, not working when `mode="inline"` | \[number, number] | - | |
|
||||
| title | Title of sub menu | ReactNode | - | |
|
||||
| theme | Color theme of the SubMenu (inherits from Menu by default) | | `light` \| `dark` | - | 4.19.0 |
|
||||
| theme | Color theme of the SubMenu (inherits from Menu by default) | | `light` \| `dark` | - | |
|
||||
| onTitleClick | Callback executed when the sub-menu title is clicked | function({ key, domEvent }) | - | |
|
||||
|
||||
### Menu.ItemGroup
|
||||
#### MenuItemGroupType
|
||||
|
||||
Define `type` as `group` to make as group:
|
||||
|
||||
```ts
|
||||
const groupItem = {
|
||||
type: 'group', // Must have
|
||||
label: 'My Group',
|
||||
chidlren: [],
|
||||
};
|
||||
```
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| -------- | ---------------------- | ----------- | ------------- | ------- |
|
||||
| children | Sub-menu items | MenuItem\[] | - | |
|
||||
| title | The title of the group | ReactNode | - | |
|
||||
| label | The title of the group | ReactNode | - | |
|
||||
|
||||
### Menu.Divider
|
||||
#### MenuDividerType
|
||||
|
||||
Divider line in between menu items, only used in vertical popup Menu or Dropdown Menu.
|
||||
Divider line in between menu items, only used in vertical popup Menu or Dropdown Menu. Need define the `type` as `divider`:
|
||||
|
||||
```ts
|
||||
const dividerItem = {
|
||||
type: 'divider', // Must have
|
||||
};
|
||||
```
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| ------ | ---------------------- | ------- | ------------- | ------- |
|
||||
| dashed | Whether line is dashed | boolean | false | 4.17.0 |
|
||||
| dashed | Whether line is dashed | boolean | false | |
|
||||
|
||||
## FAQ
|
||||
|
||||
|
@ -12,6 +12,8 @@ import collapseMotion from '../_util/motion';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
import MenuContext, { MenuTheme } from './MenuContext';
|
||||
import MenuDivider from './MenuDivider';
|
||||
import type { ItemType } from './hooks/useItems';
|
||||
import useItems from './hooks/useItems';
|
||||
|
||||
export { MenuDividerProps } from './MenuDivider';
|
||||
|
||||
@ -19,7 +21,7 @@ export { MenuItemGroupProps } from 'rc-menu';
|
||||
|
||||
export type MenuMode = 'vertical' | 'vertical-left' | 'vertical-right' | 'horizontal' | 'inline';
|
||||
|
||||
export interface MenuProps extends RcMenuProps {
|
||||
export interface MenuProps extends Omit<RcMenuProps, 'items'> {
|
||||
theme?: MenuTheme;
|
||||
inlineIndent?: number;
|
||||
|
||||
@ -29,6 +31,8 @@ export interface MenuProps extends RcMenuProps {
|
||||
* for removing.
|
||||
*/
|
||||
_internalDisableMenuItemTitleTooltip?: boolean;
|
||||
|
||||
items?: ItemType[];
|
||||
}
|
||||
|
||||
type InternalMenuProps = MenuProps &
|
||||
@ -49,11 +53,16 @@ function InternalMenu(props: InternalMenuProps) {
|
||||
_internalDisableMenuItemTitleTooltip,
|
||||
inlineCollapsed,
|
||||
siderCollapsed,
|
||||
items,
|
||||
children,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
const passedProps = omit(restProps, ['collapsedWidth']);
|
||||
|
||||
// ========================= Items ===========================
|
||||
const mergedChildren = useItems(items) || children;
|
||||
|
||||
// ======================== Warning ==========================
|
||||
devWarning(
|
||||
!('inlineCollapsed' in props && props.mode !== 'inline'),
|
||||
@ -67,6 +76,12 @@ function InternalMenu(props: InternalMenuProps) {
|
||||
'`inlineCollapsed` not control Menu under Sider. Should set `collapsed` on Sider instead.',
|
||||
);
|
||||
|
||||
devWarning(
|
||||
!!items && !children,
|
||||
'Menu',
|
||||
'`children` will be removed in next major version. Please use `items` instead.',
|
||||
);
|
||||
|
||||
// ======================== Collapsed ========================
|
||||
// Inline Collapsed
|
||||
const mergedInlineCollapsed = React.useMemo(() => {
|
||||
@ -114,7 +129,9 @@ function InternalMenu(props: InternalMenuProps) {
|
||||
expandIcon={cloneElement(expandIcon, {
|
||||
className: `${prefixCls}-submenu-expand-icon`,
|
||||
})}
|
||||
/>
|
||||
>
|
||||
{mergedChildren}
|
||||
</RcMenu>
|
||||
</MenuContext.Provider>
|
||||
);
|
||||
}
|
||||
|
@ -23,12 +23,15 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3XZcjGpvK/Menu.svg
|
||||
## API
|
||||
|
||||
```jsx
|
||||
<Menu>
|
||||
<Menu.Item>菜单项</Menu.Item>
|
||||
<SubMenu title="子菜单">
|
||||
<Menu.Item>子菜单项</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
const items = [
|
||||
{ label: '菜单项' },
|
||||
{
|
||||
label: '子菜单',
|
||||
children: [{ label: '子菜单项' }],
|
||||
},
|
||||
];
|
||||
|
||||
<Menu items={items} />;
|
||||
```
|
||||
|
||||
### Menu
|
||||
@ -41,6 +44,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3XZcjGpvK/Menu.svg
|
||||
| forceSubMenuRender | 在子菜单展示之前就渲染进 DOM | boolean | false | |
|
||||
| inlineCollapsed | inline 时菜单是否收起状态 | boolean | - | |
|
||||
| inlineIndent | inline 模式的菜单缩进宽度 | number | 24 | |
|
||||
| items | 菜单内容 | [ItemType\[\]](#ItemType) | - | 4.20.0 |
|
||||
| mode | 菜单类型,现在支持垂直、水平、和内嵌模式三种 | `vertical` \| `horizontal` \| `inline` | `vertical` | |
|
||||
| multiple | 是否允许多选 | boolean | false | |
|
||||
| openKeys | 当前展开的 SubMenu 菜单项 key 数组 | string\[] | - | |
|
||||
@ -59,15 +63,20 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3XZcjGpvK/Menu.svg
|
||||
|
||||
> 更多属性查看 [rc-menu](https://github.com/react-component/menu#api)
|
||||
|
||||
### Menu.Item
|
||||
### ItemType
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| -------- | ------------------------ | --------- | ------ | ----- |
|
||||
| danger | 展示错误状态样式 | boolean | false | 4.3.0 |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| icon | 菜单图标 | ReactNode | - | 4.2.0 |
|
||||
| key | item 的唯一标志 | string | - | |
|
||||
| title | 设置收缩时展示的悬浮标题 | string | - | |
|
||||
> type ItemType = [MenuItemType](#MenuItemType) | [SubMenuType](#SubMenuType) | [MenuItemGroupType](#MenuItemGroupType) | [MenuDividerType](#MenuDividerType);
|
||||
|
||||
#### MenuItemType
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| -------- | ------------------------ | --------- | ------ | ---- |
|
||||
| danger | 展示错误状态样式 | boolean | false | |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| icon | 菜单图标 | ReactNode | - | |
|
||||
| key | item 的唯一标志 | string | - | |
|
||||
| label | 菜单项标题 | string | - | |
|
||||
| title | 设置收缩时展示的悬浮标题 | string | - | |
|
||||
|
||||
> 注意:`icon` 是 `4.2.0` 新增的属性,之前的版本请使用下面的方式定义图标。
|
||||
>
|
||||
@ -88,34 +97,50 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3XZcjGpvK/Menu.svg
|
||||
> </Menu.SubMenu>
|
||||
> ```
|
||||
|
||||
### Menu.SubMenu
|
||||
#### SubMenuType
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| children | 子菜单的菜单项 | Array<MenuItem \| SubMenu> | - | |
|
||||
| children | 子菜单的菜单项 | [ItemType\[\]](#ItemType) | - | |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| icon | 菜单图标 | ReactNode | - | 4.2.0 |
|
||||
| icon | 菜单图标 | ReactNode | - | |
|
||||
| key | 唯一标志 | string | - | |
|
||||
| label | 菜单项标题 | ReactNode | - | |
|
||||
| popupClassName | 子菜单样式,`mode="inline"` 时无效 | string | - | |
|
||||
| popupOffset | 子菜单偏移量,`mode="inline"` 时无效 | \[number, number] | - | |
|
||||
| title | 子菜单项值 | ReactNode | - | |
|
||||
| onTitleClick | 点击子菜单标题 | function({ key, domEvent }) | - | |
|
||||
| theme | 设置子菜单的主题,默认从 Menu 上继承 | | `light` \| `dark` | - | 4.19.0 |
|
||||
| theme | 设置子菜单的主题,默认从 Menu 上继承 | | `light` \| `dark` | - | |
|
||||
|
||||
### Menu.ItemGroup
|
||||
#### MenuItemGroupType
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| -------- | ------------ | ----------- | ------ | ---- |
|
||||
| children | 分组的菜单项 | MenuItem\[] | - | |
|
||||
| title | 分组标题 | ReactNode | - | |
|
||||
定义类型为 `group` 时,会作为分组处理:
|
||||
|
||||
### Menu.Divider
|
||||
```ts
|
||||
const groupItem = {
|
||||
type: 'group', // Must have
|
||||
label: 'My Group',
|
||||
chidlren: [],
|
||||
};
|
||||
```
|
||||
|
||||
菜单项分割线,只用在弹出菜单内。
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| -------- | ------------ | --------------------------------- | ------ | ---- |
|
||||
| children | 分组的菜单项 | [MenuItemType\[\]](#MenuItemType) | - | |
|
||||
| label | 分组标题 | ReactNode | - | |
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| ------ | -------- | ------- | ------ | ------ |
|
||||
| dashed | 是否虚线 | boolean | false | 4.17.0 |
|
||||
#### MenuDividerType
|
||||
|
||||
菜单项分割线,只用在弹出菜单内,需要定义类型为 `divider`:
|
||||
|
||||
```ts
|
||||
const dividerItem = {
|
||||
type: 'divider', // Must have
|
||||
};
|
||||
```
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| ------ | -------- | ------- | ------ | ---- |
|
||||
| dashed | 是否虚线 | boolean | false | |
|
||||
|
||||
## FAQ
|
||||
|
||||
|
@ -20,23 +20,31 @@ import { MoreOutlined } from '@ant-design/icons';
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">
|
||||
1st menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">
|
||||
2nd menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">
|
||||
3rd menu item
|
||||
</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">
|
||||
1st menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">
|
||||
2nd menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">
|
||||
3rd menu item
|
||||
</a>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
const DropdownMenu = () => (
|
||||
|
@ -18,12 +18,7 @@ To see if bordered style applied to other tables.
|
||||
import { Table, Badge, Menu, Dropdown, Switch, Form, Space } from 'antd';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>Action 1</Menu.Item>
|
||||
<Menu.Item>Action 2</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
const menu = <Menu items={[{ label: 'Action 1' }, { label: 'Action 2' }]} />;
|
||||
|
||||
function NestedTable() {
|
||||
const createExpandedRowRender = bordered => () => {
|
||||
|
@ -17,12 +17,7 @@ Showing more detailed info of every row.
|
||||
import { Table, Badge, Menu, Dropdown, Space } from 'antd';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>Action 1</Menu.Item>
|
||||
<Menu.Item>Action 2</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
const menu = <Menu items={[{ label: 'Action 1' }, { label: 'Action 2' }]} />;
|
||||
|
||||
function NestedTable() {
|
||||
const expandedRowRender = () => {
|
||||
|
@ -4,6 +4,7 @@ import isEqual from 'lodash/isEqual';
|
||||
import FilterFilled from '@ant-design/icons/FilterFilled';
|
||||
import Button from '../../../button';
|
||||
import Menu from '../../../menu';
|
||||
import type { MenuProps } from '../../../menu';
|
||||
import Tree from '../../../tree';
|
||||
import type { DataNode, EventDataNode } from '../../../tree';
|
||||
import Checkbox from '../../../checkbox';
|
||||
@ -55,42 +56,42 @@ function renderFilterItems({
|
||||
filterMultiple: boolean;
|
||||
searchValue: string;
|
||||
filterSearch: FilterSearchType;
|
||||
}) {
|
||||
}): Required<MenuProps>['items'] {
|
||||
return filters.map((filter, index) => {
|
||||
const key = String(filter.value);
|
||||
|
||||
if (filter.children) {
|
||||
return (
|
||||
<Menu.SubMenu
|
||||
key={key || index}
|
||||
title={filter.text}
|
||||
popupClassName={`${prefixCls}-dropdown-submenu`}
|
||||
>
|
||||
{renderFilterItems({
|
||||
filters: filter.children,
|
||||
prefixCls,
|
||||
filteredKeys,
|
||||
filterMultiple,
|
||||
searchValue,
|
||||
filterSearch,
|
||||
})}
|
||||
</Menu.SubMenu>
|
||||
);
|
||||
return {
|
||||
key: key || index,
|
||||
label: filter.text,
|
||||
popupClassName: `${prefixCls}-dropdown-submenu`,
|
||||
children: renderFilterItems({
|
||||
filters: filter.children,
|
||||
prefixCls,
|
||||
filteredKeys,
|
||||
filterMultiple,
|
||||
searchValue,
|
||||
filterSearch,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
const Component = filterMultiple ? Checkbox : Radio;
|
||||
|
||||
const item = (
|
||||
<Menu.Item key={filter.value !== undefined ? key : index}>
|
||||
<Component checked={filteredKeys.includes(key)} />
|
||||
<span>{filter.text}</span>
|
||||
</Menu.Item>
|
||||
);
|
||||
const item = {
|
||||
key: filter.value !== undefined ? key : index,
|
||||
label: (
|
||||
<>
|
||||
<Component checked={filteredKeys.includes(key)} />
|
||||
<span>{filter.text}</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
if (searchValue.trim()) {
|
||||
if (typeof filterSearch === 'function') {
|
||||
return filterSearch(searchValue, filter) ? item : undefined;
|
||||
return filterSearch(searchValue, filter) ? item : null;
|
||||
}
|
||||
return searchValueMatched(searchValue, filter.text) ? item : undefined;
|
||||
return searchValueMatched(searchValue, filter.text) ? item : null;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
@ -381,8 +382,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
||||
getPopupContainer={getPopupContainer}
|
||||
openKeys={openKeys}
|
||||
onOpenChange={onOpenChange}
|
||||
>
|
||||
{renderFilterItems({
|
||||
items={renderFilterItems({
|
||||
filters: column.filters || [],
|
||||
filterSearch,
|
||||
prefixCls,
|
||||
@ -390,7 +390,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
||||
filterMultiple,
|
||||
searchValue,
|
||||
})}
|
||||
</Menu>
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -405,21 +405,20 @@ export default function useSelection<RecordType>(
|
||||
let customizeSelections: React.ReactNode;
|
||||
if (mergedSelections) {
|
||||
const menu = (
|
||||
<Menu getPopupContainer={getPopupContainer}>
|
||||
{mergedSelections.map((selection, index) => {
|
||||
<Menu
|
||||
getPopupContainer={getPopupContainer}
|
||||
items={mergedSelections.map((selection, index) => {
|
||||
const { key, text, onSelect: onSelectionClick } = selection;
|
||||
return (
|
||||
<Menu.Item
|
||||
key={key || index}
|
||||
onClick={() => {
|
||||
onSelectionClick?.(recordKeys);
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Menu.Item>
|
||||
);
|
||||
|
||||
return {
|
||||
key: key || index,
|
||||
onClick: () => {
|
||||
onSelectionClick?.(recordKeys);
|
||||
},
|
||||
label: text,
|
||||
};
|
||||
})}
|
||||
</Menu>
|
||||
/>
|
||||
);
|
||||
customizeSelections = (
|
||||
<div className={`${prefixCls}-selection-extra`}>
|
||||
|
@ -365,88 +365,85 @@ export default class TransferList<
|
||||
|
||||
let menu: React.ReactElement | null = null;
|
||||
if (showRemove) {
|
||||
menu = (
|
||||
<Menu>
|
||||
{/* Remove Current Page */}
|
||||
{pagination && (
|
||||
<Menu.Item
|
||||
key="removeCurrent"
|
||||
onClick={() => {
|
||||
const items = [
|
||||
/* Remove Current Page */
|
||||
pagination
|
||||
? {
|
||||
key: 'removeCurrent',
|
||||
onClick: () => {
|
||||
const pageKeys = getEnabledItemKeys(
|
||||
(this.defaultListBodyRef.current?.getItems() || []).map(entity => entity.item),
|
||||
);
|
||||
onItemRemove?.(pageKeys);
|
||||
}}
|
||||
>
|
||||
{removeCurrent}
|
||||
</Menu.Item>
|
||||
)}
|
||||
},
|
||||
label: removeCurrent,
|
||||
}
|
||||
: null,
|
||||
|
||||
{/* Remove All */}
|
||||
<Menu.Item
|
||||
key="removeAll"
|
||||
onClick={() => {
|
||||
onItemRemove?.(getEnabledItemKeys(filteredItems));
|
||||
}}
|
||||
>
|
||||
{removeAll}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
/* Remove All */
|
||||
{
|
||||
key: 'removeAll',
|
||||
onClick: () => {
|
||||
onItemRemove?.(getEnabledItemKeys(filteredItems));
|
||||
},
|
||||
label: removeAll,
|
||||
},
|
||||
].filter(item => item);
|
||||
|
||||
menu = <Menu items={items} />;
|
||||
} else {
|
||||
menu = (
|
||||
<Menu>
|
||||
<Menu.Item
|
||||
key="selectAll"
|
||||
onClick={() => {
|
||||
const keys = getEnabledItemKeys(filteredItems);
|
||||
onItemSelectAll(keys, keys.length !== checkedKeys.length);
|
||||
}}
|
||||
>
|
||||
{selectAll}
|
||||
</Menu.Item>
|
||||
{pagination && (
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
const items = [
|
||||
{
|
||||
key: 'selectAll',
|
||||
onClick: () => {
|
||||
const keys = getEnabledItemKeys(filteredItems);
|
||||
onItemSelectAll(keys, keys.length !== checkedKeys.length);
|
||||
},
|
||||
label: selectAll,
|
||||
},
|
||||
pagination
|
||||
? {
|
||||
key: 'selectCurrent',
|
||||
onClick: () => {
|
||||
const pageItems = this.defaultListBodyRef.current?.getItems() || [];
|
||||
onItemSelectAll(getEnabledItemKeys(pageItems.map(entity => entity.item)), true);
|
||||
}}
|
||||
>
|
||||
{selectCurrent}
|
||||
</Menu.Item>
|
||||
)}
|
||||
<Menu.Item
|
||||
key="selectInvert"
|
||||
onClick={() => {
|
||||
let availableKeys: string[];
|
||||
if (pagination) {
|
||||
availableKeys = getEnabledItemKeys(
|
||||
(this.defaultListBodyRef.current?.getItems() || []).map(entity => entity.item),
|
||||
);
|
||||
},
|
||||
label: selectCurrent,
|
||||
}
|
||||
: null,
|
||||
|
||||
{
|
||||
key: 'selectInvert',
|
||||
onClick: () => {
|
||||
let availableKeys: string[];
|
||||
if (pagination) {
|
||||
availableKeys = getEnabledItemKeys(
|
||||
(this.defaultListBodyRef.current?.getItems() || []).map(entity => entity.item),
|
||||
);
|
||||
} else {
|
||||
availableKeys = getEnabledItemKeys(filteredItems);
|
||||
}
|
||||
|
||||
const checkedKeySet = new Set(checkedKeys);
|
||||
const newCheckedKeys: string[] = [];
|
||||
const newUnCheckedKeys: string[] = [];
|
||||
|
||||
availableKeys.forEach(key => {
|
||||
if (checkedKeySet.has(key)) {
|
||||
newUnCheckedKeys.push(key);
|
||||
} else {
|
||||
availableKeys = getEnabledItemKeys(filteredItems);
|
||||
newCheckedKeys.push(key);
|
||||
}
|
||||
});
|
||||
|
||||
const checkedKeySet = new Set(checkedKeys);
|
||||
const newCheckedKeys: string[] = [];
|
||||
const newUnCheckedKeys: string[] = [];
|
||||
onItemSelectAll(newCheckedKeys, true);
|
||||
onItemSelectAll(newUnCheckedKeys, false);
|
||||
},
|
||||
label: selectInvert,
|
||||
},
|
||||
];
|
||||
|
||||
availableKeys.forEach(key => {
|
||||
if (checkedKeySet.has(key)) {
|
||||
newUnCheckedKeys.push(key);
|
||||
} else {
|
||||
newCheckedKeys.push(key);
|
||||
}
|
||||
});
|
||||
|
||||
onItemSelectAll(newCheckedKeys, true);
|
||||
onItemSelectAll(newUnCheckedKeys, false);
|
||||
}}
|
||||
>
|
||||
{selectInvert}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
menu = <Menu items={items} />;
|
||||
}
|
||||
|
||||
const dropdown = (
|
||||
|
@ -132,7 +132,7 @@
|
||||
"rc-input": "~0.0.1-alpha.5",
|
||||
"rc-input-number": "~7.3.0",
|
||||
"rc-mentions": "~1.6.1",
|
||||
"rc-menu": "~9.3.2",
|
||||
"rc-menu": "~9.5.1",
|
||||
"rc-motion": "^2.4.4",
|
||||
"rc-notification": "~4.5.7",
|
||||
"rc-pagination": "~3.1.9",
|
||||
|
Loading…
Reference in New Issue
Block a user