浏览代码

feat: collapse clickHeaderToExpand api

代强 2 年之前
父节点
当前提交
14bacab9c7

+ 1 - 0
content/show/collapse/index-en-US.md

@@ -176,6 +176,7 @@ import { IconCopy } from '@douyinfe/semi-icons';
 | accordion | Accordion mode | boolean | `false` | - |
 | activeKey | Controlled property, key of the currently expanded panel | string \| string[] | - | - |
 | className | className of Collapse | string | '' | - |
+| clickHeaderToExpand | Click Header to expand and collapse, otherwise only respond to click arrow | boolean | true | 2.32.0 |
 | collapseIcon | Custom collapsing icons | ReactNode | `<IconChevronDown />` | - |
 | defaultActiveKey | Key of the expanded panel when initialized | string \| string[] | - | - |
 | expandIcon | Custom expanding icon | ReactNode | `<IconChevronUp />` | - |

+ 1 - 0
content/show/collapse/index.md

@@ -175,6 +175,7 @@ import { IconCopy } from '@douyinfe/semi-icons';
 | accordion | 手风琴模式 | boolean | `false` | - |
 | activeKey | 受控属性, 当前展开的面板的 key | string \| string[] | 无 | - |
 | className | 样式类名 | string | '' | - |
+| clickHeaderToExpand | 点击 Header 展开收起,否则只响应点击箭头 | boolean | true | 2.32.0 |
 | collapseIcon | 自定义折叠图标 | ReactNode | `<IconChevronDown />` | - |
 | defaultActiveKey | 初始化选中面板的 key | string \| string[] | 无 | - |
 | expandIcon | 自定义展开图标 | ReactNode | `<IconChevronUp />` | - |

+ 1 - 0
packages/semi-foundation/collapse/foundation.ts

@@ -7,6 +7,7 @@ export interface CollapseProps{
     activeKey?: string | string[];
     defaultActiveKey?: string | string[];
     accordion?: boolean;
+    clickHeaderToExpand?: boolean;
     onChange?: (activeKey: CollapseProps['activeKey'], e: any) => void;
     expandIcon?: any;
     collapseIcon?: any;

+ 1 - 0
packages/semi-ui/collapse/collapse-context.tsx

@@ -5,6 +5,7 @@ export interface CollapseContextType{
     activeSet: Set<string>;
     expandIcon: React.ReactNode;
     collapseIcon: React.ReactNode;
+    clickHeaderToExpand: boolean;
     keepDOM: boolean;
     expandIconPosition: 'left' | 'right';
     onClick: (activeKey: string, e: React.MouseEvent) => void;

+ 4 - 1
packages/semi-ui/collapse/index.tsx

@@ -35,6 +35,7 @@ class Collapse extends BaseComponent<CollapseReactProps, CollapseState> {
         activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
         defaultActiveKey: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
         accordion: PropTypes.bool,
+        clickHeaderToExpand: PropTypes.bool,
         onChange: PropTypes.func,
         expandIcon: PropTypes.node,
         collapseIcon: PropTypes.node,
@@ -47,6 +48,7 @@ class Collapse extends BaseComponent<CollapseReactProps, CollapseState> {
 
     static defaultProps = {
         defaultActiveKey: '',
+        clickHeaderToExpand: true,
         onChange: noop,
         expandIconPosition: 'right'
     };
@@ -94,7 +96,7 @@ class Collapse extends BaseComponent<CollapseReactProps, CollapseState> {
 
     render() {
         // eslint-disable-next-line max-len
-        const { defaultActiveKey, accordion, style, motion, className, keepDOM, expandIconPosition, expandIcon, collapseIcon, children, ...rest } = this.props;
+        const { defaultActiveKey, accordion, style, motion, className, keepDOM, expandIconPosition, expandIcon, collapseIcon, children, clickHeaderToExpand, ...rest } = this.props;
         const clsPrefix = cls(cssClasses.PREFIX, className);
         const { activeSet } = this.state;
         return (
@@ -104,6 +106,7 @@ class Collapse extends BaseComponent<CollapseReactProps, CollapseState> {
                         activeSet,
                         expandIcon,
                         collapseIcon,
+                        clickHeaderToExpand,
                         keepDOM,
                         expandIconPosition,
                         onClick: this.onChange,

+ 9 - 4
packages/semi-ui/collapse/item.tsx

@@ -21,7 +21,7 @@ export interface CollapsePanelProps {
 
 export default class CollapsePanel extends PureComponent<CollapsePanelProps> {
     static contextType: React.Context<CollapseContextType> = CollapseContext;
-
+    headerExpandIconTriggerRef = React.createRef<HTMLElement>()
     static propTypes = {
         itemKey: PropTypes.string,
         extra: PropTypes.node,
@@ -65,7 +65,7 @@ export default class CollapsePanel extends PureComponent<CollapsePanelProps> {
             collapseIcon = (<IconChevronUp/>);
         }
         const icon = (
-            <span aria-hidden='true' className={cls([`${cssClasses.PREFIX}-header-icon`,
+            <span ref={this.headerExpandIconTriggerRef} aria-hidden='true' className={cls([`${cssClasses.PREFIX}-header-icon`,
                 { [`${cssClasses.PREFIX}-header-iconDisabled`]: !expandIconEnable }])}>
                 {/* eslint-disable-next-line no-nested-ternary */}
                 {expandIconEnable ? (active ? collapseIcon : expandIcon) : expandIcon}
@@ -93,6 +93,12 @@ export default class CollapsePanel extends PureComponent<CollapsePanelProps> {
         );
     }
 
+    handleClick = (itemKey: string, e: React.MouseEvent)=>{
+        if (this.context.clickHeaderToExpand || this.headerExpandIconTriggerRef.current?.contains(e.target as HTMLElement)) {
+            this.context.onClick(itemKey, e);
+        }
+    }
+
     render() {
         const {
             className,
@@ -109,7 +115,6 @@ export default class CollapsePanel extends PureComponent<CollapsePanelProps> {
             keepDOM,
             expandIconPosition,
             activeSet,
-            onClick,
             motion,
         } = this.context;
         const active = activeSet.has(itemKey);
@@ -136,7 +141,7 @@ export default class CollapsePanel extends PureComponent<CollapsePanelProps> {
                     aria-disabled={disabled}
                     aria-expanded={active ? 'true' : 'false'}
                     aria-owns={this.ariaID}
-                    onClick={e => !disabled && onClick(itemKey, e)}
+                    onClick={e => !disabled && this.handleClick(itemKey, e)}
                 >
                     {this.renderHeader(active, children !== undefined && !disabled)}
                 </div>