Skip to content

Commit eba8f6b

Browse files
committed
feat: menu items icon add arg
1 parent 760c4c2 commit eba8f6b

File tree

7 files changed

+44
-32
lines changed

7 files changed

+44
-32
lines changed

components/menu/demo/horizontal.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ Horizontal top navigation menu.
2222
<script lang="ts" setup>
2323
import { h, ref } from 'vue';
2424
import { MailOutlined, AppstoreOutlined, SettingOutlined } from '@ant-design/icons-vue';
25+
import { MenuProps } from 'ant-design-vue';
2526
const current = ref<string[]>(['mail']);
26-
const items = ref([
27+
const items = ref<MenuProps['items']>([
2728
{
2829
key: 'mail',
2930
icon: () => h(MailOutlined),

components/menu/index.en-US.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,14 @@ More layouts with navigation: [Layout](/components/layout).
6666
6767
#### MenuItemType
6868

69-
| Param | Description | Type | Default value | Version |
70-
| -------- | ------------------------------------ | ------- | ------------- | ------- |
71-
| danger | Display the danger style | boolean | false | |
72-
| disabled | Whether menu item is disabled | boolean | false | |
73-
| icon | The icon of the menu item | VueNode | - | |
74-
| key | Unique ID of the menu item | string | - | |
75-
| label | Menu label | VueNode | - | |
76-
| title | Set display title for collapsed item | string | - | |
69+
| Param | Description | Type | Default value | Version |
70+
| --- | --- | --- | --- | --- |
71+
| danger | Display the danger style | boolean | false | |
72+
| disabled | Whether menu item is disabled | boolean | false | |
73+
| icon | The icon of the menu item | VueNode \| (item: MenuItemType) => VNode | - | |
74+
| key | Unique ID of the menu item | string | - | |
75+
| label | Menu label | VueNode | - | |
76+
| title | Set display title for collapsed item | string | - | |
7777

7878
#### SubMenuType
7979

@@ -82,7 +82,7 @@ More layouts with navigation: [Layout](/components/layout).
8282
| --- | --- | --- | --- | --- |
8383
| children | Sub-menus or sub-menu items | [ItemType\[\]](#ItemType) | - | |
8484
| disabled | Whether sub-menu is disabled | boolean | false | |
85-
| icon | Icon of sub menu | VueNode\|()=>VueNode | - | |
85+
| icon | Icon of sub menu | VueNode \| (item: SubMenuType) => VueNode | - | |
8686
| key | Unique ID of the sub-menu | string | - | |
8787
| label | Menu label | VueNode | - | |
8888
| popupClassName | Sub-menu class name, not working when `mode="inline"` | string | - | |

components/menu/index.zh-CN.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,22 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*Vn4XSqJFAxcAAA
6767
6868
### MenuItemType
6969

70-
| 参数 | 说明 | 类型 | 默认值 | 版本 |
71-
| -------- | ------------------------ | -------------------- | ------ | ---- |
72-
| danger | 展示错误状态样式 | boolean | false | |
73-
| disabled | 是否禁用 | boolean | false | |
74-
| icon | 菜单图标 | VueNode\|()=>VueNode | - | |
75-
| key | item 的唯一标志 | string | - | |
76-
| label | 菜单项标题 | VueNode | - | |
77-
| title | 设置收缩时展示的悬浮标题 | string | - | |
70+
| 参数 | 说明 | 类型 | 默认值 | 版本 |
71+
| -------- | ------------------------ | -------------------------------------- | ------ | ---- |
72+
| danger | 展示错误状态样式 | boolean | false | |
73+
| disabled | 是否禁用 | boolean | false | |
74+
| icon | 菜单图标 | VueNode\|(item: MenuItemType)=>VueNode | - | |
75+
| key | item 的唯一标志 | string | - | |
76+
| label | 菜单项标题 | VueNode | - | |
77+
| title | 设置收缩时展示的悬浮标题 | string | - | |
7878

7979
#### SubMenuType
8080

8181
| 参数 | 说明 | 类型 | 默认值 | 版本 |
8282
| --- | --- | --- | --- | --- |
8383
| children | 子菜单的菜单项 | [ItemType\[\]](#ItemType) | - | |
8484
| disabled | 是否禁用 | boolean | false | |
85-
| icon | 菜单图标 | VueNode\|()=>VueNode | - | |
85+
| icon | 菜单图标 | VueNode\|(item: SubMenuType)=>VueNode | - | |
8686
| key | 唯一标志 | string | - | |
8787
| label | 菜单项标题 | VueNode | - | |
8888
| popupClassName | 子菜单样式,`mode="inline"` 时无效 | string | - | |

components/menu/src/ItemGroup.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@ import { computed, defineComponent } from 'vue';
44
import PropTypes from '../../_util/vue-types';
55
import { useInjectMenu } from './hooks/useMenuContext';
66
import { useMeasure } from './hooks/useKeyPath';
7+
import type { ItemType } from './interface';
8+
import { objectType } from '../../_util/type';
79

810
export const menuItemGroupProps = () => ({
911
title: PropTypes.any,
12+
// Internal user prop
13+
originItemValue: objectType<ItemType>(),
1014
});
1115

1216
export type MenuItemGroupProps = Partial<ExtractPropTypes<ReturnType<typeof menuItemGroupProps>>>;

components/menu/src/MenuItem.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { flattenChildren, getPropsSlot, isValidElement } from '../../_util/props-util';
1+
import { flattenChildren, isValidElement } from '../../_util/props-util';
22
import PropTypes from '../../_util/vue-types';
33
import type { ExtractPropTypes, PropType } from 'vue';
44
import {
@@ -13,12 +13,13 @@ import { useInjectKeyPath, useMeasure } from './hooks/useKeyPath';
1313
import { useInjectFirstLevel, useInjectMenu } from './hooks/useMenuContext';
1414
import { cloneElement } from '../../_util/vnode';
1515
import Tooltip from '../../tooltip';
16-
import type { MenuInfo } from './interface';
16+
import type { ItemType, MenuInfo } from './interface';
1717
import KeyCode from '../../_util/KeyCode';
1818
import useDirectionStyle from './hooks/useDirectionStyle';
1919
import Overflow from '../../vc-overflow';
2020
import devWarning from '../../vc-util/devWarning';
2121
import type { MouseEventHandler } from '../../_util/EventInterface';
22+
import { objectType } from '../../_util/type';
2223

2324
let indexGuid = 0;
2425
export const menuItemProps = () => ({
@@ -33,6 +34,8 @@ export const menuItemProps = () => ({
3334
onClick: Function as PropType<MouseEventHandler>,
3435
onKeydown: Function as PropType<MouseEventHandler>,
3536
onFocus: Function as PropType<MouseEventHandler>,
37+
// Internal user prop
38+
originItemValue: objectType<ItemType>(),
3639
});
3740

3841
export type MenuItemProps = Partial<ExtractPropTypes<ReturnType<typeof menuItemProps>>>;
@@ -215,7 +218,7 @@ export default defineComponent({
215218
optionRoleProps['aria-selected'] = selected.value;
216219
}
217220

218-
const icon = getPropsSlot(slots, props, 'icon');
221+
const icon = props.icon ?? slots.icon?.(props);
219222
return (
220223
<Tooltip
221224
{...tooltipProps}
@@ -248,7 +251,7 @@ export default defineComponent({
248251
title={typeof title === 'string' ? title : undefined}
249252
>
250253
{cloneElement(
251-
typeof icon === 'function' ? icon() : icon,
254+
typeof icon === 'function' ? icon(props.originItemValue) : icon,
252255
{
253256
class: `${prefixCls.value}-item-icon`,
254257
},

components/menu/src/SubMenu.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ import devWarning from '../../vc-util/devWarning';
2828
import isValid from '../../_util/isValid';
2929
import type { MouseEventHandler } from '../../_util/EventInterface';
3030
import type { Key } from '../../_util/type';
31-
import type { MenuTheme } from './interface';
31+
import { objectType } from '../../_util/type';
32+
import type { ItemType, MenuTheme } from './interface';
3233

3334
let indexGuid = 0;
3435

@@ -46,6 +47,9 @@ export const subMenuProps = () => ({
4647
onMouseenter: Function as PropType<MouseEventHandler>,
4748
onMouseleave: Function as PropType<MouseEventHandler>,
4849
onTitleClick: Function as PropType<(e: MouseEvent, key: Key) => void>,
50+
51+
// Internal user prop
52+
originItemValue: objectType<ItemType>(),
4953
});
5054

5155
export type SubMenuProps = Partial<ExtractPropTypes<ReturnType<typeof subMenuProps>>>;
@@ -224,7 +228,7 @@ export default defineComponent({
224228
return (
225229
<>
226230
{cloneElement(
227-
typeof icon === 'function' ? icon() : icon,
231+
typeof icon === 'function' ? icon(props.originItemValue) : icon,
228232
{
229233
class: `${prefixCls.value}-item-icon`,
230234
},
@@ -247,7 +251,7 @@ export default defineComponent({
247251
);
248252
const baseTitleNode = () => {
249253
const subMenuPrefixClsValue = subMenuPrefixCls.value;
250-
const icon = getPropsSlot(slots, props, 'icon');
254+
const icon = props.icon ?? slots.icon?.(props);
251255
const expandIcon = props.expandIcon || slots.expandIcon || menuExpandIcon.value;
252256
const title = renderTitle(getPropsSlot(slots, props, 'title'), icon);
253257
return (

components/menu/src/hooks/useItems.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ import ItemGroup from '../ItemGroup';
99
import MenuDivider from '../Divider';
1010
import MenuItem from '../MenuItem';
1111
import type { Key } from '../../../_util/type';
12+
import type { VNode } from 'vue';
1213
import { ref, shallowRef, watch } from 'vue';
1314
import type { MenuProps } from '../Menu';
1415
import type { StoreMenuInfo } from './useMenuContext';
1516

1617
export interface MenuItemType extends VcMenuItemType {
1718
danger?: boolean;
18-
icon?: any;
19+
icon?: VNode | ((item: MenuItemType) => VNode);
1920
title?: string;
2021
}
2122

2223
export interface SubMenuType extends Omit<VcSubMenuType, 'children'> {
23-
icon?: any;
24-
theme?: 'dark' | 'light';
24+
icon?: VNode | ((item: SubMenuType) => VNode);
2525
children: ItemType[];
2626
}
2727

@@ -69,7 +69,7 @@ function convertItemsToNodes(
6969
const childrenNodes = convertItemsToNodes(children, store, parentMenuInfo);
7070
// Group
7171
return (
72-
<ItemGroup key={mergedKey} {...restProps} title={label}>
72+
<ItemGroup key={mergedKey} {...restProps} title={label} originItemValue={opt}>
7373
{childrenNodes}
7474
</ItemGroup>
7575
);
@@ -84,7 +84,7 @@ function convertItemsToNodes(
8484
parentKeys: [].concat(parentKeys, mergedKey),
8585
});
8686
return (
87-
<SubMenu key={mergedKey} {...restProps} title={label}>
87+
<SubMenu key={mergedKey} {...restProps} title={label} originItemValue={opt}>
8888
{childrenNodes}
8989
</SubMenu>
9090
);
@@ -97,7 +97,7 @@ function convertItemsToNodes(
9797
menuInfo.isLeaf = true;
9898
store.set(mergedKey, menuInfo);
9999
return (
100-
<MenuItem key={mergedKey} {...restProps}>
100+
<MenuItem key={mergedKey} {...restProps} originItemValue={opt}>
101101
{label}
102102
</MenuItem>
103103
);

0 commit comments

Comments
 (0)