glass-app-manager
Version:
Informatica's Glass Framework CLI for bootstrapping
94 lines (80 loc) • 2.9 kB
JavaScript
//@flow
import * as React from "react";
import classNames from "classnames";
export type SectionProps = {
children: React.Node,
className?: string,
/**
* Show a toggle button to allow the Section's content to be collapsible
*/
collapsible?: boolean,
/**
* If the Section has collapsible set, you may set the initial state to collapsed
*/
initialCollapsed?: boolean,
/**
* The maximum height of the entire Section container.
* Contents of the section will be scrollable if they exceed the height of the container.
*/
maxHeight?: number,
/**
* A Section requires a title. In most cases this should be a string.
*/
title: React.ChildrenArray<string | React.Element<any>>,
style?: {},
/**
* Renders a `Toolbar` component right-aligned in the Section's header.
* Internal state of the section such as expanded is provided as arguments to the function.
*/
toolbar?: ({ expanded: boolean }) => React.Node,
};
function Section({
children,
className,
collapsible = false,
initialCollapsed = false,
title,
toolbar,
style = {},
maxHeight,
...rest
}: SectionProps) {
const [expanded, toggleExpanded] = React.useReducer(state => !state, !initialCollapsed);
const calculatedStyle = React.useMemo(() => ({ ...style, ...(maxHeight ? { maxHeight: `${maxHeight}px` } : {}) }), [
style,
maxHeight,
]);
const handleCollapseKeyDown = React.useCallback((e: SyntheticKeyboardEvent<HTMLElement>) => {
if (e.key === "Enter") {
toggleExpanded();
}
}, []);
return (
<div
className={classNames("section", className, { "section--collapsed": !expanded })}
{...rest}
style={calculatedStyle}>
<div className="section__header">
<div className="section__header__container">
{collapsible ? (
<i
onKeyDown={handleCollapseKeyDown}
role="button"
tabIndex="0"
className={classNames("section__header__toggle-expansion-icon", {
"section__header__toggle-expansion-icon--expanded": expanded,
})}
onClick={toggleExpanded}
/>
) : null}
{title}
{toolbar ? toolbar({ expanded }) : null}
</div>
</div>
<div className={classNames("section__content", { "section__content--collapsed": !expanded })}>
{children}
</div>
</div>
);
}
export default Section;