parent
a7b80b2e36
commit
767288aa96
3 changed files with 89 additions and 1 deletions
@ -0,0 +1,61 @@ |
|||||||
|
import { |
||||||
|
ExpandLess as ExpandLessIcon, |
||||||
|
ExpandMore as ExpandMoreIcon, |
||||||
|
} from '@mui/icons-material'; |
||||||
|
import { Box, IconButton } from '@mui/material'; |
||||||
|
import { FC, ReactNode, useMemo, useState } from 'react'; |
||||||
|
|
||||||
|
import { GREY } from '../../lib/consts/DEFAULT_THEME'; |
||||||
|
|
||||||
|
import InnerPanel from './InnerPanel'; |
||||||
|
import InnerPanelBody from './InnerPanelBody'; |
||||||
|
import InnerPanelHeader from './InnerPanelHeader'; |
||||||
|
|
||||||
|
type ExpandablePanelOptionalProps = { |
||||||
|
isExpandInitially?: boolean; |
||||||
|
}; |
||||||
|
|
||||||
|
type ExpandablePanelProps = ExpandablePanelOptionalProps & { |
||||||
|
header: ReactNode; |
||||||
|
}; |
||||||
|
|
||||||
|
const EXPANDABLE_PANEL_DEFAULT_PROPS: Required<ExpandablePanelOptionalProps> = { |
||||||
|
isExpandInitially: false, |
||||||
|
}; |
||||||
|
|
||||||
|
const ExpandablePanel: FC<ExpandablePanelProps> = ({ |
||||||
|
children, |
||||||
|
header, |
||||||
|
isExpandInitially = EXPANDABLE_PANEL_DEFAULT_PROPS.isExpandInitially, |
||||||
|
}) => { |
||||||
|
const [isExpand, setIsExpand] = useState<boolean>(isExpandInitially); |
||||||
|
|
||||||
|
const expandButtonIcon = useMemo( |
||||||
|
() => (isExpand ? <ExpandLessIcon /> : <ExpandMoreIcon />), |
||||||
|
[isExpand], |
||||||
|
); |
||||||
|
const contentHeight = useMemo(() => (isExpand ? 'auto' : '.2em'), [isExpand]); |
||||||
|
|
||||||
|
return ( |
||||||
|
<InnerPanel> |
||||||
|
<InnerPanelHeader> |
||||||
|
{header} |
||||||
|
<IconButton |
||||||
|
onClick={() => { |
||||||
|
setIsExpand((previous) => !previous); |
||||||
|
}} |
||||||
|
sx={{ color: GREY, padding: '.2em' }} |
||||||
|
> |
||||||
|
{expandButtonIcon} |
||||||
|
</IconButton> |
||||||
|
</InnerPanelHeader> |
||||||
|
<Box sx={{ height: contentHeight, overflowY: 'hidden' }}> |
||||||
|
<InnerPanelBody>{children}</InnerPanelBody> |
||||||
|
</Box> |
||||||
|
</InnerPanel> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
ExpandablePanel.defaultProps = EXPANDABLE_PANEL_DEFAULT_PROPS; |
||||||
|
|
||||||
|
export default ExpandablePanel; |
@ -0,0 +1,18 @@ |
|||||||
|
import { Box, BoxProps } from '@mui/material'; |
||||||
|
import { FC } from 'react'; |
||||||
|
|
||||||
|
const InnerPanelBody: FC<BoxProps> = ({ sx, ...innerPanelBodyRestProps }) => ( |
||||||
|
<Box |
||||||
|
{...{ |
||||||
|
...innerPanelBodyRestProps, |
||||||
|
sx: { |
||||||
|
paddingLeft: '.7em', |
||||||
|
paddingRight: '.7em', |
||||||
|
paddingTop: '.3em', |
||||||
|
...sx, |
||||||
|
}, |
||||||
|
}} |
||||||
|
/> |
||||||
|
); |
||||||
|
|
||||||
|
export default InnerPanelBody; |
@ -1,6 +1,15 @@ |
|||||||
|
import ExpandablePanel from './ExpandablePanel'; |
||||||
import InnerPanel from './InnerPanel'; |
import InnerPanel from './InnerPanel'; |
||||||
|
import InnerPanelBody from './InnerPanelBody'; |
||||||
import InnerPanelHeader from './InnerPanelHeader'; |
import InnerPanelHeader from './InnerPanelHeader'; |
||||||
import Panel from './Panel'; |
import Panel from './Panel'; |
||||||
import PanelHeader from './PanelHeader'; |
import PanelHeader from './PanelHeader'; |
||||||
|
|
||||||
export { InnerPanel, InnerPanelHeader, Panel, PanelHeader }; |
export { |
||||||
|
ExpandablePanel, |
||||||
|
InnerPanel, |
||||||
|
InnerPanelBody, |
||||||
|
InnerPanelHeader, |
||||||
|
Panel, |
||||||
|
PanelHeader, |
||||||
|
}; |
||||||
|
Loading…
Reference in new issue