monday-ui-react-core
Version:
Official monday.com UI resources for application development in React.js
110 lines (102 loc) • 3.29 kB
JSX
import React, { useState, useRef, forwardRef, useCallback } from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import useMergeRefs from "../../hooks/useMergeRefs";
import "./ExpandCollapse.scss";
import Icon from "../Icon/Icon";
import Heading from "../Heading/Heading";
import { TYPES } from "../Heading/HeadingConstants";
import DropdownChevronDown from "../Icon/Icons/components/DropdownChevronDown";
const ExpandCollapse = forwardRef(
({ children, headerComponentRenderer, title, className, defaultOpenState, iconSize, id, open, onClick }, ref) => {
const componentRef = useRef(null);
const mergedRef = useMergeRefs({ refs: [ref, componentRef] });
const [isOpen, setIsOpen] = useState(defaultOpenState);
const isExpanded = open === undefined ? isOpen : open;
const toogleExpand = () => {
setIsOpen(!isOpen);
};
const renderHeader = useCallback(() => {
return <Heading type={TYPES.h5} value={title} className="expand-collapse__header-content" />;
}, [title]);
return (
<div ref={mergedRef} className={cx("expand-collapse--wrapper", className)} id={id}>
<div className="expand-collapse">
<button
type="button"
className={cx("expand-collapse__header", "expand-collapse__section", {
"expand-collapse__header--open": isExpanded
})}
onClickCapture={onClick || toogleExpand}
aria-expanded={isExpanded}
aria-controls={`${id}-controls`}
>
{title.length !== 0 ? renderHeader() : headerComponentRenderer && headerComponentRenderer()}
<Icon
className={isExpanded ? "animate-icon-open" : "animate-icon-close"}
iconType={Icon.type.SVG}
icon={DropdownChevronDown}
iconSize={iconSize}
tabindex="-1"
clickable={false}
/>
</button>
{isExpanded && (
<div
className={`expand-collapse__content expand-collapse__section ${isExpanded &&
"animate-expand-collapse__content"}`}
id={`${id}-controls`}
role="region"
>
{children}
</div>
)}
</div>
</div>
);
}
);
ExpandCollapse.propTypes = {
/**
* Id for the component
*/
id: PropTypes.string,
/**
* Component as parameter to be rendered as header
*/
headerComponentRenderer: PropTypes.func,
/**
* Header title
*/
title: PropTypes.string,
/**
* The value of the expandable section
*/
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
/**
* Custom styling
*/
className: PropTypes.string,
/**
* The expand icon font size
*/
iconSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
/**
* Should be open or closed by default (when rendered)
*/
defaultOpenState: PropTypes.bool,
open: PropTypes.bool,
onClick: PropTypes.func
};
ExpandCollapse.defaultProps = {
id: "",
className: "",
defaultOpenState: false,
iconSize: 24,
onClick: null,
title: "",
headerComponentRenderer: null,
children: null,
open: undefined
};
export default ExpandCollapse;