Skip to content

Commit

Permalink
feat(expansion-panel): added controlled opening state
Browse files Browse the repository at this point in the history
  • Loading branch information
supersnager committed Feb 4, 2023
1 parent 19eeb5b commit 63c725b
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 7 deletions.
8 changes: 6 additions & 2 deletions src/components/ExpansionPanel/ExpansionPanel.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import type {ReactElement} from "react";
import type {ReactElement, MouseEvent} from "react";
import type {ChatComponentPropsChildren} from "../../types";

export interface ExpansionPanelProps {
export type ExpansionPanelOnChangeHandler<IsOpened extends boolean | undefined> = IsOpened extends boolean ? (evt: MouseEvent) => void : (state: boolean, evt: MouseEvent ) => void;

export interface ExpansionPanelProps<IsOpened extends boolean | undefined = undefined> {
title?:string;
open?:boolean;
isOpened?: IsOpened;
onChange?: ExpansionPanelOnChangeHandler<IsOpened>;
}

export declare const ExpansionPanel: (props:ChatComponentPropsChildren<ExpansionPanelProps,"div">) => ReactElement;
Expand Down
37 changes: 32 additions & 5 deletions src/components/ExpansionPanel/ExpansionPanel.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useCallback, useMemo } from "react";
import PropTypes from "prop-types";
import { prefix } from "../settings";
import classNames from "classnames";
Expand All @@ -10,6 +10,8 @@ export const ExpansionPanel = ({
children,
title,
open: defaultOpen,
isOpened,
onChange,
className,
...rest
}) => {
Expand All @@ -19,12 +21,29 @@ export const ExpansionPanel = ({

const [open, setOpen] = useState(defaultOpenFlag);

const openModifier = open === true ? `${cName}--open` : "";
const icon = open === true ? faChevronDown : faChevronLeft;
const opened = useMemo(
() => (typeof isOpened === "boolean" ? isOpened : open),
[isOpened, open]
);

const openModifier = opened === true ? `${cName}--open` : "";
const icon = opened === true ? faChevronDown : faChevronLeft;

const handleOpen = useCallback(
(e) => {
if (typeof isOpened === "boolean") {
onChange?.(e);
} else {
setOpen(!opened);
onChange?.(!opened, e);
}
},
[onChange, open, opened, isOpened]
);

return (
<div {...rest} className={classNames(cName, openModifier, className)}>
<div className={`${cName}__header`} onClick={() => setOpen(!open)}>
<div className={`${cName}__header`} onClick={handleOpen}>
<div className={`${cName}__title`}>{title}</div>
<div className={`${cName}__icon`}>
<FontAwesomeIcon icon={icon} />
Expand All @@ -35,18 +54,26 @@ export const ExpansionPanel = ({
);
};

ExpansionPanel.displayName = "ExpansionPanel";

ExpansionPanel.propTypes = {
/** Primary content. */
children: PropTypes.node,

/** Title. */
title: PropTypes.string,

/** Default open state. */
/** Default open state (uncontrolled mode). */
open: PropTypes.bool,

/** If panel is opened (controlled mode). */
isOpened: PropTypes.bool,

/** Additional classes. */
className: PropTypes.string,

/** Called when the opening state changes. */
onChange: PropTypes.func,
};

ExpansionPanel.defaultProps = {
Expand Down

0 comments on commit 63c725b

Please sign in to comment.