mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-11-29 18:48:32 +08:00
feat[tooltip]: add arrow
attribute (#7459)
* docs: updating the `dropdownRender` description and jumps in the FAQ for Select * wip: add popover-arrow * wip: trigger add arrow attr * fix: remove popupContextKey * optimize * perf: optimize * docs: optimize docs * docs: add `arrow` attribute in tooltip en-US docs * fix: fix bug * perf[demo]: `radio-group` replace with `segmented`
This commit is contained in:
parent
966bc1004c
commit
85c48c0566
@ -209,7 +209,9 @@ export default function getArrowStyle<Token extends TokenWithCommonCls<AliasToke
|
||||
// Offset the popover to account for the dropdown arrow
|
||||
// >>>>> Top
|
||||
[connectArrowCls(
|
||||
[`&-placement-topLeft`, `&-placement-top`, `&-placement-topRight`],
|
||||
[`&-placement-topLeft`, `&-placement-top`, `&-placement-topRight`].map(
|
||||
cls => (cls += ':not(&-arrow-hidden)'),
|
||||
),
|
||||
showArrowCls,
|
||||
)]: {
|
||||
paddingBottom: dropdownArrowDistance,
|
||||
@ -217,7 +219,9 @@ export default function getArrowStyle<Token extends TokenWithCommonCls<AliasToke
|
||||
|
||||
// >>>>> Bottom
|
||||
[connectArrowCls(
|
||||
[`&-placement-bottomLeft`, `&-placement-bottom`, `&-placement-bottomRight`],
|
||||
[`&-placement-bottomLeft`, `&-placement-bottom`, `&-placement-bottomRight`].map(
|
||||
cls => (cls += ':not(&-arrow-hidden)'),
|
||||
),
|
||||
showArrowCls,
|
||||
)]: {
|
||||
paddingTop: dropdownArrowDistance,
|
||||
@ -225,7 +229,9 @@ export default function getArrowStyle<Token extends TokenWithCommonCls<AliasToke
|
||||
|
||||
// >>>>> Left
|
||||
[connectArrowCls(
|
||||
[`&-placement-leftTop`, `&-placement-left`, `&-placement-leftBottom`],
|
||||
[`&-placement-leftTop`, `&-placement-left`, `&-placement-leftBottom`].map(
|
||||
cls => (cls += ':not(&-arrow-hidden)'),
|
||||
),
|
||||
showArrowCls,
|
||||
)]: {
|
||||
paddingRight: {
|
||||
@ -236,7 +242,9 @@ export default function getArrowStyle<Token extends TokenWithCommonCls<AliasToke
|
||||
|
||||
// >>>>> Right
|
||||
[connectArrowCls(
|
||||
[`&-placement-rightTop`, `&-placement-right`, `&-placement-rightBottom`],
|
||||
[`&-placement-rightTop`, `&-placement-right`, `&-placement-rightBottom`].map(
|
||||
cls => (cls += ':not(&-arrow-hidden)'),
|
||||
),
|
||||
showArrowCls,
|
||||
)]: {
|
||||
paddingLeft: {
|
||||
|
@ -145,11 +145,16 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
const tooltipPlacements = computed(() => {
|
||||
const { builtinPlacements, arrowPointAtCenter, autoAdjustOverflow } = props;
|
||||
const { builtinPlacements, autoAdjustOverflow, arrow, arrowPointAtCenter } = props;
|
||||
let mergedArrowPointAtCenter = arrowPointAtCenter;
|
||||
|
||||
if (typeof arrow === 'object') {
|
||||
mergedArrowPointAtCenter = arrow.pointAtCenter ?? arrowPointAtCenter;
|
||||
}
|
||||
return (
|
||||
builtinPlacements ||
|
||||
getPlacements({
|
||||
arrowPointAtCenter,
|
||||
arrowPointAtCenter: mergedArrowPointAtCenter,
|
||||
autoAdjustOverflow,
|
||||
})
|
||||
);
|
||||
@ -283,6 +288,7 @@ export default defineComponent({
|
||||
...attrs,
|
||||
...(props as TooltipProps),
|
||||
prefixCls: prefixCls.value,
|
||||
arrow: !!props.arrow,
|
||||
getPopupContainer: getPopupContainer?.value,
|
||||
builtinPlacements: tooltipPlacements.value,
|
||||
visible: tempVisible,
|
||||
|
@ -35,7 +35,12 @@ export default () => ({
|
||||
mouseEnterDelay: Number,
|
||||
mouseLeaveDelay: Number,
|
||||
getPopupContainer: Function as PropType<(triggerNode: HTMLElement) => HTMLElement>,
|
||||
/**@deprecated Please use `arrow={{ pointAtCenter: true }}` instead. */
|
||||
arrowPointAtCenter: { type: Boolean, default: undefined },
|
||||
arrow: {
|
||||
type: [Boolean, Object] as PropType<boolean | { pointAtCenter?: boolean }>,
|
||||
default: true as boolean | { pointAtCenter?: boolean },
|
||||
},
|
||||
autoAdjustOverflow: {
|
||||
type: [Boolean, Object] as PropType<boolean | AdjustOverflow>,
|
||||
default: undefined as boolean | AdjustOverflow,
|
||||
|
143
components/tooltip/demo/arrow.vue
Normal file
143
components/tooltip/demo/arrow.vue
Normal file
@ -0,0 +1,143 @@
|
||||
<docs>
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 箭头展示
|
||||
en-US: Arrow show
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
支持显示、隐藏以及将箭头保持居中定位。
|
||||
|
||||
## en-US
|
||||
|
||||
Support show, hide or keep arrow in the center.
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
<div id="components-a-tooltip-demo-arrow">
|
||||
<div style="margin-bottom: 24px">
|
||||
<a-segmented v-model:value="arrow" :options="options" />
|
||||
</div>
|
||||
<div :style="{ marginLeft: `${buttonWidth}px`, whiteSpace: 'nowrap' }">
|
||||
<a-tooltip placement="topLeft" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>TL</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="top" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>Top</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="topRight" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>TR</a-button>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div :style="{ width: `${buttonWidth}px`, float: 'left' }">
|
||||
<a-tooltip placement="leftTop" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>LT</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="left" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>Left</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="leftBottom" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>LB</a-button>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div :style="{ width: `${buttonWidth}px`, marginLeft: `${buttonWidth * 4 + 24}px` }">
|
||||
<a-tooltip placement="rightTop" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>RT</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="right" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>Right</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="rightBottom" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>RB</a-button>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div :style="{ marginLeft: `${buttonWidth}px`, clear: 'both', whiteSpace: 'nowrap' }">
|
||||
<a-tooltip placement="bottomLeft" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>BL</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottom" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>Bottom</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottomRight" :arrow="mergedArrow">
|
||||
<template #title>
|
||||
<span>prompt text</span>
|
||||
</template>
|
||||
<a-button>BR</a-button>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
const buttonWidth = 70;
|
||||
|
||||
const arrow = ref<string>('show');
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: 'Show',
|
||||
value: 'show',
|
||||
},
|
||||
{
|
||||
label: 'Hide',
|
||||
value: 'hide',
|
||||
},
|
||||
{
|
||||
label: 'Center',
|
||||
value: 'center',
|
||||
},
|
||||
];
|
||||
const mergedArrow = computed(() => {
|
||||
switch (arrow.value) {
|
||||
case 'show':
|
||||
return true;
|
||||
case 'hide':
|
||||
return false;
|
||||
case 'center':
|
||||
return { pointAtCenter: true };
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
:deep(#components-a-tooltip-demo-arrow) .ant-btn {
|
||||
width: 70px;
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
margin-right: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
@ -5,6 +5,7 @@
|
||||
<arrow-point-at-center />
|
||||
<auto-adjust-overflow />
|
||||
<color />
|
||||
<Arrow />
|
||||
</demo-sort>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
@ -13,6 +14,7 @@ import Placement from './placement.vue';
|
||||
import arrowPointAtCenter from './arrow-point-at-center.vue';
|
||||
import AutoAdjustOverflow from './auto-adjust-overflow.vue';
|
||||
import Color from './color.vue';
|
||||
import Arrow from './arrow.vue';
|
||||
import CN from '../index.zh-CN.md';
|
||||
import US from '../index.en-US.md';
|
||||
import { defineComponent } from 'vue';
|
||||
@ -25,6 +27,7 @@ export default defineComponent({
|
||||
arrowPointAtCenter,
|
||||
AutoAdjustOverflow,
|
||||
Color,
|
||||
Arrow,
|
||||
},
|
||||
setup() {
|
||||
return {};
|
||||
|
@ -27,6 +27,7 @@ The following APIs are shared by Tooltip, Popconfirm, Popover.
|
||||
| --- | --- | --- | --- | --- |
|
||||
| align | this value will be merged into placement's config, please refer to the settings [dom-align](https://github.com/yiminghe/dom-align) | Object | - | |
|
||||
| arrowPointAtCenter | Whether the arrow is pointed at the center of target | boolean | `false` | |
|
||||
| arrow | Change arrow's visible state and change whether the arrow is pointed at the center of target. | boolean \| { pointAtCenter: boolean} | `true` | |
|
||||
| autoAdjustOverflow | Whether to adjust popup placement automatically when popup is off screen | boolean | `true` | |
|
||||
| color | The background color | string | - | |
|
||||
| destroyTooltipOnHide | Whether to destroy tooltip on hide | boolean | false | |
|
||||
|
@ -28,6 +28,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*gwrhTozoTC4AAA
|
||||
| --- | --- | --- | --- | --- |
|
||||
| align | 该值将合并到 placement 的配置中,设置参考 [dom-align](https://github.com/yiminghe/dom-align) | Object | 无 | |
|
||||
| arrowPointAtCenter | 箭头是否指向目标元素中心 | boolean | `false` | |
|
||||
| arrow | 修改箭头的显示状态以及修改箭头是否指向目标元素中心 | boolean \| { pointAtCenter: boolean} | `true` | |
|
||||
| autoAdjustOverflow | 气泡被遮挡时自动调整位置 | boolean | `true` | |
|
||||
| color | 背景颜色 | string | 无 | |
|
||||
| destroyTooltipOnHide | 隐藏后是否销毁 tooltip | boolean | false | |
|
||||
|
@ -5,6 +5,7 @@ import Content from './Content';
|
||||
import { getPropsSlot } from '../../_util/props-util';
|
||||
import type { CSSProperties, PropType } from 'vue';
|
||||
import { defineComponent, shallowRef, watchEffect } from 'vue';
|
||||
|
||||
function noop() {}
|
||||
export default defineComponent({
|
||||
compatConfig: { MODE: 3 },
|
||||
@ -36,16 +37,20 @@ export default defineComponent({
|
||||
popupVisible: { type: Boolean, default: undefined },
|
||||
onVisibleChange: Function,
|
||||
onPopupAlign: Function,
|
||||
arrow: { type: Boolean, default: true },
|
||||
},
|
||||
setup(props, { slots, attrs, expose }) {
|
||||
const triggerDOM = shallowRef();
|
||||
|
||||
const getPopupElement = () => {
|
||||
const { prefixCls, tipId, overlayInnerStyle } = props;
|
||||
|
||||
return [
|
||||
<div class={`${prefixCls}-arrow`} key="arrow">
|
||||
{getPropsSlot(slots, props, 'arrowContent')}
|
||||
</div>,
|
||||
!!props.arrow ? (
|
||||
<div class={`${prefixCls}-arrow`} key="arrow">
|
||||
{getPropsSlot(slots, props, 'arrowContent')}
|
||||
</div>
|
||||
) : null,
|
||||
<Content
|
||||
key="content"
|
||||
prefixCls={prefixCls}
|
||||
@ -122,6 +127,7 @@ export default defineComponent({
|
||||
onPopupVisibleChange: props.onVisibleChange || (noop as any),
|
||||
onPopupAlign: props.onPopupAlign || noop,
|
||||
ref: triggerDOM,
|
||||
arrow: !!props.arrow,
|
||||
popup: getPopupElement(),
|
||||
};
|
||||
return <Trigger {...triggerProps} v-slots={{ default: slots.default }}></Trigger>;
|
||||
|
@ -210,6 +210,7 @@ const Tour = defineComponent({
|
||||
/>
|
||||
<Trigger
|
||||
{...restProps}
|
||||
arrow={!!restProps.arrow}
|
||||
builtinPlacements={
|
||||
!curStep.value.target
|
||||
? undefined
|
||||
|
@ -171,7 +171,13 @@ export default defineComponent({
|
||||
if (childNode.length > 1) {
|
||||
childNode = <div class={`${prefixCls}-content`}>{childNode}</div>;
|
||||
}
|
||||
const mergedClassName = classNames(prefixCls, attrs.class, alignedClassName.value);
|
||||
|
||||
const mergedClassName = classNames(
|
||||
prefixCls,
|
||||
attrs.class,
|
||||
alignedClassName.value,
|
||||
!props.arrow && `${prefixCls}-arrow-hidden`,
|
||||
);
|
||||
const hasAnimate = visible.value || !props.visible;
|
||||
const transitionProps = hasAnimate ? getTransitionProps(motion.value.name, motion.value) : {};
|
||||
|
||||
|
@ -10,6 +10,8 @@ export const innerProps = {
|
||||
destroyPopupOnHide: Boolean,
|
||||
forceRender: Boolean,
|
||||
|
||||
arrow: { type: Boolean, default: true },
|
||||
|
||||
// Legacy Motion
|
||||
animation: [String, Object],
|
||||
transitionName: String,
|
||||
|
@ -414,11 +414,13 @@ export default defineComponent({
|
||||
stretch,
|
||||
alignPoint,
|
||||
mobile,
|
||||
arrow,
|
||||
forceRender,
|
||||
} = this.$props;
|
||||
const { sPopupVisible, point } = this.$data;
|
||||
const popupProps = {
|
||||
prefixCls,
|
||||
arrow,
|
||||
destroyPopupOnHide,
|
||||
visible: sPopupVisible,
|
||||
point: alignPoint ? point : null,
|
||||
|
@ -111,6 +111,7 @@ export const triggerProps = () => ({
|
||||
onPopupVisibleChange: Function as PropType<(open: boolean) => void>,
|
||||
afterPopupVisibleChange: PropTypes.func.def(noop),
|
||||
popup: PropTypes.any,
|
||||
arrow: PropTypes.bool.def(true),
|
||||
popupStyle: { type: Object as PropType<CSSProperties>, default: undefined as CSSProperties },
|
||||
prefixCls: PropTypes.string.def('rc-trigger-popup'),
|
||||
popupClassName: PropTypes.string.def(''),
|
||||
|
Loading…
Reference in New Issue
Block a user