From cc5108b1803d6bde840cb7af1de69bff9e98192f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Sat, 20 May 2023 16:36:37 +0800 Subject: [PATCH 1/4] feat: keyPress => keyDown --- README.md | 6 ++++++ docs/examples/basic.tsx | 8 +++++++- src/Collapse.tsx | 2 ++ src/Panel.tsx | 6 ++++-- src/hooks/useItems.tsx | 5 ++++- src/interface.ts | 2 ++ tests/index.spec.tsx | 6 +++--- 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 898e727..da46f2f 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,12 @@ If `accordion` is true, only one panel can be open. Opening another panel will c - specify whether the panel be collapsible or the area of collapsible. + + changeByClickOnly + boolean + false + If pass true, the collapse will not change open state when keydown enter. + diff --git a/docs/examples/basic.tsx b/docs/examples/basic.tsx index 4b45637..f02168d 100644 --- a/docs/examples/basic.tsx +++ b/docs/examples/basic.tsx @@ -6,8 +6,14 @@ import '../../assets/index.less'; const App = () => { const items: CollapseProps['items'] = [ { - label: 'title', + label: , children: 'content', + changeByClickOnly: true, + }, + { + label: , + children: 'content', + collapsible: 'icon', }, { label: 'title 2', diff --git a/src/Collapse.tsx b/src/Collapse.tsx index 36267d2..83ca5d7 100644 --- a/src/Collapse.tsx +++ b/src/Collapse.tsx @@ -31,6 +31,7 @@ const Collapse = React.forwardRef((props, ref) => defaultActiveKey, onChange, items, + changeByClickOnly = false, } = props; const collapseClassName = classNames(prefixCls, className); @@ -72,6 +73,7 @@ const Collapse = React.forwardRef((props, ref) => destroyInactivePanel, onItemClick, activeKey, + changeByClickOnly, }); // ======================== Render ======================== diff --git a/src/Panel.tsx b/src/Panel.tsx index af5a1c9..ec2c516 100644 --- a/src/Panel.tsx +++ b/src/Panel.tsx @@ -23,6 +23,7 @@ const CollapsePanel = React.forwardRef((prop openMotion, destroyInactivePanel, children, + changeByClickOnly = false, ...resetProps } = props; @@ -36,7 +37,7 @@ const CollapsePanel = React.forwardRef((prop onItemClick?.(panelKey!); }; - const handleKeyPress = (e: React.KeyboardEvent) => { + const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.keyCode === KeyCode.ENTER || e.which === KeyCode.ENTER) { handleItemClick(); } @@ -76,7 +77,8 @@ const CollapsePanel = React.forwardRef((prop className: headerClassName, 'aria-expanded': isActive, 'aria-disabled': disabled, - onKeyPress: handleKeyPress, + onKeyDown: + (!collapsible || collapsibleHeader) && !changeByClickOnly ? handleKeyDown : undefined, }; if (!collapsibleHeader && !collapsibleIcon) { diff --git a/src/hooks/useItems.tsx b/src/hooks/useItems.tsx index 2bc5db7..384aa4c 100644 --- a/src/hooks/useItems.tsx +++ b/src/hooks/useItems.tsx @@ -4,7 +4,10 @@ import type { CollapsePanelProps, CollapseProps, ItemType } from '../interface'; import CollapsePanel from '../Panel'; type Props = Pick & - Pick & { + Pick< + CollapseProps, + 'accordion' | 'collapsible' | 'destroyInactivePanel' | 'changeByClickOnly' + > & { activeKey: React.Key[]; }; diff --git a/src/interface.ts b/src/interface.ts index 838446a..721d757 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -31,6 +31,7 @@ export interface CollapseProps { destroyInactivePanel?: boolean; expandIcon?: (props: object) => React.ReactNode; collapsible?: CollapsibleType; + changeByClickOnly?: boolean; children?: React.ReactNode; /** * Collapse items content @@ -59,4 +60,5 @@ export interface CollapsePanelProps extends React.DOMAttributes role?: string; collapsible?: CollapsibleType; children?: React.ReactNode; + changeByClickOnly?: boolean; } diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index 533df08..a845bdf 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -401,11 +401,11 @@ describe('collapse', () => { , ); - fireEvent.keyPress(container.querySelectorAll('.rc-collapse-header')?.[2], myKeyEvent); + fireEvent.keyDown(container.querySelectorAll('.rc-collapse-header')?.[2], myKeyEvent); jest.runAllTimers(); expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); - fireEvent.keyPress(container.querySelector('.rc-collapse-header')!, myKeyEvent); + fireEvent.keyDown(container.querySelector('.rc-collapse-header')!, myKeyEvent); jest.runAllTimers(); expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(1); @@ -414,7 +414,7 @@ describe('collapse', () => { 'rc-collapse-content-active', ); - fireEvent.keyPress(container.querySelector('.rc-collapse-header')!, myKeyEvent); + fireEvent.keyDown(container.querySelector('.rc-collapse-header')!, myKeyEvent); jest.runAllTimers(); expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); From 09ce19a011eec9add8d52c0a23888624b63e2d77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Sun, 21 May 2023 21:27:05 +0800 Subject: [PATCH 2/4] feat: update test case --- tests/index.spec.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index a845bdf..ef75ad7 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -396,7 +396,13 @@ describe('collapse', () => { second - second + third + + + four + + + five , ); @@ -421,6 +427,14 @@ describe('collapse', () => { expect(container.querySelector('.rc-collapse-content')!.className).not.toContain( 'rc-collapse-content-active', ); + + fireEvent.keyDown(container.querySelectorAll('.rc-collapse-header')?.[3], myKeyEvent); + jest.runAllTimers(); + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); + + fireEvent.keyDown(container.querySelectorAll('.rc-collapse-header')?.[4], myKeyEvent); + jest.runAllTimers(); + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); }); describe('wrapped in Fragment', () => { From 055ca1cae06cae0a08c21cffd381de17ef04267f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Mon, 22 May 2023 10:57:52 +0800 Subject: [PATCH 3/4] feat: optimize code --- README.md | 41 +++++++++++++++++++++++++++++++++++------ docs/examples/basic.tsx | 8 +------- src/Collapse.tsx | 9 +++++++-- src/Panel.tsx | 4 +--- src/hooks/useItems.tsx | 5 +---- src/interface.ts | 2 -- tests/index.spec.tsx | 14 -------------- 7 files changed, 45 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index da46f2f..92a1967 100644 --- a/README.md +++ b/README.md @@ -190,12 +190,6 @@ If `accordion` is true, only one panel can be open. Opening another panel will c - specify whether the panel be collapsible or the area of collapsible. - - changeByClickOnly - boolean - false - If pass true, the collapse will not change open state when keydown enter. - @@ -205,6 +199,41 @@ If `accordion` is true, only one panel can be open. Opening another panel will c If `key` is not provided, the panel's index will be used instead. +#### KeyBoard Event + +By default, Collapse will listen `onKeyDown`(<3.7.0 `onKeyPress`) event with `enter` key to toggle panel's active state when `collapsible` is not `disabled`. If you want to disable this behavior, you can prevent the event from bubbling like this: + +```jsx +const App = () => { + const items: CollapseProps['items'] = [ + { + label: e.stopPropagation()} />, + children: 'content', + }, + { + label: ( +
e.stopPropagation()}> + +
+ ), + children: 'content', + }, + { + label: 'title 2', + children: 'content 2', + collapsible: 'disabled', + }, + { + label: 'title 3', + children: 'content 3', + onItemClick: console.log, + }, + ]; + + return ; +}; +``` + ## Development ```bash diff --git a/docs/examples/basic.tsx b/docs/examples/basic.tsx index f02168d..dcd1ff7 100644 --- a/docs/examples/basic.tsx +++ b/docs/examples/basic.tsx @@ -6,14 +6,8 @@ import '../../assets/index.less'; const App = () => { const items: CollapseProps['items'] = [ { - label: , + label: e.stopPropagation()} />, children: 'content', - changeByClickOnly: true, - }, - { - label: , - children: 'content', - collapsible: 'icon', }, { label: 'title 2', diff --git a/src/Collapse.tsx b/src/Collapse.tsx index 83ca5d7..118aca5 100644 --- a/src/Collapse.tsx +++ b/src/Collapse.tsx @@ -31,9 +31,15 @@ const Collapse = React.forwardRef((props, ref) => defaultActiveKey, onChange, items, - changeByClickOnly = false, } = props; + if (process.env.NODE_ENV === 'development') { + warning( + false, + `[Collapse] Please use 'onKeyDown' instead of 'onKeyPress to prevent the event from bubbling.`, + ); + } + const collapseClassName = classNames(prefixCls, className); const [activeKey, setActiveKey] = useMergedState([], { @@ -73,7 +79,6 @@ const Collapse = React.forwardRef((props, ref) => destroyInactivePanel, onItemClick, activeKey, - changeByClickOnly, }); // ======================== Render ======================== diff --git a/src/Panel.tsx b/src/Panel.tsx index ec2c516..34d65f7 100644 --- a/src/Panel.tsx +++ b/src/Panel.tsx @@ -23,7 +23,6 @@ const CollapsePanel = React.forwardRef((prop openMotion, destroyInactivePanel, children, - changeByClickOnly = false, ...resetProps } = props; @@ -77,8 +76,7 @@ const CollapsePanel = React.forwardRef((prop className: headerClassName, 'aria-expanded': isActive, 'aria-disabled': disabled, - onKeyDown: - (!collapsible || collapsibleHeader) && !changeByClickOnly ? handleKeyDown : undefined, + onKeyDown: handleKeyDown, }; if (!collapsibleHeader && !collapsibleIcon) { diff --git a/src/hooks/useItems.tsx b/src/hooks/useItems.tsx index 384aa4c..2bc5db7 100644 --- a/src/hooks/useItems.tsx +++ b/src/hooks/useItems.tsx @@ -4,10 +4,7 @@ import type { CollapsePanelProps, CollapseProps, ItemType } from '../interface'; import CollapsePanel from '../Panel'; type Props = Pick & - Pick< - CollapseProps, - 'accordion' | 'collapsible' | 'destroyInactivePanel' | 'changeByClickOnly' - > & { + Pick & { activeKey: React.Key[]; }; diff --git a/src/interface.ts b/src/interface.ts index 721d757..838446a 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -31,7 +31,6 @@ export interface CollapseProps { destroyInactivePanel?: boolean; expandIcon?: (props: object) => React.ReactNode; collapsible?: CollapsibleType; - changeByClickOnly?: boolean; children?: React.ReactNode; /** * Collapse items content @@ -60,5 +59,4 @@ export interface CollapsePanelProps extends React.DOMAttributes role?: string; collapsible?: CollapsibleType; children?: React.ReactNode; - changeByClickOnly?: boolean; } diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index ef75ad7..34f49d5 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -398,12 +398,6 @@ describe('collapse', () => { third - - four - - - five - , ); @@ -427,14 +421,6 @@ describe('collapse', () => { expect(container.querySelector('.rc-collapse-content')!.className).not.toContain( 'rc-collapse-content-active', ); - - fireEvent.keyDown(container.querySelectorAll('.rc-collapse-header')?.[3], myKeyEvent); - jest.runAllTimers(); - expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); - - fireEvent.keyDown(container.querySelectorAll('.rc-collapse-header')?.[4], myKeyEvent); - jest.runAllTimers(); - expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); }); describe('wrapped in Fragment', () => { From 3158d3fbb90fb2de2029cb136dd019a14a5c7a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Mon, 22 May 2023 11:21:43 +0800 Subject: [PATCH 4/4] feat: remove warning --- src/Collapse.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Collapse.tsx b/src/Collapse.tsx index 118aca5..36267d2 100644 --- a/src/Collapse.tsx +++ b/src/Collapse.tsx @@ -33,13 +33,6 @@ const Collapse = React.forwardRef((props, ref) => items, } = props; - if (process.env.NODE_ENV === 'development') { - warning( - false, - `[Collapse] Please use 'onKeyDown' instead of 'onKeyPress to prevent the event from bubbling.`, - ); - } - const collapseClassName = classNames(prefixCls, className); const [activeKey, setActiveKey] = useMergedState([], {