Update sidePanel to support multiple components

This commit is contained in:
Gustavo Lelis 2020-04-22 23:13:08 -03:00 committed by James A. Petts
parent 802a8d5f1b
commit 08ebfd5865
3 changed files with 181 additions and 105 deletions

View File

@ -1,4 +1,4 @@
import React, { useState, useCallback } from 'react'; import React, { useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
@ -53,30 +53,78 @@ const position = {
}, },
}; };
const getChildComponent = (childComponents, componentOpen) => {
if (Array.isArray(childComponents)) {
return childComponents.find(
(_childComponent) => _childComponent.name === componentOpen
);
} else {
return childComponents;
}
};
const SidePanel = ({ const SidePanel = ({
side, side,
className, className,
children, defaultComponentOpen,
defaultIsOpen, childComponents,
componentLabel,
iconLabel,
iconName,
}) => { }) => {
const [isOpen, setIsOpen] = useState(defaultIsOpen); const [componentOpen, setComponentOpen] = useState(defaultComponentOpen);
const openStatus = isOpen ? 'open' : 'closed';
const openStatus = componentOpen ? 'open' : 'closed';
const style = Object.assign({}, styleMap[openStatus][side], baseStyle); const style = Object.assign({}, styleMap[openStatus][side], baseStyle);
const getSidePanelHeader = useCallback(() => { const childComponent = getChildComponent(childComponents, componentOpen);
return (
<React.Fragment> const getPanelButtons = () => {
{isOpen ? ( const _childComponents = Array.isArray(childComponents)
? childComponents
: [childComponents];
return _childComponents.map((childComponent) => {
return (
<Button
key={childComponent.name}
variant="text"
color="inherit"
onClick={() => {
setComponentOpen(childComponent.name);
}}
style={{
minWidth: `${collapsedWidth}px`,
width: `${collapsedWidth}px`,
}}
className="flex flex-col text-xs px-1 py-1 text-white border-transparent border-b"
>
<Icon
name={childComponent.iconName}
className="text-primary-active"
/>
<span className="mt-2 text-white text-xs">
{childComponent.iconLabel}
</span>
</Button>
);
});
};
return (
<div
className={classnames(
className,
baseClasses,
classesMap[openStatus][side]
)}
style={style}
>
{componentOpen ? (
<React.Fragment>
<div className="px-3 border-b border-secondary-light"> <div className="px-3 border-b border-secondary-light">
<Button <Button
variant="text" variant="text"
color="inherit" color="inherit"
rounded="none" rounded="none"
onClick={() => { onClick={() => {
setIsOpen(false); setComponentOpen(null);
}} }}
className="flex flex-row items-center px-3 h-12 relative w-full" className="flex flex-row items-center px-3 h-12 relative w-full"
> >
@ -89,58 +137,45 @@ const SidePanel = ({
style={{ ...position[side] }} style={{ ...position[side] }}
/> />
<span className="flex-1 text-primary-active"> <span className="flex-1 text-primary-active">
{componentLabel} {childComponent.label}
</span> </span>
</Button> </Button>
</div> </div>
) : ( {childComponent.content}
<Button </React.Fragment>
variant="text" ) : (
color="inherit" <React.Fragment>{getPanelButtons()}</React.Fragment>
onClick={() => {
setIsOpen(true);
}}
style={{
minWidth: `${collapsedWidth}px`,
width: `${collapsedWidth}px`,
}}
className="flex flex-col text-xs px-1 py-1 text-white border-transparent border-b"
>
<Icon name={iconName} className="text-primary-active" />
<span className="mt-2 text-white text-xs">{iconLabel}</span>
</Button>
)}
</React.Fragment>
);
}, [componentLabel, iconLabel, iconName, isOpen, side]);
return (
<div
className={classnames(
className,
baseClasses,
classesMap[openStatus][side]
)} )}
style={style}
>
{getSidePanelHeader()}
{isOpen && children}
</div> </div>
); );
}; };
SidePanel.defaultProps = { SidePanel.defaultProps = {
defaultIsOpen: false, defaultComponentOpen: null,
}; };
SidePanel.propTypes = { SidePanel.propTypes = {
side: PropTypes.oneOf(['left', 'right']).isRequired, side: PropTypes.oneOf(['left', 'right']).isRequired,
iconLabel: PropTypes.string.isRequired,
componentLabel: PropTypes.string.isRequired,
iconName: PropTypes.string.isRequired,
defaultIsOpen: PropTypes.bool,
className: PropTypes.string, className: PropTypes.string,
children: PropTypes.node, defaultComponentOpen: PropTypes.string,
childComponents: PropTypes.oneOfType([
PropTypes.shape({
iconName: PropTypes.string.isRequired,
iconLabel: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
content: PropTypes.node,
}),
PropTypes.arrayOf(
PropTypes.shape({
iconName: PropTypes.string.isRequired,
iconLabel: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
content: PropTypes.node,
})
),
]),
}; };
export default SidePanel; export default SidePanel;

View File

@ -24,19 +24,52 @@ import { SidePanel } from '@ohif/ui';
> >
<SidePanel <SidePanel
side="left" side="left"
iconName="group-layers" childComponents={{
iconLabel="Studies" iconName: "group-layers",
componentLabel="Studies" iconLabel: "Studies",
defaultIsOpen={false} name: "studies",
> label: "Studies",
<div className="flex justify-center text-white p-2">panel content</div> content: <div className="flex justify-center text-white p-2">panel content</div>,
</SidePanel> }}
/>
<div className="flex flex-1 h-100 overflow-hidden bg-primary-main items-center justify-center text-white"> <div className="flex flex-1 h-100 overflow-hidden bg-primary-main items-center justify-center text-white">
CONTENT CONTENT
</div> </div>
</div> </div>
</Playground> </Playground>
## Multiple panels
<Playground>
<div
className="flex flex-row flex-no-wrap flex-1 items-stretch overflow-hidden w-full"
style={{ height: '500px' }}
>
<SidePanel
side="left"
childComponents={[{
iconName: "group-layers",
iconLabel: "Studies",
name: "studies",
label: "Studies",
content: <div className="flex justify-center text-white p-2">studies panel content</div>,
},
{
iconName: "list-bullets",
iconLabel: "Measure",
name: "measurements",
label: "Measurements",
content: <div className="flex justify-center text-white p-2">measure panel content</div>,
}]}
/>
<div className="flex flex-1 h-100 overflow-hidden bg-primary-main items-center justify-center text-white">
CONTENT
</div>
</div>
</Playground>
## Properties ## Properties
<Props of={SidePanel} /> <Props of={SidePanel} />

View File

@ -57,14 +57,18 @@ import { tabs } from './studyBrowserMockData';
> >
<SidePanel <SidePanel
side="left" side="left"
iconName="group-layers" defaultComponentOpen='studies'
iconLabel="Studies" childComponents={{
componentLabel="Studies" iconName: 'group-layers',
defaultIsOpen={true} iconLabel: 'Studies',
> label: 'Studies',
<StudyBrowser tabs={tabs} /> name: 'studies',
</SidePanel> content: (
<div className="flex flex-col flex-1 h-100"> <StudyBrowser tabs={tabs} />
)
}}
/>
<div className="flex flex-col flex-1 h-full pb-2">
<div className="flex flex-2 w-100 border-b border-transparent h-12"> <div className="flex flex-2 w-100 border-b border-transparent h-12">
<ViewportToolbar /> <ViewportToolbar />
</div> </div>
@ -100,45 +104,49 @@ import { tabs } from './studyBrowserMockData';
</div> </div>
<SidePanel <SidePanel
side="right" side="right"
iconName="list-bullets" defaultComponentOpen="measurements"
iconLabel="Measure" childComponents={{
componentLabel="Measurements" iconName: 'list-bullets',
defaultIsOpen={true} iconLabel: 'Measure',
> label: 'Measurements',
<MeasurementsPanel name: 'measurements',
descriptionData={descriptionData} content: (
measurementTableData={measurementTableData} <MeasurementsPanel
actionButtons={ descriptionData={descriptionData}
<> measurementTableData={measurementTableData}
<ButtonGroup onClick={() => alert('Export')}> actionButtons={
<Button <React.Fragment>
className="text-white border-primary-main bg-black text-base py-2 px-2" <ButtonGroup onClick={() => alert('Export')}>
size="initial" <Button
color="inherit" className="text-white border-primary-main bg-black text-base py-2 px-2"
> size="initial"
Export color="inherit"
</Button> >
<IconButton Export
className="bg-black border-primary-main px-2 text-white px-2" </Button>
color="inherit" <IconButton
size="initial" className="bg-black border-primary-main px-2 text-white px-2"
> color="inherit"
<Icon name="arrow-down" /> size="initial"
</IconButton> >
</ButtonGroup> <Icon name="arrow-down" />
<Button </IconButton>
className="text-white border border-primary-main bg-black text-base py-2 px-2 ml-2" </ButtonGroup>
variant="outlined" <Button
size="initial" className="text-white border border-primary-main bg-black text-base py-2 px-2 ml-2"
color="inherit" variant="outlined"
onClick={() => alert('Create Report')} size="initial"
> color="inherit"
Create Report onClick={() => alert('Create Report')}
</Button> >
</> Create Report
} </Button>
/> </React.Fragment>
</SidePanel> }
/>
)
}}
/>
</div> </div>
</div> </div>
); );