feat: dropdown support arrow pointing at center (#33658)

* feat: add pointAtCenter prop for dropdown

* feat: dropdown support arrow pointing at center

* chore: code clean

* chore: use getPlacements in tooltip

* feat: dropdown support 'top' and 'bottom'

* chore: update snapshot

* chore: move placements to util folder

* feat: make 'topCenter' and 'bottomCenter' in Dropdown deprecated

* test: update snapshot

* test: add test for topCenter and bottomCenter
This commit is contained in:
MadCcc 2022-01-13 13:34:34 +08:00 committed by GitHub
parent 5fb13e9681
commit e5451a95cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1510 additions and 53 deletions

View File

@ -42,6 +42,7 @@ export default function getPlacements(config: PlacementsConfig) {
horizontalArrowShift = 16, horizontalArrowShift = 16,
verticalArrowShift = 8, verticalArrowShift = 8,
autoAdjustOverflow, autoAdjustOverflow,
arrowPointAtCenter,
} = config; } = config;
const placementMap: BuildInPlacements = { const placementMap: BuildInPlacements = {
left: { left: {
@ -94,7 +95,7 @@ export default function getPlacements(config: PlacementsConfig) {
}, },
}; };
Object.keys(placementMap).forEach(key => { Object.keys(placementMap).forEach(key => {
placementMap[key] = config.arrowPointAtCenter placementMap[key] = arrowPointAtCenter
? { ? {
...placementMap[key], ...placementMap[key],
overflow: getOverflowOptions(autoAdjustOverflow), overflow: getOverflowOptions(autoAdjustOverflow),

View File

@ -30,7 +30,7 @@ const BreadcrumbItem: BreadcrumbItemInterface = ({
const renderBreadcrumbNode = (breadcrumbItem: React.ReactNode) => { const renderBreadcrumbNode = (breadcrumbItem: React.ReactNode) => {
if (overlay) { if (overlay) {
return ( return (
<DropDown overlay={overlay} placement="bottomCenter" {...dropdownProps}> <DropDown overlay={overlay} placement="bottom" {...dropdownProps}>
<span className={`${prefixCls}-overlay-link`}> <span className={`${prefixCls}-overlay-link`}>
{breadcrumbItem} {breadcrumbItem}
<DownOutlined /> <DownOutlined />
@ -62,9 +62,7 @@ const BreadcrumbItem: BreadcrumbItemInterface = ({
return ( return (
<span> <span>
{link} {link}
{separator && ( {separator && <span className={`${prefixCls}-separator`}>{separator}</span>}
<span className={`${prefixCls}-separator`}>{separator}</span>
)}
</span> </span>
); );
} }

View File

@ -15,7 +15,7 @@ Array [
type="button" type="button"
> >
<span> <span>
bottomCenter bottom
</span> </span>
</button>, </button>,
<button <button
@ -40,7 +40,61 @@ Array [
type="button" type="button"
> >
<span> <span>
topCenter top
</span>
</button>,
<button
class="ant-btn ant-dropdown-trigger"
type="button"
>
<span>
topRight
</span>
</button>,
]
`;
exports[`renders ./components/dropdown/demo/arrow-center.md correctly 1`] = `
Array [
<button
class="ant-btn ant-dropdown-trigger"
type="button"
>
<span>
bottomLeft
</span>
</button>,
<button
class="ant-btn ant-dropdown-trigger"
type="button"
>
<span>
bottom
</span>
</button>,
<button
class="ant-btn ant-dropdown-trigger"
type="button"
>
<span>
bottomRight
</span>
</button>,
<br />,
<button
class="ant-btn ant-dropdown-trigger"
type="button"
>
<span>
topLeft
</span>
</button>,
<button
class="ant-btn ant-dropdown-trigger"
type="button"
>
<span>
top
</span> </span>
</button>, </button>,
<button <button
@ -658,7 +712,7 @@ exports[`renders ./components/dropdown/demo/placement.md correctly 1`] = `
type="button" type="button"
> >
<span> <span>
bottomCenter bottom
</span> </span>
</button> </button>
</div> </div>
@ -706,7 +760,7 @@ exports[`renders ./components/dropdown/demo/placement.md correctly 1`] = `
type="button" type="button"
> >
<span> <span>
topCenter top
</span> </span>
</button> </button>
</div> </div>

View File

@ -59,4 +59,24 @@ describe('Dropdown', () => {
await sleep(500); await sleep(500);
expect(wrapper.find(Dropdown).find('#customExpandIcon').length).toBe(1); expect(wrapper.find(Dropdown).find('#customExpandIcon').length).toBe(1);
}); });
it('should warn if use topCenter or bottomCenter', () => {
const error = jest.spyOn(console, 'error');
mount(
<div>
<Dropdown overlay="123" placement="bottomCenter">
<button type="button">bottomCenter</button>
</Dropdown>
<Dropdown overlay="123" placement="topCenter">
<button type="button">topCenter</button>
</Dropdown>
</div>,
);
expect(error).toHaveBeenCalledWith(
expect.stringContaining("[antd: Dropdown] You are using 'bottomCenter'"),
);
expect(error).toHaveBeenCalledWith(
expect.stringContaining("[antd: Dropdown] You are using 'topCenter'"),
);
});
}); });

View File

@ -0,0 +1,75 @@
---
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.
```jsx
import { Menu, Dropdown, Button } from 'antd';
const menu = (
<Menu>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
1st menu item
</a>
</Menu.Item>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
2nd menu item
</a>
</Menu.Item>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
3rd menu item
</a>
</Menu.Item>
</Menu>
);
ReactDOM.render(
<>
<Dropdown overlay={menu} placement="bottomLeft" arrow={{ pointAtCenter: true }}>
<Button>bottomLeft</Button>
</Dropdown>
<Dropdown overlay={menu} placement="bottom" arrow={{ pointAtCenter: true }}>
<Button>bottom</Button>
</Dropdown>
<Dropdown overlay={menu} placement="bottomRight" arrow={{ pointAtCenter: true }}>
<Button>bottomRight</Button>
</Dropdown>
<br />
<Dropdown overlay={menu} placement="topLeft" arrow={{ pointAtCenter: true }}>
<Button>topLeft</Button>
</Dropdown>
<Dropdown overlay={menu} placement="top" arrow={{ pointAtCenter: true }}>
<Button>top</Button>
</Dropdown>
<Dropdown overlay={menu} placement="topRight" arrow={{ pointAtCenter: true }}>
<Button>topRight</Button>
</Dropdown>
</>,
mountNode,
);
```
```css
#components-dropdown-demo-arrow-center .ant-btn {
margin-right: 8px;
margin-bottom: 8px;
}
.ant-row-rtl #components-dropdown-demo-arrow-center .ant-btn {
margin-right: 0;
margin-bottom: 8px;
margin-left: 8px;
}
```

View File

@ -41,8 +41,8 @@ ReactDOM.render(
<Dropdown overlay={menu} placement="bottomLeft" arrow> <Dropdown overlay={menu} placement="bottomLeft" arrow>
<Button>bottomLeft</Button> <Button>bottomLeft</Button>
</Dropdown> </Dropdown>
<Dropdown overlay={menu} placement="bottomCenter" arrow> <Dropdown overlay={menu} placement="bottom" arrow>
<Button>bottomCenter</Button> <Button>bottom</Button>
</Dropdown> </Dropdown>
<Dropdown overlay={menu} placement="bottomRight" arrow> <Dropdown overlay={menu} placement="bottomRight" arrow>
<Button>bottomRight</Button> <Button>bottomRight</Button>
@ -51,8 +51,8 @@ ReactDOM.render(
<Dropdown overlay={menu} placement="topLeft" arrow> <Dropdown overlay={menu} placement="topLeft" arrow>
<Button>topLeft</Button> <Button>topLeft</Button>
</Dropdown> </Dropdown>
<Dropdown overlay={menu} placement="topCenter" arrow> <Dropdown overlay={menu} placement="top" arrow>
<Button>topCenter</Button> <Button>top</Button>
</Dropdown> </Dropdown>
<Dropdown overlay={menu} placement="topRight" arrow> <Dropdown overlay={menu} placement="topRight" arrow>
<Button>topRight</Button> <Button>topRight</Button>

View File

@ -46,7 +46,7 @@ ReactDOM.render(
<Dropdown.Button onClick={handleButtonClick} overlay={menu}> <Dropdown.Button onClick={handleButtonClick} overlay={menu}>
Dropdown Dropdown
</Dropdown.Button> </Dropdown.Button>
<Dropdown.Button overlay={menu} placement="bottomCenter" icon={<UserOutlined />}> <Dropdown.Button overlay={menu} placement="bottom" icon={<UserOutlined />}>
Dropdown Dropdown
</Dropdown.Button> </Dropdown.Button>
<Dropdown.Button onClick={handleButtonClick} overlay={menu} disabled> <Dropdown.Button onClick={handleButtonClick} overlay={menu} disabled>

View File

@ -42,8 +42,8 @@ ReactDOM.render(
<Dropdown overlay={menu} placement="bottomLeft"> <Dropdown overlay={menu} placement="bottomLeft">
<Button>bottomLeft</Button> <Button>bottomLeft</Button>
</Dropdown> </Dropdown>
<Dropdown overlay={menu} placement="bottomCenter"> <Dropdown overlay={menu} placement="bottom">
<Button>bottomCenter</Button> <Button>bottom</Button>
</Dropdown> </Dropdown>
<Dropdown overlay={menu} placement="bottomRight"> <Dropdown overlay={menu} placement="bottomRight">
<Button>bottomRight</Button> <Button>bottomRight</Button>
@ -53,8 +53,8 @@ ReactDOM.render(
<Dropdown overlay={menu} placement="topLeft"> <Dropdown overlay={menu} placement="topLeft">
<Button>topLeft</Button> <Button>topLeft</Button>
</Dropdown> </Dropdown>
<Dropdown overlay={menu} placement="topCenter"> <Dropdown overlay={menu} placement="top">
<Button>topCenter</Button> <Button>top</Button>
</Dropdown> </Dropdown>
<Dropdown overlay={menu} placement="topRight"> <Dropdown overlay={menu} placement="topRight">
<Button>topRight</Button> <Button>topRight</Button>

View File

@ -7,6 +7,7 @@ import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning'; import devWarning from '../_util/devWarning';
import { tuple } from '../_util/type'; import { tuple } from '../_util/type';
import { cloneElement } from '../_util/reactNode'; import { cloneElement } from '../_util/reactNode';
import getPlacements from '../_util/placements';
const Placements = tuple( const Placements = tuple(
'topLeft', 'topLeft',
@ -15,6 +16,8 @@ const Placements = tuple(
'bottomLeft', 'bottomLeft',
'bottomCenter', 'bottomCenter',
'bottomRight', 'bottomRight',
'top',
'bottom',
); );
type Placement = typeof Placements[number]; type Placement = typeof Placements[number];
@ -34,8 +37,12 @@ type Align = {
useCssTransform?: boolean; useCssTransform?: boolean;
}; };
export type DropdownArrowOptions = {
pointAtCenter?: boolean;
};
export interface DropDownProps { export interface DropDownProps {
arrow?: boolean; arrow?: boolean | DropdownArrowOptions;
trigger?: ('click' | 'hover' | 'contextMenu')[]; trigger?: ('click' | 'hover' | 'contextMenu')[];
overlay: React.ReactElement | OverlayFunc; overlay: React.ReactElement | OverlayFunc;
onVisibleChange?: (visible: boolean) => void; onVisibleChange?: (visible: boolean) => void;
@ -129,10 +136,21 @@ const Dropdown: DropdownInterface = props => {
const getPlacement = () => { const getPlacement = () => {
const { placement } = props; const { placement } = props;
if (placement !== undefined) { if (!placement) {
return placement; return direction === 'rtl' ? ('bottomRight' as Placement) : ('bottomLeft' as Placement);
} }
return direction === 'rtl' ? ('bottomRight' as Placement) : ('bottomLeft' as Placement);
if (placement.includes('Center')) {
const newPlacement = placement.slice(0, placement.indexOf('Center'));
devWarning(
!placement.includes('Center'),
'Dropdown',
`You are using '${placement}' placement in Dropdown, which is deprecated. Try to use '${newPlacement}' instead.`,
);
return newPlacement;
}
return placement;
}; };
const { const {
@ -169,11 +187,16 @@ const Dropdown: DropdownInterface = props => {
alignPoint = true; alignPoint = true;
} }
const builtinPlacements = getPlacements({
arrowPointAtCenter: typeof arrow === 'object' && arrow.pointAtCenter,
});
return ( return (
<RcDropdown <RcDropdown
arrow={arrow}
alignPoint={alignPoint} alignPoint={alignPoint}
{...props} {...props}
builtinPlacements={builtinPlacements}
arrow={!!arrow}
overlayClassName={overlayClassNameCustomized} overlayClassName={overlayClassNameCustomized}
prefixCls={prefixCls} prefixCls={prefixCls}
getPopupContainer={getPopupContainer || getContextPopupContainer} getPopupContainer={getPopupContainer || getContextPopupContainer}

View File

@ -17,14 +17,14 @@ When there are more than a few options to choose from, you can wrap them in a `D
| Property | Description | Type | Default | Version | | Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| arrow | Whether the dropdown arrow should be visible | boolean | false | | | arrow | Whether the dropdown arrow should be visible | boolean \| { pointAtCenter: boolean } | false | |
| disabled | Whether the dropdown menu is disabled | boolean | - | | | disabled | Whether the dropdown menu is disabled | boolean | - | |
| destroyPopupOnHide | Whether destroy dropdown when hidden | boolean | false | | | destroyPopupOnHide | Whether destroy dropdown when hidden | boolean | false | |
| getPopupContainer | To set the container of the dropdown menu. The default is to create a div element in body, but you can reset it to the scrolling area and make a relative reposition. [Example on CodePen](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | (triggerNode: HTMLElement) => HTMLElement | () => document.body | | | getPopupContainer | To set the container of the dropdown menu. The default is to create a div element in body, but you can reset it to the scrolling area and make a relative reposition. [Example on CodePen](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | (triggerNode: HTMLElement) => HTMLElement | () => document.body | |
| overlay | The dropdown menu | [Menu](/components/menu) \| () => Menu | - | | | overlay | The dropdown menu | [Menu](/components/menu) \| () => Menu | - | |
| overlayClassName | The class name of the dropdown root element | string | - | | | overlayClassName | The class name of the dropdown root element | string | - | |
| overlayStyle | The style of the dropdown root element | CSSProperties | - | | | overlayStyle | The style of the dropdown root element | CSSProperties | - | |
| placement | Placement of popup menu: `bottomLeft`, `bottomCenter`, `bottomRight`, `topLeft`, `topCenter` or `topRight` | string | `bottomLeft` | | | placement | Placement of popup menu: `bottom` `bottomLeft` `bottomRight` `top` `topLeft` `topRight` | string | `bottomLeft` | |
| trigger | The trigger mode which executes the dropdown action. Note that hover can't be used on touchscreens | Array&lt;`click`\|`hover`\|`contextMenu`> | \[`hover`] | | | trigger | The trigger mode which executes the dropdown action. Note that hover can't be used on touchscreens | Array&lt;`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
| visible | Whether the dropdown menu is currently visible | boolean | - | | | visible | Whether the dropdown menu is currently visible | boolean | - | |
| onVisibleChange | Called when the visible state is changed. Not trigger when hidden by click item | (visible: boolean) => void | - | | | onVisibleChange | Called when the visible state is changed. Not trigger when hidden by click item | (visible: boolean) => void | - | |
@ -44,7 +44,7 @@ You should use [Menu](/components/menu/) as `overlay`. The menu items and divide
| disabled | Whether the dropdown menu is disabled | boolean | - | | | disabled | Whether the dropdown menu is disabled | boolean | - | |
| icon | Icon (appears on the right) | ReactNode | - | | | icon | Icon (appears on the right) | ReactNode | - | |
| overlay | The dropdown menu | [Menu](/components/menu) | - | | | overlay | The dropdown menu | [Menu](/components/menu) | - | |
| placement | Placement of popup menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | string | `bottomLeft` | | | placement | Placement of popup menu: `bottom` `bottomLeft` `bottomRight` `top` `topLeft` `topRight` | string | `bottomLeft` | |
| size | Size of the button, the same as [Button](/components/button/#API) | string | `default` | | | size | Size of the button, the same as [Button](/components/button/#API) | string | `default` | |
| trigger | The trigger mode which executes the dropdown action | Array&lt;`click`\|`hover`\|`contextMenu`> | \[`hover`] | | | trigger | The trigger mode which executes the dropdown action | Array&lt;`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
| type | Type of the button, the same as [Button](/components/button/#API) | string | `default` | | | type | Type of the button, the same as [Button](/components/button/#API) | string | `default` | |

View File

@ -21,14 +21,14 @@ cover: https://gw.alipayobjects.com/zos/alicdn/eedWN59yJ/Dropdown.svg
| 参数 | 说明 | 类型 | 默认值 | 版本 | | 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| arrow | 下拉框箭头是否显示 | boolean | false | | | arrow | 下拉框箭头是否显示 | boolean \| { pointAtCenter: boolean } | false | |
| disabled | 菜单是否禁用 | boolean | - | | | disabled | 菜单是否禁用 | boolean | - | |
| destroyPopupOnHide | 关闭后是否销毁 Dropdown | boolean | false | | | destroyPopupOnHide | 关闭后是否销毁 Dropdown | boolean | false | |
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | (triggerNode: HTMLElement) => HTMLElement | () => document.body | | | getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | (triggerNode: HTMLElement) => HTMLElement | () => document.body | |
| overlay | 菜单 | [Menu](/components/menu) \| () => Menu | - | | | overlay | 菜单 | [Menu](/components/menu) \| () => Menu | - | |
| overlayClassName | 下拉根元素的类名称 | string | - | | | overlayClassName | 下拉根元素的类名称 | string | - | |
| overlayStyle | 下拉根元素的样式 | CSSProperties | - | | | overlayStyle | 下拉根元素的样式 | CSSProperties | - | |
| placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | string | `bottomLeft` | | | placement | 菜单弹出位置:`bottom` `bottomLeft` `bottomRight` `top` `topLeft` `topRight` | string | `bottomLeft` | |
| trigger | 触发下拉的行为, 移动端不支持 hover | Array&lt;`click`\|`hover`\|`contextMenu`> | \[`hover`] | | | trigger | 触发下拉的行为, 移动端不支持 hover | Array&lt;`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
| visible | 菜单是否显示 | boolean | - | | | visible | 菜单是否显示 | boolean | - | |
| onVisibleChange | 菜单显示状态改变时调用,参数为 `visible`。点击菜单按钮导致的消失不会触发 | (visible: boolean) => void | - | | | onVisibleChange | 菜单显示状态改变时调用,参数为 `visible`。点击菜单按钮导致的消失不会触发 | (visible: boolean) => void | - | |
@ -48,7 +48,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/eedWN59yJ/Dropdown.svg
| disabled | 菜单是否禁用 | boolean | - | | | disabled | 菜单是否禁用 | boolean | - | |
| icon | 右侧的 icon | ReactNode | - | | | icon | 右侧的 icon | ReactNode | - | |
| overlay | 菜单 | [Menu](/components/menu/) | - | | | overlay | 菜单 | [Menu](/components/menu/) | - | |
| placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | string | `bottomLeft` | | | placement | 菜单弹出位置:`bottom` `bottomLeft` `bottomRight` `top` `topLeft` `topRight` | string | `bottomLeft` | |
| size | 按钮大小,和 [Button](/components/button/#API) 一致 | string | `default` | | | size | 按钮大小,和 [Button](/components/button/#API) 一致 | string | `default` | |
| trigger | 触发下拉的行为 | Array&lt;`click`\|`hover`\|`contextMenu`> | \[`hover`] | | | trigger | 触发下拉的行为 | Array&lt;`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
| type | 按钮类型,和 [Button](/components/button/#API) 一致 | string | `default` | | | type | 按钮类型,和 [Button](/components/button/#API) 一致 | string | `default` | |

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;
} }
@ -76,7 +76,7 @@
transform: rotate(45deg); transform: rotate(45deg);
} }
&-placement-topCenter > &-arrow, &-placement-top > &-arrow,
&-placement-topLeft > &-arrow, &-placement-topLeft > &-arrow,
&-placement-topRight > &-arrow { &-placement-topRight > &-arrow {
bottom: @popover-distance - @popover-arrow-width + 2.2px; bottom: @popover-distance - @popover-arrow-width + 2.2px;
@ -84,7 +84,7 @@
box-shadow: 3px 3px 7px fade(@black, 7%); box-shadow: 3px 3px 7px fade(@black, 7%);
} }
&-placement-topCenter > &-arrow { &-placement-top > &-arrow {
left: 50%; left: 50%;
transform: translateX(-50%) rotate(45deg); transform: translateX(-50%) rotate(45deg);
} }
@ -97,7 +97,7 @@
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-distance - @popover-arrow-width + 2px;
@ -105,7 +105,7 @@
box-shadow: -2px -2px 5px fade(@black, 6%); box-shadow: -2px -2px 5px fade(@black, 6%);
} }
&-placement-bottomCenter > &-arrow { &-placement-bottom > &-arrow {
left: 50%; left: 50%;
transform: translateX(-50%) rotate(45deg); transform: translateX(-50%) rotate(45deg);
} }
@ -300,8 +300,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;
@ -309,21 +309,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;
} }

View File

@ -4,7 +4,7 @@ import useMergedState from 'rc-util/lib/hooks/useMergedState';
import { TooltipProps as RcTooltipProps } from 'rc-tooltip/lib/Tooltip'; import { TooltipProps as RcTooltipProps } from 'rc-tooltip/lib/Tooltip';
import classNames from 'classnames'; import classNames from 'classnames';
import { placements as Placements } from 'rc-tooltip/lib/placements'; import { placements as Placements } from 'rc-tooltip/lib/placements';
import getPlacements, { AdjustOverflow, PlacementsConfig } from './placements'; import getPlacements, { AdjustOverflow, PlacementsConfig } from '../_util/placements';
import { cloneElement, isValidElement } from '../_util/reactNode'; import { cloneElement, isValidElement } from '../_util/reactNode';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import { PresetColorType, PresetColorTypes } from '../_util/colors'; import { PresetColorType, PresetColorTypes } from '../_util/colors';
@ -130,9 +130,11 @@ function getDisabledCompatibleChildren(element: React.ReactElement<any>, prefixC
} }
const Tooltip = React.forwardRef<unknown, TooltipProps>((props, ref) => { const Tooltip = React.forwardRef<unknown, TooltipProps>((props, ref) => {
const { getPopupContainer: getContextPopupContainer, getPrefixCls, direction } = React.useContext( const {
ConfigContext, getPopupContainer: getContextPopupContainer,
); getPrefixCls,
direction,
} = React.useContext(ConfigContext);
const [visible, setVisible] = useMergedState(false, { const [visible, setVisible] = useMergedState(false, {
value: props.visible, value: props.visible,
@ -167,11 +169,11 @@ const Tooltip = React.forwardRef<unknown, TooltipProps>((props, ref) => {
const onPopupAlign = (domNode: HTMLElement, align: any) => { const onPopupAlign = (domNode: HTMLElement, align: any) => {
const placements: any = getTooltipPlacements(); const placements: any = getTooltipPlacements();
// 当前返回的位置 // 当前返回的位置
const placement = Object.keys(placements).filter( const placement = Object.keys(placements).find(
key => key =>
placements[key].points[0] === align.points[0] && placements[key].points[0] === align.points[0] &&
placements[key].points[1] === align.points[1], placements[key].points[1] === align.points[1],
)[0]; );
if (!placement) { if (!placement) {
return; return;
} }

View File

@ -126,7 +126,7 @@
"rc-collapse": "~3.1.0", "rc-collapse": "~3.1.0",
"rc-dialog": "~8.6.0", "rc-dialog": "~8.6.0",
"rc-drawer": "~4.4.2", "rc-drawer": "~4.4.2",
"rc-dropdown": "~3.2.0", "rc-dropdown": "~3.2.2",
"rc-field-form": "~1.22.0-2", "rc-field-form": "~1.22.0-2",
"rc-image": "~5.2.5", "rc-image": "~5.2.5",
"rc-input-number": "~7.3.0", "rc-input-number": "~7.3.0",

View File

@ -523,7 +523,7 @@ class MainContent extends Component {
</section> </section>
{componentPage && ( {componentPage && (
<div className="fixed-widgets"> <div className="fixed-widgets">
<Dropdown overlay={this.getThemeSwitchMenu()} placement="topCenter"> <Dropdown overlay={this.getThemeSwitchMenu()} placement="top">
<Avatar className="fixed-widgets-avatar" size={44} icon={<ThemeIcon />} /> <Avatar className="fixed-widgets-avatar" size={44} icon={<ThemeIcon />} />
</Dropdown> </Dropdown>
</div> </div>