Skip to content

Commit 9a3b368

Browse files
authored
Merge pull request #863 from Vidit-Kushwaha/feat/panel
[component] Added Panel component to sistent
2 parents fdb745a + df32123 commit 9a3b368

File tree

8 files changed

+303
-3
lines changed

8 files changed

+303
-3
lines changed

package-lock.json

Lines changed: 42 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@
119119
"billboard.js": "^3.14.3",
120120
"js-yaml": "^4.1.0",
121121
"lodash": "^4.17.21",
122+
"re-resizable": "^6.10.3",
123+
"react-draggable": "^4.4.6",
122124
"moment": "^2.30.1",
123125
"react-share": "^5.1.0"
124126
}

src/custom/Panel/Panel.tsx

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { Resizable } from 're-resizable';
2+
import React from 'react';
3+
import Draggable from 'react-draggable';
4+
import { Box, BoxProps, IconButton, Tooltip } from '../../base';
5+
import { CloseIcon, CollapseAllIcon, ExpandAllIcon } from '../../icons';
6+
import { PanelDragHandleIcon } from '../../icons/PanelDragHandle';
7+
import { useTheme } from '../../theme';
8+
import { ErrorBoundary } from '../ErrorBoundary';
9+
import {
10+
DragHandle,
11+
DrawerHeader,
12+
HeaderActionsContainer,
13+
HeaderContainer,
14+
PanelBody,
15+
PanelContainer,
16+
ResizableContent
17+
} from './style';
18+
19+
export type PanelProps = {
20+
isOpen: boolean;
21+
children: React.ReactNode;
22+
areAllExpanded?: boolean;
23+
toggleExpandAll?: () => void;
24+
handleClose: () => void;
25+
sx?: BoxProps['sx'];
26+
id?: string;
27+
intitialPosition?: {
28+
left?: string | number;
29+
right?: string | number;
30+
top?: string | number;
31+
bottom?: string | number;
32+
};
33+
};
34+
35+
const Panel_: React.FC<PanelProps> = ({
36+
isOpen,
37+
id = 'panel',
38+
children,
39+
areAllExpanded,
40+
toggleExpandAll,
41+
handleClose,
42+
intitialPosition,
43+
sx
44+
}) => {
45+
const theme = useTheme();
46+
if (!isOpen) return null;
47+
return (
48+
<Draggable handle=".drag-handle">
49+
<PanelContainer theme={theme} intitialPosition={intitialPosition} sx={sx}>
50+
<Resizable
51+
defaultSize={{ width: '18rem', height: 'auto' }}
52+
onResize={() => {
53+
window.dispatchEvent(new Event('panel-resize'));
54+
}}
55+
enable={{
56+
top: true,
57+
right: true,
58+
bottom: true,
59+
left: true,
60+
topRight: true,
61+
bottomRight: true,
62+
bottomLeft: true,
63+
topLeft: true
64+
}}
65+
>
66+
<ResizableContent>
67+
<ErrorBoundary>
68+
<div className="drag-handle">
69+
<DrawerHeader>
70+
<Box display="flex" justifyContent="flex-end" padding="8px">
71+
{toggleExpandAll && (
72+
<Tooltip title={areAllExpanded ? 'Collapse All' : 'Expand All'}>
73+
<IconButton onClick={toggleExpandAll}>
74+
{areAllExpanded ? <CollapseAllIcon /> : <ExpandAllIcon />}
75+
</IconButton>
76+
</Tooltip>
77+
)}
78+
</Box>
79+
<DragHandle>
80+
<PanelDragHandleIcon />
81+
</DragHandle>
82+
<HeaderContainer>
83+
<HeaderActionsContainer
84+
id={`${id}-panel-header-actions-container`}
85+
></HeaderActionsContainer>
86+
<IconButton onClick={handleClose}>
87+
<CloseIcon />
88+
</IconButton>
89+
</HeaderContainer>
90+
</DrawerHeader>
91+
</div>
92+
<PanelBody className="panel-body">{children}</PanelBody>
93+
</ErrorBoundary>
94+
</ResizableContent>
95+
</Resizable>
96+
</PanelContainer>
97+
</Draggable>
98+
);
99+
};
100+
101+
export const Panel: React.FC<PanelProps> = ({ ...props }) => {
102+
return <Panel_ {...props} />;
103+
};

src/custom/Panel/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { Panel } from './Panel';
2+
3+
export { Panel };

src/custom/Panel/style.tsx

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { ListItemProps } from '@mui/material';
2+
import { Box, ListItem } from '../../base';
3+
import { styled } from '../../theme';
4+
import { PanelProps } from './Panel';
5+
6+
export const ListHeader = styled(ListItem)(({ theme }) => ({
7+
padding: theme.spacing(0.5, 0.5),
8+
marginBlock: theme.spacing(1),
9+
'& .MuiListItemText-primary': {
10+
fontSize: '1rem',
11+
textTransform: 'capitalize',
12+
fontWeight: 700
13+
},
14+
cursor: 'pointer',
15+
'&:hover': {
16+
backgroundColor: theme.palette.action.hover
17+
},
18+
'& .MuiSvgIcon-root': {
19+
opacity: 0,
20+
transition: 'opacity 0.2s'
21+
},
22+
'&:hover .MuiSvgIcon-root': {
23+
opacity: 1
24+
}
25+
}));
26+
27+
interface CustomListItemProps extends ListItemProps {
28+
isVisible: boolean;
29+
}
30+
31+
export const StyledListItem = styled(ListItem, {
32+
shouldForwardProp: (props) => props !== 'isVisible'
33+
})<CustomListItemProps>(({ theme, isVisible }) => ({
34+
padding: theme.spacing(0.05, 0.5),
35+
fontStyle: isVisible ? 'normal' : 'italic',
36+
overflow: 'hidden',
37+
textOverflow: 'ellipsis',
38+
whiteSpace: 'nowrap',
39+
'& .MuiSvgIcon-root': {
40+
height: 20,
41+
width: 20
42+
},
43+
'& .MuiListItemIcon-root': {
44+
minWidth: 0,
45+
opacity: isVisible ? 0.8 : 0.3
46+
},
47+
'& .MuiTypography-root': {
48+
fontSize: '0.9rem',
49+
opacity: isVisible ? 1 : 0.5
50+
}
51+
}));
52+
53+
export const DrawerHeader = styled('div')(({ theme }) => ({
54+
display: 'flex',
55+
alignItems: 'center',
56+
padding: theme.spacing(4, 2),
57+
alignContent: 'stretch',
58+
justifyContent: 'space-between',
59+
cursor: 'move',
60+
background:
61+
theme.palette.mode === 'light'
62+
? 'linear-gradient(90deg, #3B687B 0%, #507D90 100%)'
63+
: 'linear-gradient(90deg, #28353A 0%, #3D4F57 100%)',
64+
height: '3rem',
65+
flexShrink: 0
66+
}));
67+
68+
export const PanelBody = styled(Box)(({ theme }) => ({
69+
padding: theme.spacing(2),
70+
backgroundColor: theme.palette.background.surfaces,
71+
overflow: 'auto',
72+
flex: 1,
73+
minHeight: 0
74+
}));
75+
76+
export const ResizableContent = styled('div')({
77+
height: '100%',
78+
display: 'flex',
79+
flexDirection: 'column',
80+
minHeight: '3rem'
81+
});
82+
83+
export const PanelContainer = styled(Box)<{ intitialPosition: PanelProps['intitialPosition'] }>(
84+
({ theme, intitialPosition }) => ({
85+
borderRadius: '8px',
86+
overflow: 'hidden',
87+
flexShrink: 0,
88+
zIndex: 99999,
89+
position: 'absolute',
90+
backgroundColor: theme.palette.background.blur?.light,
91+
boxShadow: '0 4px 16px #05003812',
92+
maxHeight: '80%',
93+
display: 'flex',
94+
boxSizing: 'border-box',
95+
...intitialPosition
96+
})
97+
);
98+
99+
export const DragHandle = styled('div')({
100+
position: 'absolute',
101+
top: '-3rem',
102+
left: '50%'
103+
});
104+
105+
export const HeaderActionsContainer = styled('div')({
106+
display: 'flex',
107+
gap: '1rem',
108+
justifyContent: 'flex-end',
109+
alignItems: 'center'
110+
});
111+
112+
export const HeaderContainer = styled('div')({
113+
display: 'flex',
114+
justifyContent: 'end',
115+
alignItems: 'center',
116+
flex: '1'
117+
});

src/custom/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export { InputSearchField } from './InputSearchField';
5757
export { LearningContent } from './LearningContent';
5858
export { NavigationNavbar } from './NavigationNavbar';
5959
export { Note } from './Note';
60+
export { Panel } from './Panel';
6061
export { PerformersSection, PerformersSectionButton } from './PerformersSection';
6162
export { SetupPreReq } from './SetupPrerequisite';
6263
export { StyledChapter } from './StyledChapter';
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { FC } from 'react';
2+
import { IconProps } from '../types';
3+
4+
export const PanelDragHandleIcon: FC<IconProps> = ({
5+
height = 24,
6+
width = 24,
7+
fill = '#E8EFF3',
8+
...props
9+
}) => {
10+
return (
11+
<svg
12+
width={width}
13+
height={height}
14+
viewBox="0 0 24 24"
15+
fill="none"
16+
xmlns="http://www.w3.org/2000/svg"
17+
{...props}
18+
>
19+
<g clipPath="url(#clip0_34897_172744)">
20+
<path
21+
d="M6 10C4.9 10 4 10.9 4 12C4 13.1 4.9 14 6 14C7.1 14 8 13.1 8 12C8 10.9 7.1 10 6 10ZM18 10C16.9 10 16 10.9 16 12C16 13.1 16.9 14 18 14C19.1 14 20 13.1 20 12C20 10.9 19.1 10 18 10ZM12 10C10.9 10 10 10.9 10 12C10 13.1 10.9 14 12 14C13.1 14 14 13.1 14 12C14 10.9 13.1 10 12 10Z"
22+
fill={fill}
23+
/>
24+
</g>
25+
<defs>
26+
<clipPath id="clip0_34897_172744">
27+
<rect width="24" height="24" fill="white" />
28+
</clipPath>
29+
</defs>
30+
</svg>
31+
);
32+
};
33+
34+
export default PanelDragHandleIcon;

src/icons/PanelDragHandle/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as PanelDragHandleIcon } from './PanelDragHandleIcon';

0 commit comments

Comments
 (0)