Skip to content

Instantly share code, notes, and snippets.

@brandonbryant12
Last active June 12, 2025 00:50
Show Gist options
  • Select an option

  • Save brandonbryant12/2386173e88a2daa98f0ad0ff0972191b to your computer and use it in GitHub Desktop.

Select an option

Save brandonbryant12/2386173e88a2daa98f0ad0ff0972191b to your computer and use it in GitHub Desktop.
import React, { useState } from 'react';
import {
Box,
IconButton,
Typography,
styled,
} from '@mui/material';
import ChevronRightIcon from '@mui/icons-material/ChevronRight'; // ► collapsed
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; // ▼ expanded
import { CustomInfoCard, CustomInfoCardProps } from './CustomInfoCard';
/* ---------- styled helpers ---------- */
const TitleRow = styled(Box)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
width: '100%',
// let long titles truncate, but never push the skim boxes off-screen
minWidth: 0,
'& .title-text': {
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
},
'& .skim-wrapper': {
marginLeft: theme.spacing(2),
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1),
},
}));
/* ---------- props ---------- */
export interface PeruseCustomInfoCardProps extends CustomInfoCardProps {
/** Boxes (or any node) that appear after the title *only* when collapsed. */
skimContent: React.ReactNode;
}
/* ---------- component ---------- */
export const PeruseCustomInfoCard: React.FC<PeruseCustomInfoCardProps> = ({
skimContent,
title,
children,
dataSources,
footerButtonsComponent,
menuActions,
...restProps
}) => {
const [expanded, setExpanded] = useState(false);
const handleToggle = () => setExpanded((prev) => !prev);
/* -------------------- COLLAPSED -------------------- */
if (!expanded) {
return (
<CustomInfoCard
{...restProps}
title={
<TitleRow>
<IconButton
size="small"
onClick={handleToggle}
aria-label="Expand"
sx={{ mr: 1 }}
>
<ChevronRightIcon fontSize="small" />
</IconButton>
<Typography
component="span"
variant="subtitle1"
className="title-text"
>
{title}
</Typography>
<Box className="skim-wrapper">{skimContent}</Box>
</TitleRow>
}
/>
);
}
/* -------------------- EXPANDED -------------------- */
return (
<CustomInfoCard
{...restProps}
title={
<TitleRow>
<IconButton
size="small"
onClick={handleToggle}
aria-label="Collapse"
sx={{ mr: 1 }}
>
<ExpandMoreIcon fontSize="small" />
</IconButton>
<Typography component="span" variant="subtitle1">
{title}
</Typography>
</TitleRow>
}
dataSources={dataSources}
footerButtonsComponent={footerButtonsComponent}
menuActions={menuActions}
>
{children}
</CustomInfoCard>
);
};
// SkimMetricBox.tsx
import React from 'react';
import { Stack, Typography, Box, SxProps, Theme } from '@mui/material';
export interface SkimMetricBoxProps {
label: string;
value: React.ReactNode;
sx?: SxProps<Theme>;
}
/**
* A tiny dark pill that shows a label + value.
* Use inside a <Stack direction="row"> to compose skim content.
*/
export const SkimMetricBox: React.FC<SkimMetricBoxProps> = ({
label,
value,
sx = {},
}) => (
<Box
sx={{
px: 2,
py: 0.75,
bgcolor: 'grey.900',
borderRadius: 1,
minWidth: 80,
...sx,
}}
>
<Stack spacing={0.25}>
<Typography variant="caption" color="text.secondary">
{label}
</Typography>
<Typography variant="subtitle2">{value}</Typography>
</Stack>
</Box>
);
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 PeruseWrapper = styled(Box)(({ theme }) => ({
position: 'relative',
'& .expand-button': {
position: 'absolute',
top: theme.spacing(2),
left: theme.spacing(2),
zIndex: 1,
},
'&.skim-view': {
'& .MuiCardHeader-content': {
paddingLeft: theme.spacing(7),
},
},
}));
interface PeruseCustomInfoCardProps
extends Omit<CustomInfoCardProps, 'title'> {
skimContent?: React.ReactNode | React.ReactNode[];
title: 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">
<IconButton
className="expand-button"
size="small"
aria-label="Expand"
onClick={() => setExpanded(true)}
>
<ExpandMoreIcon fontSize="inherit" />
</IconButton>
<CustomInfoCard
title={
<Grid container alignItems="center" wrap="nowrap">
<Grid item xs={3} zeroMinWidth>
{typeof title === 'string' ? (
<Typography variant="subtitle1" noWrap>{title}</Typography>
) : (
title
)}
</Grid>
<Grid item xs={9}>
<Box sx={{ width: '100%' }}>{skimContent}</Box>
</Grid>
</Grid>
}
{...restProps}
/>
</PeruseWrapper>
);
}
return (
<PeruseWrapper>
<IconButton
className="expand-button"
size="small"
aria-label="Collapse"
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>
);
@brandonbryant12
Copy link
Author

// SkimMetricBox.tsx
import React from 'react';
import { Stack, Typography, Box, SxProps, Theme } from '@mui/material';

export interface SkimMetricBoxProps {
label: string;
value: React.ReactNode;
sx?: SxProps;
}

/**

  • A tiny dark pill that shows a label + value.
  • Use inside a to compose skim content.
    */
    export const SkimMetricBox: React.FC = ({
    label,
    value,
    sx = {},
    }) => (
    <Box
    sx={{
    px: 2,
    py: 0.75,
    bgcolor: 'grey.900',
    borderRadius: 1,
    minWidth: 80,
    ...sx,
    }}
<Stack spacing={0.25}>
  <Typography variant="caption" color="text.secondary">
    {label}
  </Typography>
  <Typography variant="subtitle2">{value}</Typography>
</Stack>
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment