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

View File

@ -144,7 +144,7 @@ const Dropdown = defineComponent({
...attrs, ...attrs,
builtinPlacements, builtinPlacements,
overlayClassName: overlayClassNameCustomized, overlayClassName: overlayClassNameCustomized,
arrow, arrow: !!arrow,
alignPoint, alignPoint,
prefixCls: prefixCls.value, prefixCls: prefixCls.value,
getPopupContainer: getPopupContainer.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 | | | 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 | | | destroyPopupOnHide | Whether destroy dropdown when hidden | boolean | false | |
| disabled | whether the dropdown menu is disabled | boolean | - | | | 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` | | | 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 | | destroyPopupOnHide | 关闭后是否销毁 Dropdown | boolean | false | 3.0 |
| disabled | 菜单是否禁用 | boolean | - | | | disabled | 菜单是否禁用 | boolean | - | |
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | `() => document.body` | | | getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | `() => document.body` | |

View File

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