Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save brandonbryant12/1b3e2b7b5069be97d67ee47d11932fd2 to your computer and use it in GitHub Desktop.

Select an option

Save brandonbryant12/1b3e2b7b5069be97d67ee47d11932fd2 to your computer and use it in GitHub Desktop.
import React, { useState } from ‘react’;
import {
Box,
Grid,
IconButton,
Typography,
styled,
Stack,
} from ‘@mui/material’;
import ExpandMoreIcon from ‘@mui/icons-material/ExpandMore’;
import ExpandLessIcon from ‘@mui/icons-material/ExpandLess’;
import CustomInfoCard, { CustomInfoCardProps } from ‘./CustomInfoCard’;
const COLLAPSED_TITLE_WIDTH = 3; // 25% (3/12 grid units)
const COLLAPSED_CONTENT_WIDTH = 9; // 75% (9/12 grid units)
const PeruseWrapper = styled(Box)(({ theme }) => ({
position: ‘relative’,
transition: ‘all 0.3s ease-in-out’,
‘& .expand-button’: {
position: ‘absolute’,
top: theme.spacing(2),
left: theme.spacing(2),
zIndex: 1,
},
‘&.skim-view’: {
cursor: ‘pointer’,
‘&:hover’: {
backgroundColor: theme.palette.action.hover,
},
‘& .MuiCardHeader-content’: {
paddingLeft: theme.spacing(7),
},
},
}));
interface PeruseCustomInfoCardProps extends CustomInfoCardProps {
skimContent: React.ReactNode;
}
export const PeruseCustomInfoCard: React.FC<PeruseCustomInfoCardProps> = ({
skimContent,
title,
children,
dataSources = [],
footerButtonsComponent,
menuActions = [],
…restProps
}) => {
const [expanded, setExpanded] = useState(false);
if (!expanded) {
return (
<PeruseWrapper
className=“skim-view”
onClick={() => setExpanded(true)}
role=“button”
tabIndex={0}
onKeyDown={(e) => {
if (e.key === ‘Enter’ || e.key === ’ ’) {
e.preventDefault();
setExpanded(true);
}
}}
>
<IconButton
className=“expand-button”
size=“small”
aria-label=“Expand card”
aria-expanded={false}
onClick={(e) => {
e.stopPropagation();
setExpanded(true);
}}
>
<ExpandMoreIcon fontSize="inherit" />
</IconButton>
```
<CustomInfoCard
title={
<Grid container alignItems="center" wrap="nowrap">
<Grid item xs={COLLAPSED_TITLE_WIDTH} zeroMinWidth>
{typeof title === 'string' ? (
<Typography variant="subtitle1" noWrap>{title}</Typography>
) : (
title
)}
</Grid>
<Grid item xs={COLLAPSED_CONTENT_WIDTH}>
<Box sx={{ width: '100%' }}>{skimContent}</Box>
</Grid>
</Grid>
}
{...restProps}
/>
</PeruseWrapper>
);
```
}
return (
<PeruseWrapper>
<IconButton
className=“expand-button”
size=“small”
aria-label=“Collapse card”
aria-expanded={true}
onClick={() => setExpanded(false)}
>
<ExpandLessIcon fontSize="inherit" />
</IconButton>
```
<CustomInfoCard
title={title}
dataSources={dataSources}
footerButtonsComponent={footerButtonsComponent}
menuActions={menuActions}
{...restProps}
>
{children}
</CustomInfoCard>
</PeruseWrapper>
```
);
};
export interface SkimMetricProps {
label: string;
value: React.ReactNode;
color?: string;
}
export const SkimMetric: React.FC<SkimMetricProps> = ({
label,
value,
color = ‘grey.800’,
}) => (
<Stack
spacing={0.5}
sx={{
px: 1.5,
py: 1,
bgcolor: color,
borderRadius: 1,
minWidth: 90,
}}
```
<Typography variant="caption" color="text.secondary">
{label}
</Typography>
<Typography variant="body2" fontWeight={600}>
{value}
</Typography>
```
</Stack>
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment