feat: Menu support expandIcon (#27565)

* style: optimize menu expand icon color

close #20035

* feat: 🆕 support Menu expandIcon

* revert arrow color
This commit is contained in:
偏右 2020-11-06 15:25:43 +08:00 committed by GitHub
parent 8f18328aad
commit 756a1dffea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 78 deletions

View File

@ -31,6 +31,7 @@ More layouts with navigation: [Layout](/components/layout).
| --- | --- | --- | --- | --- |
| defaultOpenKeys | Array with the keys of default opened sub menus | string\[] | - | |
| defaultSelectedKeys | Array with the keys of default selected menu items | string\[] | - | |
| expandIcon | custom expand icon of submenu | ReactNode \| `(props: SubMenuProps & { isSubMenu: boolean }) => ReactNode` | - | 4.9.0 |
| 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 | |

View File

@ -7,6 +7,7 @@ import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import devWarning from '../_util/devWarning';
import { SiderContext, SiderContextProps } from '../layout/Sider';
import collapseMotion from '../_util/motion';
import { cloneElement } from '../_util/reactNode';
import MenuContext, { MenuTheme } from './MenuContext';
export { MenuItemGroupProps } from 'rc-menu';
@ -53,7 +54,7 @@ class InternalMenu extends React.Component<InternalMenuProps> {
}
renderMenu = ({ getPopupContainer, getPrefixCls, direction }: ConfigConsumerProps) => {
const { prefixCls: customizePrefixCls, className, theme } = this.props;
const { prefixCls: customizePrefixCls, className, theme, expandIcon } = this.props;
const defaultMotions = {
horizontal: { motionName: 'slide-up' },
inline: collapseMotion,
@ -84,6 +85,9 @@ class InternalMenu extends React.Component<InternalMenuProps> {
prefixCls={prefixCls}
direction={direction}
defaultMotions={defaultMotions}
expandIcon={cloneElement(expandIcon, {
className: `${prefixCls}-submenu-expand-icon`,
})}
/>
</MenuContext.Provider>
);

View File

@ -32,6 +32,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3XZcjGpvK/Menu.svg
| --- | --- | --- | --- | --- |
| defaultOpenKeys | 初始展开的 SubMenu 菜单项 key 数组 | string\[] | - | |
| defaultSelectedKeys | 初始选中的菜单项 key 数组 | string\[] | - | |
| expandIcon | 自定义展开图标 | ReactNode \| `(props: SubMenuProps & { isSubMenu: boolean }) => ReactNode` | - | 4.9.0 |
| forceSubMenuRender | 在子菜单展示之前就渲染进 DOM | boolean | false | |
| inlineCollapsed | inline 时菜单是否收起状态 | boolean | - | |
| inlineIndent | inline 模式的菜单缩进宽度 | number | 24 | |

View File

@ -42,12 +42,12 @@
}
&-horizontal &-submenu {
transition: border-color 0.3s @ease-in-out, background 0.3s @ease-in-out;
transition: border-color 0.3s ease-in-out, background 0.3s ease-in-out;
}
&-submenu,
&-submenu-inline {
transition: border-color 0.3s @ease-in-out, background 0.3s @ease-in-out,
padding 0.15s @ease-in-out;
transition: border-color 0.3s ease-in-out, background 0.3s ease-in-out,
padding 0.15s ease-in-out;
}
&-submenu-selected {
@ -61,7 +61,7 @@
&-submenu &-sub {
cursor: initial;
transition: background 0.3s @ease-in-out, padding 0.3s @ease-in-out;
transition: background 0.3s ease-in-out, padding 0.3s ease-in-out;
}
&-item a {
@ -173,9 +173,9 @@
&-horizontal &-item,
&-horizontal &-submenu-title {
transition: color 0.3s @ease-in-out, border-color 0.3s @ease-in-out,
background 0.3s @ease-in-out;
transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background 0.3s ease-in-out;
}
&-item,
&-submenu-title {
position: relative;
@ -184,16 +184,16 @@
padding: @menu-item-padding;
white-space: nowrap;
cursor: pointer;
transition: color 0.3s @ease-in-out, border-color 0.3s @ease-in-out,
background 0.3s @ease-in-out, padding 0.15s @ease-in-out;
transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background 0.3s ease-in-out,
padding 0.15s ease-in-out;
.@{iconfont-css-prefix} {
min-width: 14px;
margin-right: @menu-icon-margin-right;
font-size: @menu-icon-size;
transition: font-size 0.15s @ease-out, margin 0.3s @ease-in-out;
transition: font-size 0.15s ease-out, margin 0.3s ease-in-out, color 0.3s ease-in-out;
+ span {
opacity: 1;
transition: opacity 0.3s @ease-in-out, width 0.3s @ease-in-out;
transition: opacity 0.3s ease-in-out, width 0.3s ease-in-out, color 0.3s ease-in-out;
}
}
@ -245,7 +245,7 @@
background-color: @menu-bg;
border-radius: @border-radius-base;
&-submenu-title::after {
transition: transform 0.3s @ease-in-out;
transition: transform 0.3s ease-in-out;
}
}
@ -253,78 +253,62 @@
background-color: @menu-popup-bg;
}
&-vertical,
&-vertical-left,
&-vertical-right,
&-inline {
> .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow {
&-expand-icon,
&-arrow {
position: absolute;
top: 50%;
right: 16px;
width: 10px;
color: @menu-item-color;
transform: translateY(-50%);
transition: transform 0.3s ease-in-out;
}
&-arrow {
&::before,
&::after {
position: absolute;
top: 50%;
right: 16px;
width: 10px;
transition: transform 0.3s @ease-in-out;
&::before,
&::after {
position: absolute;
width: 6px;
height: 1.5px;
// background + background-image to makes before & after cross have same color.
// ref: https://github.com/ant-design/ant-design/issues/15910
background-image: linear-gradient(to right, @menu-item-color, @menu-item-color);
border-radius: 2px;
transition: background 0.3s @ease-in-out, transform 0.3s @ease-in-out,
top 0.3s @ease-in-out;
content: '';
}
&::before {
transform: rotate(45deg) translateY(-2px);
}
&::after {
transform: rotate(-45deg) translateY(2px);
}
width: 6px;
height: 1.5px;
background-color: currentColor;
border-radius: 2px;
transition: background 0.3s ease-in-out, transform 0.3s ease-in-out, top 0.3s ease-in-out,
color 0.3s ease-in-out;
content: '';
}
> .@{menu-prefix-cls}-submenu-title:hover .@{menu-prefix-cls}-submenu-arrow {
&::after,
&::before {
background: linear-gradient(to right, @menu-highlight-color, @menu-highlight-color);
}
}
}
&-vertical,
&-vertical-left,
&-vertical-right {
> .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow {
&::before {
transform: rotate(45deg) translateY(-2px);
}
&::after {
transform: rotate(-45deg) translateY(2px);
}
}
}
&-inline > .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow {
&::before {
transform: rotate(-45deg) translateX(2px);
transform: rotate(45deg) translateY(-2.5px);
}
&::after {
transform: rotate(45deg) translateX(-2px);
transform: rotate(-45deg) translateY(2.5px);
}
}
&-open {
&.@{menu-prefix-cls}-submenu-inline
> .@{menu-prefix-cls}-submenu-title
.@{menu-prefix-cls}-submenu-arrow {
transform: translateY(-2px);
&::after {
transform: rotate(-45deg) translateX(-2px);
}
&::before {
transform: rotate(45deg) translateX(2px);
}
&:hover &-expand-icon,
&:hover &-arrow {
color: @menu-highlight-color;
}
&-inline &-arrow {
&::before {
transform: rotate(-45deg) translateX(2.5px);
}
&::after {
transform: rotate(45deg) translateX(-2.5px);
}
}
&-horizontal &-arrow {
display: none;
}
&-open&-inline &-arrow {
transform: translateY(-2px);
&::after {
transform: rotate(-45deg) translateX(-2.5px);
}
&::before {
transform: rotate(45deg) translateX(2.5px);
}
}
}
@ -411,7 +395,7 @@
border-right: @menu-item-active-border-width solid @menu-highlight-color;
transform: scaleY(0.0001);
opacity: 0;
transition: transform 0.15s @ease-out, opacity 0.15s @ease-out;
transition: transform 0.15s ease-out, opacity 0.15s ease-out;
content: '';
}
}
@ -456,7 +440,7 @@
&::after {
transform: scaleY(1);
opacity: 1;
transition: transform 0.15s @ease-in-out, opacity 0.15s @ease-in-out;
transition: transform 0.15s ease-in-out, opacity 0.15s ease-in-out;
}
}