Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added Panel component to sistent #863

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@
"dependencies": {
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"re-resizable": "^6.10.3",
"react-draggable": "^4.4.6",
"react-share": "^5.1.0"
}
}
126 changes: 126 additions & 0 deletions src/custom/Panel/Panel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { Resizable } from 're-resizable';
import React from 'react';
import Draggable from 'react-draggable';
import { Box, BoxProps, IconButton, Tooltip } from '../../base';
import { CloseIcon, CollapseAllIcon, ExpandAllIcon } from '../../icons';
import { PanelDragHandleIcon } from '../../icons/PanelDragHandle';
import { useTheme } from '../../theme';
import { ErrorBoundary } from '../ErrorBoundary';
import { DrawerHeader, PanelBody, ResizableContent } from './style';

type PanelProps = {
isOpen: boolean;
children: React.ReactNode;
areAllExpanded?: boolean;
toggleExpandAll?: () => void;
handleClose: () => void;
sx?: BoxProps['sx'];
id?: string;
intitialPosition?: {
left?: string | number;
right?: string | number;
top?: string | number;
bottom?: string | number;
};
};

const Panel_: React.FC<PanelProps> = ({
isOpen,
id = 'panel',
children,
areAllExpanded,
toggleExpandAll,
handleClose,
intitialPosition,
sx
}) => {
const theme = useTheme();
if (!isOpen) return null;
return (
<Draggable handle=".drag-handle">
<Box
sx={{
borderRadius: '8px',
overflow: 'hidden',
flexShrink: 0,
zIndex: 99999,
position: 'absolute',
backgroundColor: theme.palette.background.blur?.light,
boxShadow: '0 4px 16px #05003812',
maxHeight: '80%',
display: 'flex',
boxSizing: 'border-box',
...(intitialPosition || {
top: '6rem',
right: '2rem'
}),
...(sx || {})
}}
>
<Resizable
defaultSize={{ width: '18rem', height: 'auto' }}
onResize={() => {
window.dispatchEvent(new Event('panel-resize'));
}}
enable={{
top: true,
right: true,
bottom: true,
left: true,
topRight: true,
bottomRight: true,
bottomLeft: true,
topLeft: true
}}
>
<ResizableContent>
<ErrorBoundary>
<div className="drag-handle">
<DrawerHeader>
<Box display="flex" justifyContent="flex-end" padding="8px">
{toggleExpandAll && (
<Tooltip title={areAllExpanded ? 'Collapse All' : 'Expand All'}>
<IconButton onClick={toggleExpandAll}>
{areAllExpanded ? <CollapseAllIcon /> : <ExpandAllIcon />}
</IconButton>
</Tooltip>
)}
</Box>
<PanelDragHandleIcon
style={{ marginTop: '-3rem', position: 'absolute', left: '50%' }}
/>
<div
style={{
display: 'flex',
justifyContent: 'end',
alignItems: 'center',
flex: 1
}}
>
<div
id={`${id}-panel-header-actions-container`}
style={{
display: 'flex',
gap: '1rem',
justifyContent: 'flex-end',
alignItems: 'center'
}}
></div>
<IconButton onClick={handleClose}>
<CloseIcon />
</IconButton>
</div>
</DrawerHeader>
</div>
<PanelBody className="panel-body">{children}</PanelBody>
</ErrorBoundary>
</ResizableContent>
</Resizable>
</Box>
</Draggable>
);
};

export const Panel: React.FC<PanelProps> = ({ ...props }) => {
return <Panel_ {...props} />;
};
3 changes: 3 additions & 0 deletions src/custom/Panel/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Panel } from './Panel';

export { Panel };
80 changes: 80 additions & 0 deletions src/custom/Panel/style.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { ListItemProps } from '@mui/material';
import { Box, ListItem } from '../../base';
import { styled } from '../../theme';

export const ListHeader = styled(ListItem)(({ theme }) => ({
padding: theme.spacing(0.5, 0.5),
marginBlock: theme.spacing(1),
'& .MuiListItemText-primary': {
fontSize: '1rem',
textTransform: 'capitalize',
fontWeight: 700
},
cursor: 'pointer',
'&:hover': {
backgroundColor: theme.palette.action.hover
},
'& .MuiSvgIcon-root': {
opacity: 0,
transition: 'opacity 0.2s'
},
'&:hover .MuiSvgIcon-root': {
opacity: 1
}
}));

interface CustomListItemProps extends ListItemProps {
isVisible: boolean;
}

export const StyledListItem = styled(ListItem, {
shouldForwardProp: (props) => props !== 'isVisible'
})<CustomListItemProps>(({ theme, isVisible }) => ({
padding: theme.spacing(0.05, 0.5),
fontStyle: isVisible ? 'normal' : 'italic',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
'& .MuiSvgIcon-root': {
height: 20,
width: 20
},
'& .MuiListItemIcon-root': {
minWidth: 0,
opacity: isVisible ? 0.8 : 0.3
},
'& .MuiTypography-root': {
fontSize: '0.9rem',
opacity: isVisible ? 1 : 0.5
}
}));

export const DrawerHeader = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
padding: theme.spacing(4, 2),
alignContent: 'stretch',
justifyContent: 'space-between',
cursor: 'move',
background:
theme.palette.mode === 'light'
? 'linear-gradient(90deg, #3B687B 0%, #507D90 100%)'
: 'linear-gradient(90deg, #28353A 0%, #3D4F57 100%)',
height: '3rem',
flexShrink: 0
}));

export const PanelBody = styled(Box)(({ theme }) => ({
padding: theme.spacing(2),
backgroundColor: theme.palette.background.surfaces,
overflow: 'auto',
flex: 1,
minHeight: 0
}));

export const ResizableContent = styled('div')({
height: '100%',
display: 'flex',
flexDirection: 'column',
minHeight: '3rem'
});
1 change: 1 addition & 0 deletions src/custom/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export { InputSearchField } from './InputSearchField';
export { LearningContent } from './LearningContent';
export { NavigationNavbar } from './NavigationNavbar';
export { Note } from './Note';
export { Panel } from './Panel';
export { PerformersSection, PerformersSectionButton } from './PerformersSection';
export { SetupPreReq } from './SetupPrerequisite';
export { StyledChapter } from './StyledChapter';
Expand Down
34 changes: 34 additions & 0 deletions src/icons/PanelDragHandle/PanelDragHandleIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { FC } from 'react';
import { IconProps } from '../types';

export const PanelDragHandleIcon: FC<IconProps> = ({
height = 24,
width = 24,
fill = '#E8EFF3',
...props
}) => {
return (
<svg
width={width}
height={height}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g clipPath="url(#clip0_34897_172744)">
<path
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"
fill={fill}
/>
</g>
<defs>
<clipPath id="clip0_34897_172744">
<rect width="24" height="24" fill="white" />
</clipPath>
</defs>
</svg>
);
};

export default PanelDragHandleIcon;
1 change: 1 addition & 0 deletions src/icons/PanelDragHandle/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as PanelDragHandleIcon } from './PanelDragHandleIcon';
Loading