Skip to content

Commit

Permalink
feat: switch visible to open for Dropdown (ant-design#37232)
Browse files Browse the repository at this point in the history
* feat: switch visible to open for Dropdown

* fix: merge state

* fix: props pass

* test: fix coverage
  • Loading branch information
yykoypj authored and linaaaqi committed Sep 5, 2022
1 parent eff693a commit b1d1c49
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6934,7 +6934,7 @@ Array [
]
`;

exports[`renders ./components/dropdown/demo/overlay-visible.md extend context correctly 1`] = `
exports[`renders ./components/dropdown/demo/overlay-open.md extend context correctly 1`] = `
Array [
<a
class="ant-dropdown-trigger"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ exports[`renders ./components/dropdown/demo/menu-full.md correctly 1`] = `
</a>
`;

exports[`renders ./components/dropdown/demo/overlay-visible.md correctly 1`] = `
exports[`renders ./components/dropdown/demo/overlay-open.md correctly 1`] = `
<a
class="ant-dropdown-trigger"
>
Expand Down
15 changes: 9 additions & 6 deletions components/dropdown/__tests__/dropdown-button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,28 @@ describe('DropdownButton', () => {
),
disabled: false,
trigger: ['hover'],
visible: true,
onVisibleChange: () => {},
open: true,
onOpenChange: () => {},
};

render(<DropdownButton {...props} />);
const { rerender } = render(<DropdownButton {...props} />);

Object.keys(props).forEach((key: keyof DropdownProps) => {
expect(dropdownProps[key]).toBe(props[key]);
});

rerender(<DropdownButton overlay={<div>123</div>} visible />);
expect(dropdownProps.open).toBe(true);
});

it("don't pass visible to Dropdown if it's not exits", () => {
it("don't pass open to Dropdown if it's not exits", () => {
const menu = (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
);
render(<DropdownButton overlay={menu} />);
expect('visible' in dropdownProps).toBe(false);
expect('open' in dropdownProps).toBe(false);
});

it('should support href like Button', () => {
Expand Down Expand Up @@ -100,7 +103,7 @@ describe('DropdownButton', () => {
overlayClassName="className"
overlayStyle={{ color: 'red' }}
overlay={menu}
visible
open
/>,
);
expect(container.querySelector('.ant-dropdown')?.classList).toContain('className');
Expand Down
32 changes: 28 additions & 4 deletions components/dropdown/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('Dropdown', () => {

it('overlay is function and has custom transitionName', () => {
const { asFragment } = render(
<Dropdown overlay={() => <div>menu</div>} transitionName="move-up" visible>
<Dropdown overlay={() => <div>menu</div>} transitionName="move-up" open>
<button type="button">button</button>
</Dropdown>,
);
Expand All @@ -47,7 +47,7 @@ describe('Dropdown', () => {

it('overlay is string', () => {
const { asFragment } = render(
<Dropdown overlay={'string' as any} visible>
<Dropdown overlay={'string' as any} open>
<button type="button">button</button>
</Dropdown>,
);
Expand All @@ -64,7 +64,7 @@ describe('Dropdown', () => {
</Menu.SubMenu>
</Menu>
),
visible: true,
open: true,
getPopupContainer: node => node,
};

Expand Down Expand Up @@ -95,12 +95,13 @@ describe('Dropdown', () => {
expect(error).toHaveBeenCalledWith(
expect.stringContaining("[antd: Dropdown] You are using 'topCenter'"),
);
error.mockRestore();
});

// zombieJ: when replaced with react test lib, it may be mock fully content
it('dropdown should support auto adjust placement', () => {
render(
<Dropdown overlay={<div>menu</div>} visible>
<Dropdown overlay={<div>menu</div>} open>
<button type="button">button</button>
</Dropdown>,
);
Expand Down Expand Up @@ -166,4 +167,27 @@ describe('Dropdown', () => {

jest.useRealTimers();
});

it('deprecated warning', () => {
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

const { rerender } = render(
<Dropdown visible overlay={<div>menu</div>}>
<a />
</Dropdown>,
);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Dropdown] `visible` is deprecated which will be removed in next major version, please use `open` instead.',
);
rerender(
<Dropdown onVisibleChange={() => {}} overlay={<div>menu</div>}>
<a />
</Dropdown>,
);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Dropdown] `onVisibleChange` is deprecated which will be removed in next major version, please use `onOpenChange` instead.',
);

errSpy.mockRestore();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ import { Dropdown, Menu, Space } from 'antd';
import React, { useState } from 'react';

const App: React.FC = () => {
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);

const handleMenuClick: MenuProps['onClick'] = e => {
if (e.key === '3') {
setVisible(false);
setOpen(false);
}
};

const handleVisibleChange = (flag: boolean) => {
setVisible(flag);
const handleOpenChange = (flag: boolean) => {
setOpen(flag);
};

const menu = (
Expand All @@ -53,7 +53,7 @@ const App: React.FC = () => {
);

return (
<Dropdown overlay={menu} onVisibleChange={handleVisibleChange} visible={visible}>
<Dropdown overlay={menu} onOpenChange={handleOpenChange} open={open}>
<a onClick={e => e.preventDefault()}>
<Space>
Hover me
Expand Down
10 changes: 7 additions & 3 deletions components/dropdown/dropdown-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ const DropdownButton: DropdownButtonInterface = props => {
trigger,
align,
visible,
open,
onVisibleChange,
onOpenChange,
placement,
getPopupContainer,
href,
Expand All @@ -73,7 +75,7 @@ const DropdownButton: DropdownButtonInterface = props => {
overlay,
disabled,
trigger: disabled ? [] : trigger,
onVisibleChange,
onOpenChange: onOpenChange || onVisibleChange,
getPopupContainer: getPopupContainer || getContextPopupContainer,
mouseEnterDelay,
mouseLeaveDelay,
Expand All @@ -82,8 +84,10 @@ const DropdownButton: DropdownButtonInterface = props => {
destroyPopupOnHide,
} as DropdownProps;

if ('visible' in props) {
dropdownProps.visible = visible;
if ('open' in props) {
dropdownProps.open = open;
} else if ('visible' in props) {
dropdownProps.open = visible;
}

if ('placement' in props) {
Expand Down
43 changes: 35 additions & 8 deletions components/dropdown/dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,18 @@ export interface DropdownProps {
arrow?: boolean | DropdownArrowOptions;
trigger?: ('click' | 'hover' | 'contextMenu')[];
overlay: React.ReactElement | OverlayFunc;
/**
* @deprecated `onVisibleChange` is deprecated which will be removed in next major version. Please
* use `onOpenChange` instead.
*/
onVisibleChange?: (visible: boolean) => void;
onOpenChange?: (open: boolean) => void;
/**
* @deprecated `visible` is deprecated which will be removed in next major version. Please use
* `open` instead.
*/
visible?: boolean;
open?: boolean;
disabled?: boolean;
destroyPopupOnHide?: boolean;
align?: Align;
Expand Down Expand Up @@ -79,6 +89,20 @@ const Dropdown: DropdownInterface = props => {
direction,
} = React.useContext(ConfigContext);

// Warning for deprecated usage
if (process.env.NODE_ENV !== 'production') {
[
['visible', 'open'],
['onVisibleChange', 'onOpenChange'],
].forEach(([deprecatedName, newName]) => {
warning(
!(deprecatedName in props),
'Dropdown',
`\`${deprecatedName}\` is deprecated which will be removed in next major version, please use \`${newName}\` instead.`,
);
});
}

const getTransitionName = () => {
const rootPrefixCls = getPrefixCls();
const { placement = '', transitionName } = props;
Expand Down Expand Up @@ -119,7 +143,9 @@ const Dropdown: DropdownInterface = props => {
getPopupContainer,
overlayClassName,
visible,
open,
onVisibleChange,
onOpenChange,
} = props;

const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
Expand All @@ -143,13 +169,14 @@ const Dropdown: DropdownInterface = props => {
}

// =========================== Visible ============================
const [mergedVisible, setVisible] = useMergedState(false, {
value: visible,
const [mergedOpen, setOpen] = useMergedState(false, {
value: open !== undefined ? open : visible,
});

const onInnerVisibleChange = useEvent((nextVisible: boolean) => {
onVisibleChange?.(nextVisible);
setVisible(nextVisible);
const onInnerOpenChange = useEvent((nextOpen: boolean) => {
onVisibleChange?.(nextOpen);
onOpenChange?.(nextOpen);
setOpen(nextOpen);
});

// =========================== Overlay ============================
Expand All @@ -163,7 +190,7 @@ const Dropdown: DropdownInterface = props => {
});

const onMenuClick = React.useCallback(() => {
setVisible(false);
setOpen(false);
}, []);

const renderOverlay = () => {
Expand Down Expand Up @@ -211,7 +238,7 @@ const Dropdown: DropdownInterface = props => {
<RcDropdown
alignPoint={alignPoint}
{...props}
visible={mergedVisible}
visible={mergedOpen}
builtinPlacements={builtinPlacements}
arrow={!!arrow}
overlayClassName={overlayClassNameCustomized}
Expand All @@ -221,7 +248,7 @@ const Dropdown: DropdownInterface = props => {
trigger={triggerActions}
overlay={renderOverlay}
placement={getPlacement()}
onVisibleChange={onInnerVisibleChange}
onVisibleChange={onInnerOpenChange}
>
{dropdownTrigger}
</RcDropdown>
Expand Down
8 changes: 4 additions & 4 deletions components/dropdown/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ When there are more than a few options to choose from, you can wrap them in a `D
| overlayStyle | The style of the dropdown root element | CSSProperties | - | |
| 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`] | |
| 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 | - | |
| open | Whether the dropdown menu is currently open | boolean | - | 4.23.0 |
| onOpenChange | Called when the open state is changed. Not trigger when hidden by click item | (open: boolean) => void | - | 4.23.0 |

You should use [Menu](/components/menu/) as `overlay`. The menu items and dividers are also available by using `Menu.Item` and `Menu.Divider`.

Expand All @@ -50,6 +50,6 @@ You should use [Menu](/components/menu/) as `overlay`. The menu items and divide
| 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`] | |
| type | Type of the button, the same as [Button](/components/button/#API) | string | `default` | |
| visible | Whether the dropdown menu is currently visible | boolean | - | |
| open | Whether the dropdown menu is currently open | boolean | - | 4.23.0 |
| onClick | The same as [Button](/components/button/#API): called when you click the button on the left | (event) => void | - | |
| onVisibleChange | Called when the visible state is changed | (visible: boolean) => void | - | |
| onOpenChange | Called when the open state is changed | (open: boolean) => void | - | 4.23.0 |
8 changes: 4 additions & 4 deletions components/dropdown/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ cover: https://gw.alipayobjects.com/zos/alicdn/eedWN59yJ/Dropdown.svg
| overlayStyle | 下拉根元素的样式 | CSSProperties | - | |
| placement | 菜单弹出位置:`bottom` `bottomLeft` `bottomRight` `top` `topLeft` `topRight` | string | `bottomLeft` | |
| trigger | 触发下拉的行为, 移动端不支持 hover | Array&lt;`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
| visible | 菜单是否显示 | boolean | - | |
| onVisibleChange | 菜单显示状态改变时调用,参数为 `visible`。点击菜单按钮导致的消失不会触发 | (visible: boolean) => void | - | |
| open | 菜单是否显示 | boolean | - | 4.23.0 |
| onOpenChange | 菜单显示状态改变时调用,参数为 `visible`。点击菜单按钮导致的消失不会触发 | (open: boolean) => void | - | 4.23.0 |

`overlay` 菜单使用 [Menu](/components/menu/),还包括菜单项 `Menu.Item`,分割线 `Menu.Divider`

Expand All @@ -54,6 +54,6 @@ cover: https://gw.alipayobjects.com/zos/alicdn/eedWN59yJ/Dropdown.svg
| size | 按钮大小,和 [Button](/components/button/#API) 一致 | string | `default` | |
| trigger | 触发下拉的行为 | Array&lt;`click`\|`hover`\|`contextMenu`> | \[`hover`] | |
| type | 按钮类型,和 [Button](/components/button/#API) 一致 | string | `default` | |
| visible | 菜单是否显示 | boolean | - | |
| open | 菜单是否显示 | boolean | - | 4.23.0 |
| onClick | 点击左侧按钮的回调,和 [Button](/components/button/#API) 一致 | (event) => void | - | |
| onVisibleChange | 菜单显示状态改变时调用,参数为 `visible` | (visible: boolean) => void | - | |
| onOpenChange | 菜单显示状态改变时调用,参数为 `visible` | (open: boolean) => void | - | 4.23.0 |
4 changes: 2 additions & 2 deletions components/table/hooks/useFilter/FilterDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -464,8 +464,8 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
<Dropdown
overlay={menu}
trigger={['click']}
visible={mergedVisible}
onVisibleChange={onVisibleChange}
open={mergedVisible}
onOpenChange={onVisibleChange}
getPopupContainer={getPopupContainer}
placement={direction === 'rtl' ? 'bottomLeft' : 'bottomRight'}
>
Expand Down

0 comments on commit b1d1c49

Please sign in to comment.