Skip to content

Commit 61dec15

Browse files
committed
feat(collapse): allow hiding caret and lock state when controlled
1 parent fb55991 commit 61dec15

File tree

1 file changed

+28
-13
lines changed
  • packages/components/base/src/collapse

1 file changed

+28
-13
lines changed

packages/components/base/src/collapse/index.tsx

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from "react";
1+
import React, { useEffect, useState } from "react";
22
import styles from "./styles/index.module.scss";
33
import { Icon } from "@react-ck/icon";
44
import { IconChevronDown } from "@react-ck/icon/icons/IconChevronDown";
@@ -26,6 +26,10 @@ export interface CollapseProps extends React.DetailsHTMLAttributes<HTMLDetailsEl
2626
* @default false
2727
*/
2828
keepInDom?: boolean;
29+
/** Whether to show the caret icon.
30+
* @default true
31+
*/
32+
showCaret?: boolean;
2933
}
3034

3135
/**
@@ -47,30 +51,41 @@ export interface CollapseProps extends React.DetailsHTMLAttributes<HTMLDetailsEl
4751
*/
4852

4953
export const Collapse = ({
54+
open,
5055
header,
5156
children,
52-
onToggle,
5357
onOpenChange,
5458
spacing = "s",
5559
className,
5660
keepInDom,
61+
showCaret = true,
5762
...otherProps
5863
}: Readonly<CollapseProps>): React.ReactElement => {
59-
const [internalOpen, setInternalOpen] = useState(otherProps.open);
64+
const [internalOpen, setInternalOpen] = useState(open);
65+
66+
useEffect(() => {
67+
if (open !== undefined) setInternalOpen(open);
68+
}, [open]);
6069

6170
return (
6271
<details
6372
{...otherProps}
64-
className={classNames(className, styles[`spacing_${spacing}`])}
65-
onToggle={(e) => {
66-
setInternalOpen(e.currentTarget.open);
67-
onOpenChange?.(e.currentTarget.open);
68-
onToggle?.(e);
69-
}}>
70-
<summary className={classNames(styles.header, internalOpen && styles.header_open)}>
71-
<Icon>
72-
<IconChevronDown className={classNames(styles.icon, internalOpen && styles.icon_open)} />
73-
</Icon>
73+
open={internalOpen}
74+
className={classNames(className, styles[`spacing_${spacing}`])}>
75+
<summary
76+
className={classNames(styles.header, internalOpen && styles.header_open)}
77+
onClick={(e) => {
78+
e.preventDefault();
79+
if (open === undefined) setInternalOpen(!internalOpen);
80+
onOpenChange?.(!internalOpen);
81+
}}>
82+
{showCaret && (
83+
<Icon>
84+
<IconChevronDown
85+
className={classNames(styles.icon, internalOpen && styles.icon_open)}
86+
/>
87+
</Icon>
88+
)}
7489

7590
<div className={styles.header_content}>{header}</div>
7691
</summary>

0 commit comments

Comments
 (0)