feat: menu divider add dashed
parent
c341258241
commit
32fc4fc7c4
|
@ -19,14 +19,16 @@ const collapseMotion = (name = 'ant-motion-collapse'): CSSMotionProps => {
|
|||
});
|
||||
},
|
||||
onAfterEnter: (node: HTMLDivElement) => {
|
||||
if (node) removeClass(node, name);
|
||||
node.style.height = undefined;
|
||||
node.style.opacity = undefined;
|
||||
if (node) {
|
||||
removeClass(node, name);
|
||||
node.style.height = null;
|
||||
node.style.opacity = null;
|
||||
}
|
||||
},
|
||||
onBeforeLeave: (node: HTMLDivElement) => {
|
||||
addClass(node, name);
|
||||
node.style.height = `${node.offsetHeight}px`;
|
||||
node.style.opacity = undefined;
|
||||
node.style.opacity = null;
|
||||
},
|
||||
onLeave: (node: HTMLDivElement) => {
|
||||
setTimeout(() => {
|
||||
|
@ -35,9 +37,13 @@ const collapseMotion = (name = 'ant-motion-collapse'): CSSMotionProps => {
|
|||
});
|
||||
},
|
||||
onAfterLeave: (node: HTMLDivElement) => {
|
||||
if (node) removeClass(node, name);
|
||||
node.style.height = undefined;
|
||||
node.style.opacity = undefined;
|
||||
if (node) {
|
||||
removeClass(node, name);
|
||||
if (node.style) {
|
||||
node.style.height = null;
|
||||
node.style.opacity = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -10,10 +10,16 @@ A versatile menu for navigation.
|
|||
|
||||
## When To Use
|
||||
|
||||
Navigation is an important part of any website, as a good navigation setup allows users to move around the site quickly and efficiently. Ant Design offers top and side navigation options. Top navigation provides all the categories and functions of the website. Side navigation provides the multi-level structure of the website.
|
||||
Navigation is an important part of any website, as a good navigation setup allows users to move around the site quickly and efficiently. Ant Design offers two navigation options: top and side. Top navigation provides all the categories and functions of the website. Side navigation provides the multi-level structure of the website.
|
||||
|
||||
More layouts with navigation: [Layout](/components/layout).
|
||||
|
||||
## Notes for developers
|
||||
|
||||
- Menu is rendered as a `ul` element, so it only supports [`li` and `script-supporting` elements](https://html.spec.whatwg.org/multipage/grouping-content.html#the-ul-element) as children nodes。Your customized node should be wrapped by `Menu.Item`.
|
||||
- Menu needs to collect its node structure, so its children should be `Menu.*` or encapsulated HOCs.
|
||||
- Must set unique key for `SubMenu`
|
||||
|
||||
## API
|
||||
|
||||
```html
|
||||
|
@ -95,3 +101,13 @@ The children of Menu.ItemGroup must be `MenuItem`.
|
|||
### Menu.Divider
|
||||
|
||||
Divider line in between menu items, only used in vertical popup Menu or Dropdown Menu.
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| ------ | ---------------------- | ------- | ------------- | ------- |
|
||||
| dashed | Whether line is dashed | boolean | false | 4.17.0 |
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why will Menu's children be rendered twice?
|
||||
|
||||
Menu collects structure info with twice-render to support HOC usage. Merging into one render may cause the logic to become much more complex. Contributions to help improve the collection logic are welcomed.
|
||||
|
|
|
@ -15,6 +15,12 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3XZcjGpvK/Menu.svg
|
|||
|
||||
更多布局和导航的使用可以参考:[通用布局](/components/layout-cn)。
|
||||
|
||||
## 开发者注意事项
|
||||
|
||||
- Menu 元素为 `ul`,因而仅支持 [`li` 以及 `script-supporting` 子元素](https://html.spec.whatwg.org/multipage/grouping-content.html#the-ul-element)。因而你的子节点元素应该都在 `Menu.Item` 内使用。
|
||||
- Menu 需要计算节点结构,因而其子元素仅支持 `Menu.*` 以及对此进行封装的 HOC 组件。
|
||||
- 必须为 SubMenu 设置唯一 key
|
||||
|
||||
## API
|
||||
|
||||
```html
|
||||
|
@ -96,3 +102,13 @@ Menu.ItemGroup 的子元素必须是 `MenuItem`.
|
|||
### Menu.Divider
|
||||
|
||||
菜单项分割线,只用在弹出菜单内。
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| ------ | -------- | ------- | ------ | ---- |
|
||||
| dashed | 是否虚线 | boolean | false | 3.0 |
|
||||
|
||||
## FAQ
|
||||
|
||||
### 为何 Menu 的子元素会渲染两次?
|
||||
|
||||
Menu 通过二次渲染收集嵌套结构信息以支持 HOC 的结构。合并成一个推导结构会使得逻辑变得十分复杂,欢迎 PR 以协助改进该设计。
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
import { defineComponent } from 'vue';
|
||||
import { useInjectMenu } from './hooks/useMenuContext';
|
||||
import useConfigInject from '../../_util/hooks/useConfigInject';
|
||||
import { computed, defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AMenuDivider',
|
||||
setup() {
|
||||
const { prefixCls } = useInjectMenu();
|
||||
props: {
|
||||
prefixCls: String,
|
||||
dashed: Boolean,
|
||||
},
|
||||
setup(props) {
|
||||
const { prefixCls } = useConfigInject('menu', props);
|
||||
const cls = computed(() => {
|
||||
return {
|
||||
[`${prefixCls.value}-item-divider`]: true,
|
||||
[`${prefixCls.value}-item-divider-dashed`]: !!props.dashed,
|
||||
};
|
||||
});
|
||||
return () => {
|
||||
return <li class={`${prefixCls.value}-item-divider`} />;
|
||||
return <li class={cls.value} />;
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,7 +17,6 @@ import type {
|
|||
} from './interface';
|
||||
import devWarning from '../../vc-util/devWarning';
|
||||
import type { CSSMotionProps } from '../../_util/transition';
|
||||
import { collapseMotion } from '../../_util/transition';
|
||||
import uniq from 'lodash-es/uniq';
|
||||
import { SiderCollapsedKey } from '../../layout/injectionKey';
|
||||
import { flattenChildren } from '../../_util/props-util';
|
||||
|
@ -28,6 +27,7 @@ import EllipsisOutlined from '@ant-design/icons-vue/EllipsisOutlined';
|
|||
import { cloneElement } from '../../_util/vnode';
|
||||
import { OVERFLOW_KEY, PathContext } from './hooks/useKeyPath';
|
||||
import type { FocusEventHandler, MouseEventHandler } from '../../_util/EventInterface';
|
||||
import collapseMotion from '../../_util/collapseMotion';
|
||||
|
||||
export const menuProps = {
|
||||
id: String,
|
||||
|
|
|
@ -71,11 +71,9 @@ export default defineComponent({
|
|||
const onVisibleChange = (visible: boolean) => {
|
||||
emit('visibleChange', visible);
|
||||
};
|
||||
const style = ref({});
|
||||
const className = ref('');
|
||||
const mergedMotion = computed(() => {
|
||||
const m = motion.value || defaultMotions.value?.[mode.value] || defaultMotions.value?.other;
|
||||
const res = typeof m === 'function' ? m(undefined, style, className) : m;
|
||||
const res = typeof m === 'function' ? m() : m;
|
||||
return res ? getTransitionProps(res.name, { css: true }) : undefined;
|
||||
});
|
||||
return () => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { Key } from '../../../_util/type';
|
||||
import type { ComputedRef, CSSProperties, InjectionKey, PropType, Ref, UnwrapRef } from 'vue';
|
||||
import type { ComputedRef, InjectionKey, PropType, Ref, UnwrapRef } from 'vue';
|
||||
import { defineComponent, inject, provide, toRef } from 'vue';
|
||||
import type {
|
||||
BuiltinPlacements,
|
||||
|
@ -59,9 +59,7 @@ export interface MenuContextProps {
|
|||
// // Motion
|
||||
motion?: ComputedRef<CSSMotionProps | null>;
|
||||
defaultMotions?: ComputedRef<Partial<{
|
||||
[key in MenuMode | 'other']:
|
||||
| CSSMotionProps
|
||||
| ((name: string, style: Ref<CSSProperties>, className: Ref<string>) => CSSMotionProps);
|
||||
[key in MenuMode | 'other']: CSSMotionProps | ((name?: string) => CSSMotionProps);
|
||||
}> | null>;
|
||||
|
||||
// // Popup
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
.@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow {
|
||||
opacity: 0.45;
|
||||
transition: all 0.3s;
|
||||
|
||||
&::after,
|
||||
&::before {
|
||||
background: @menu-dark-arrow-color;
|
||||
|
@ -65,6 +66,7 @@
|
|||
left: 0;
|
||||
margin-left: 0;
|
||||
border-right: 0;
|
||||
|
||||
&::after {
|
||||
border-right: 0;
|
||||
}
|
||||
|
@ -83,6 +85,7 @@
|
|||
&-dark &-submenu-title:hover {
|
||||
color: @menu-dark-highlight-color;
|
||||
background-color: transparent;
|
||||
|
||||
> a,
|
||||
> span > a {
|
||||
color: @menu-dark-highlight-color;
|
||||
|
@ -90,6 +93,7 @@
|
|||
> .@{menu-prefix-cls}-submenu-title {
|
||||
> .@{menu-prefix-cls}-submenu-arrow {
|
||||
opacity: 1;
|
||||
|
||||
&::after,
|
||||
&::before {
|
||||
background: @menu-dark-highlight-color;
|
||||
|
@ -97,6 +101,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-dark &-item:hover {
|
||||
background-color: @menu-dark-item-hover-bg;
|
||||
}
|
||||
|
@ -108,9 +113,11 @@
|
|||
&-dark &-item-selected {
|
||||
color: @menu-dark-highlight-color;
|
||||
border-right: 0;
|
||||
|
||||
&::after {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
> a,
|
||||
> span > a,
|
||||
> a:hover,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@menu-animation-duration-normal: 0.15s;
|
||||
|
||||
.accessibility-focus() {
|
||||
box-shadow: 0 0 0 2px fade(@primary-color, 20%);
|
||||
box-shadow: 0 0 0 2px @primary-1;
|
||||
}
|
||||
|
||||
// TODO: Should remove icon style compatible in v5
|
||||
|
@ -67,6 +67,7 @@
|
|||
transition: border-color @animation-duration-slow @ease-in-out,
|
||||
background @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
|
||||
&-submenu,
|
||||
&-submenu-inline {
|
||||
transition: border-color @animation-duration-slow @ease-in-out,
|
||||
|
@ -89,11 +90,17 @@
|
|||
padding @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
|
||||
&-title-content {
|
||||
transition: color @animation-duration-slow;
|
||||
}
|
||||
|
||||
&-item a {
|
||||
color: @menu-item-color;
|
||||
|
||||
&:hover {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -108,16 +115,22 @@
|
|||
// https://github.com/ant-design/ant-design/issues/19809
|
||||
&-item > .@{ant-prefix}-badge a {
|
||||
color: @menu-item-color;
|
||||
|
||||
&:hover {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-item-divider {
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
line-height: 0;
|
||||
background-color: @border-color-split;
|
||||
border-color: @border-color-split;
|
||||
border-style: solid;
|
||||
border-width: 1px 0 0;
|
||||
}
|
||||
|
||||
&-item-divider-dashed {
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
&-horizontal &-item,
|
||||
|
@ -133,6 +146,7 @@
|
|||
|
||||
&-item-selected {
|
||||
color: @menu-highlight-color;
|
||||
|
||||
a,
|
||||
a:hover {
|
||||
color: @menu-highlight-color;
|
||||
|
@ -173,6 +187,7 @@
|
|||
left: 0;
|
||||
margin-left: 0;
|
||||
border-right: 0;
|
||||
|
||||
&::after {
|
||||
border-right: 0;
|
||||
}
|
||||
|
@ -209,6 +224,7 @@
|
|||
font-size: @menu-icon-size;
|
||||
transition: font-size @menu-animation-duration-normal @ease-out,
|
||||
margin @animation-duration-slow @ease-in-out, color @animation-duration-slow;
|
||||
|
||||
+ span {
|
||||
margin-left: @menu-icon-margin-right;
|
||||
opacity: 1;
|
||||
|
@ -234,12 +250,8 @@
|
|||
}
|
||||
|
||||
& > &-item-divider {
|
||||
height: 1px;
|
||||
margin: 1px 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
line-height: 0;
|
||||
background-color: @border-color-split;
|
||||
}
|
||||
|
||||
&-submenu {
|
||||
|
@ -275,6 +287,7 @@
|
|||
> .@{menu-prefix-cls} {
|
||||
background-color: @menu-bg;
|
||||
border-radius: @border-radius-base;
|
||||
|
||||
&-submenu-title::after {
|
||||
transition: transform @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
|
@ -309,9 +322,11 @@
|
|||
color @animation-duration-slow @ease-in-out;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&::before {
|
||||
transform: rotate(45deg) translateY(-2.5px);
|
||||
}
|
||||
|
||||
&::after {
|
||||
transform: rotate(-45deg) translateY(2.5px);
|
||||
}
|
||||
|
@ -328,6 +343,7 @@
|
|||
&::before {
|
||||
transform: rotate(-45deg) translateX(2.5px);
|
||||
}
|
||||
|
||||
&::after {
|
||||
transform: rotate(45deg) translateX(-2.5px);
|
||||
}
|
||||
|
@ -340,9 +356,11 @@
|
|||
&-open&-inline > &-title > &-arrow {
|
||||
// ↑
|
||||
transform: translateY(-2px);
|
||||
|
||||
&::after {
|
||||
transform: rotate(-45deg) translateX(-2.5px);
|
||||
}
|
||||
|
||||
&::before {
|
||||
transform: rotate(45deg) translateX(2.5px);
|
||||
}
|
||||
|
@ -406,13 +424,16 @@
|
|||
> .@{menu-prefix-cls}-item {
|
||||
a {
|
||||
color: @menu-item-color;
|
||||
|
||||
&:hover {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
|
||||
&::before {
|
||||
bottom: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
&-selected a {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
|
@ -432,6 +453,7 @@
|
|||
&-inline {
|
||||
.@{menu-prefix-cls}-item {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -550,6 +572,7 @@
|
|||
margin: 0;
|
||||
font-size: @menu-icon-size-lg;
|
||||
line-height: @menu-item-height;
|
||||
|
||||
+ span {
|
||||
display: inline-block;
|
||||
opacity: 0;
|
||||
|
@ -569,6 +592,7 @@
|
|||
.@{iconfont-css-prefix} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @text-color-dark;
|
||||
}
|
||||
|
@ -663,6 +687,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/32950
|
||||
.@{ant-prefix}-menu-inline-collapsed-tooltip {
|
||||
a,
|
||||
a:hover {
|
||||
color: @white;
|
||||
}
|
||||
}
|
||||
|
||||
@import './light';
|
||||
@import './dark';
|
||||
@import './rtl';
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
transform: rotate(-45deg) translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
.@{menu-prefix-cls}-rtl & {
|
||||
transform: rotate(45deg) translateY(2px);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@import './index';
|
||||
@import (reference) '../../style/themes/index';
|
||||
@menu-prefix-cls: ~'@{ant-prefix}-menu';
|
||||
|
||||
.@{menu-prefix-cls} {
|
||||
// Danger
|
||||
|
@ -16,6 +17,7 @@
|
|||
|
||||
&-selected {
|
||||
color: @menu-highlight-danger-color;
|
||||
|
||||
> a,
|
||||
> a:hover {
|
||||
color: @menu-highlight-danger-color;
|
||||
|
|
|
@ -101,7 +101,9 @@ export default defineComponent({
|
|||
const motion = computed(() => {
|
||||
const m = typeof props.animation === 'object' ? props.animation : getMotion(props as any);
|
||||
['onAfterEnter', 'onAfterLeave'].forEach(eventName => {
|
||||
m[eventName] = () => {
|
||||
const originFn = m[eventName];
|
||||
m[eventName] = node => {
|
||||
originFn?.(node);
|
||||
goNextStatus();
|
||||
};
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue