@grafana/ui
Version:
Grafana Components Library
120 lines (117 loc) • 3.67 kB
JavaScript
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import { css, cx } from '@emotion/css';
import { uniqueId } from 'lodash';
import { useState, useRef } from 'react';
import { useStyles2 } from '../../themes/ThemeContext.mjs';
import { getFocusStyles } from '../../themes/mixins.mjs';
import { Icon } from '../Icon/Icon.mjs';
import { Spinner } from '../Spinner/Spinner.mjs';
"use strict";
const CollapsableSection = ({
label,
isOpen,
onToggle,
className,
contentClassName,
children,
labelId,
loading = false,
headerDataTestId,
contentDataTestId,
unmountContentWhenClosed = true
}) => {
const [internalOpenState, toggleInternalOpenState] = useState(isOpen);
const styles = useStyles2(collapsableSectionStyles);
const isControlled = isOpen !== void 0 && onToggle !== void 0;
const isSectionOpen = isControlled ? isOpen : internalOpenState;
const onClick = (e) => {
if (e.target instanceof HTMLElement && e.target.tagName === "A") {
return;
}
e.preventDefault();
e.stopPropagation();
onToggle == null ? void 0 : onToggle(!isOpen);
if (!isControlled) {
toggleInternalOpenState(!internalOpenState);
}
};
const { current: id } = useRef(uniqueId());
const buttonLabelId = labelId != null ? labelId : `collapse-label-${id}`;
const content = /* @__PURE__ */ jsx(
"div",
{
id: `collapse-content-${id}`,
className: cx(styles.content, contentClassName, {
[styles.contentHidden]: !unmountContentWhenClosed && !isSectionOpen
}),
"data-testid": contentDataTestId,
children
}
);
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs("div", { onClick, className: cx(styles.header, className), children: [
/* @__PURE__ */ jsx(
"button",
{
type: "button",
id: `collapse-button-${id}`,
className: styles.button,
onClick,
"aria-expanded": isSectionOpen && !loading,
"aria-controls": `collapse-content-${id}`,
"aria-labelledby": buttonLabelId,
children: loading ? /* @__PURE__ */ jsx(Spinner, { className: styles.spinner }) : /* @__PURE__ */ jsx(Icon, { name: isSectionOpen ? "angle-down" : "angle-right", className: styles.icon })
}
),
/* @__PURE__ */ jsx("div", { className: styles.label, id: `collapse-label-${id}`, "data-testid": headerDataTestId, children: label })
] }),
unmountContentWhenClosed ? isSectionOpen && content : content
] });
};
const collapsableSectionStyles = (theme) => ({
header: css({
display: "flex",
alignItems: "center",
cursor: "pointer",
boxSizing: "border-box",
position: "relative",
justifyContent: "flex-start",
fontSize: theme.typography.size.lg,
padding: `${theme.spacing(0.5)} 0`,
"&:focus-within": getFocusStyles(theme)
}),
button: css({
all: "unset",
marginRight: theme.spacing(1),
"&:focus-visible": {
outline: "none",
outlineOffset: "unset",
[theme.transitions.handleMotion("no-preference", "reduce")]: {
transition: "none"
},
boxShadow: "none"
}
}),
icon: css({
color: theme.colors.text.secondary
}),
content: css({
padding: `${theme.spacing(2)} 0`
}),
contentHidden: css({
display: "none"
}),
spinner: css({
display: "flex",
alignItems: "center",
width: theme.spacing(2)
}),
label: css({
display: "flex",
flex: "1 1 auto",
fontWeight: theme.typography.fontWeightMedium,
color: theme.colors.text.maxContrast
})
});
export { CollapsableSection };
//# sourceMappingURL=CollapsableSection.mjs.map