feat: dropdown add arrow

pull/5820/head
tangjinzhou 2022-05-16 10:57:15 +08:00
parent a1ac22443e
commit f00b9535d2
7 changed files with 145 additions and 31 deletions

View File

@ -0,0 +1,52 @@
<docs>
---
order: 3
title:
zh-CN: 箭头指向
en-US: Arrow pointing at the center
---
## zh-CN
设置 `arrow` `{ pointAtCenter: true }` 箭头将指向目标元素的中心
## en-US
By specifying `arrow` prop with `{ pointAtCenter: true }`, the arrow will point to the center of the target element.
</docs>
<template>
<a-space style="display: flex; flex-wrap: wrap">
<template v-for="placement in placements" :key="placement">
<a-dropdown :placement="placement" :arrow="{ pointAtCenter: true }">
<a-button>{{ placement }}</a-button>
<template #overlay>
<a-menu>
<a-menu-item>
<a href="javascript:;">1st menu item</a>
</a-menu-item>
<a-menu-item>
<a href="javascript:;">2nd menu item</a>
</a-menu-item>
<a-menu-item>
<a href="javascript:;">3rd menu item</a>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</template>
</a-space>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
components: {},
setup() {
return {
placements: ['topLeft', 'top', 'topRight', 'bottomLeft', 'bottom', 'bottomRight'] as const,
};
},
});
</script>

View File

@ -0,0 +1,52 @@
<docs>
---
order: 2
title:
zh-CN: 箭头
en-US: Arrow
---
## zh-CN
可以展示一个箭头
## en-US
You could display an arrow.
</docs>
<template>
<a-space style="display: flex; flex-wrap: wrap">
<template v-for="placement in placements" :key="placement">
<a-dropdown :placement="placement" arrow>
<a-button>{{ placement }}</a-button>
<template #overlay>
<a-menu>
<a-menu-item>
<a href="javascript:;">1st menu item</a>
</a-menu-item>
<a-menu-item>
<a href="javascript:;">2nd menu item</a>
</a-menu-item>
<a-menu-item>
<a href="javascript:;">3rd menu item</a>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</template>
</a-space>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
components: {},
setup() {
return {
placements: ['topLeft', 'top', 'topRight', 'bottomLeft', 'bottom', 'bottomRight'] as const,
};
},
});
</script>

View File

@ -7,6 +7,8 @@
<item />
<overlay-visible />
<placement />
<arrow-vue />
<arrow-center-vue></arrow-center-vue>
<sub-menu />
<trigger />
<loadingVue />
@ -27,11 +29,14 @@ import Placement from './placement.vue';
import SubMenu from './sub-menu.vue';
import Trigger from './trigger.vue';
import loadingVue from './loading.vue';
import arrowVue from './arrow.vue';
import arrowCenterVue from './arrow-center.vue';
export default defineComponent({
CN,
US,
components: {
arrowCenterVue,
arrowVue,
loadingVue,
Basic,
ContextMenu,

View File

@ -144,7 +144,7 @@ const Dropdown = defineComponent({
...attrs,
builtinPlacements,
overlayClassName: overlayClassNameCustomized,
arrow,
arrow: !!arrow,
alignPoint,
prefixCls: prefixCls.value,
getPopupContainer: getPopupContainer.value,

View File

@ -17,6 +17,7 @@ When there are more than a few options to choose from, you can wrap them in a `D
| Property | Description | Type | Default | |
| --- | --- | --- | --- | --- |
| arrow | Whether the dropdown arrow should be visible | boolean \| { pointAtCenter: boolean } | false | 3.3.0 |
| destroyPopupOnHide | Whether destroy dropdown when hidden | boolean | false | |
| disabled | whether the dropdown menu is disabled | boolean | - | |
| getPopupContainer | to set the container of the dropdown menu. The default is to create a `div` element in `body`, you can reset it to the scrolling area and make a relative reposition. [example](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | Function(triggerNode) | `() => document.body` | |

View File

@ -21,6 +21,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/eedWN59yJ/Dropdown.svg
| 参数 | 说明 | 类型 | 默认值 | |
| --- | --- | --- | --- | --- |
| arrow | 下拉框箭头是否显示 | boolean \| { pointAtCenter: boolean } | false | 3.3.0 |
| destroyPopupOnHide | 关闭后是否销毁 Dropdown | boolean | false | 3.0 |
| disabled | 菜单是否禁用 | boolean | - | |
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | `() => document.body` | |

View File

@ -49,14 +49,14 @@
}
// Offset the popover to account for the dropdown arrow
&-show-arrow&-placement-topCenter,
&-show-arrow&-placement-topLeft,
&-show-arrow&-placement-top,
&-show-arrow&-placement-topRight {
padding-bottom: @popover-distance;
}
&-show-arrow&-placement-bottomCenter,
&-show-arrow&-placement-bottomLeft,
&-show-arrow&-placement-bottom,
&-show-arrow&-placement-bottomRight {
padding-top: @popover-distance;
}
@ -68,23 +68,25 @@
position: absolute;
z-index: 1; // lift it up so the menu wouldn't cask shadow on it
display: block;
width: sqrt(@popover-arrow-width * @popover-arrow-width * 2);
height: sqrt(@popover-arrow-width * @popover-arrow-width * 2);
background: transparent;
border-style: solid;
border-width: (sqrt(@popover-arrow-width * @popover-arrow-width * 2) / 2);
width: @popover-arrow-width;
height: @popover-arrow-width;
background: linear-gradient(
135deg,
transparent 40%,
@popover-bg 40%
); // Use linear-gradient to prevent arrow from covering text
.roundedArrow(@popover-arrow-width, 5px, @popover-bg);
}
&-placement-top > &-arrow,
&-placement-topLeft > &-arrow,
&-placement-topRight > &-arrow {
bottom: @popover-arrow-width * sqrt((1 / 2)) + 2px;
box-shadow: 3px 3px 7px -3px fade(@black, 10%);
transform: rotate(45deg);
}
&-placement-topCenter > &-arrow,
&-placement-topLeft > &-arrow,
&-placement-topRight > &-arrow {
bottom: @popover-distance - @popover-arrow-width + 2.2px;
border-color: transparent @popover-bg @popover-bg transparent;
box-shadow: 3px 3px 7px fade(@black, 7%);
}
&-placement-topCenter > &-arrow {
&-placement-top > &-arrow {
left: 50%;
transform: translateX(-50%) rotate(45deg);
}
@ -97,17 +99,17 @@
right: 16px;
}
&-placement-bottomCenter > &-arrow,
&-placement-bottom > &-arrow,
&-placement-bottomLeft > &-arrow,
&-placement-bottomRight > &-arrow {
top: @popover-distance - @popover-arrow-width + 2px;
border-color: @popover-bg transparent transparent @popover-bg;
box-shadow: -2px -2px 5px fade(@black, 6%);
top: (@popover-arrow-width + 2px) * sqrt((1 / 2));
box-shadow: 2px 2px 5px -2px fade(@black, 10%);
transform: rotate(-135deg) translateY(-0.5px);
}
&-placement-bottomCenter > &-arrow {
&-placement-bottom > &-arrow {
left: 50%;
transform: translateX(-50%) rotate(45deg);
transform: translateX(-50%) rotate(-135deg) translateY(-0.5px);
}
&-placement-bottomLeft > &-arrow {
@ -219,7 +221,8 @@
background-color: @dropdown-selected-bg;
}
&:hover {
&:hover,
&&-active {
background-color: @item-hover-bg;
}
@ -299,8 +302,8 @@
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomLeft,
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomLeft,
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomCenter,
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomCenter,
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottom,
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottom,
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomRight,
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomRight {
animation-name: antSlideUpIn;
@ -308,21 +311,21 @@
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topLeft,
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topLeft,
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topCenter,
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topCenter,
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-top,
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-top,
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topRight,
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topRight {
animation-name: antSlideDownIn;
}
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomLeft,
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomCenter,
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottom,
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomRight {
animation-name: antSlideUpOut;
}
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topLeft,
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topCenter,
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-top,
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topRight {
animation-name: antSlideDownOut;
}