coder/site/src/components/Dashboard/Navbar/UserDropdown/BorderedMenu/BorderedMenuRow.tsx

131 lines
3.2 KiB
TypeScript

import ListItem from "@mui/material/ListItem";
import { makeStyles } from "@mui/styles";
import CheckIcon from "@mui/icons-material/Check";
import { FC } from "react";
import { NavLink } from "react-router-dom";
import { ellipsizeText } from "../../../../../utils/ellipsizeText";
import { Typography } from "../../../../Typography/Typography";
type BorderedMenuRowVariant = "narrow" | "wide";
interface BorderedMenuRowProps {
/** `true` indicates this row is currently selected */
active?: boolean;
/** Optional description that appears beneath the title */
description?: string;
/** URL path */
path: string;
/** Required title of this row */
title: string;
/** Defaults to `"wide"` */
variant?: BorderedMenuRowVariant;
/** Callback fired when this row is clicked */
onClick?: () => void;
}
export const BorderedMenuRow: FC<
React.PropsWithChildren<BorderedMenuRowProps>
> = ({ active, description, path, title, variant, onClick }) => {
const styles = useStyles();
return (
<NavLink className={styles.link} to={path}>
<ListItem
classes={{ gutters: styles.rootGutters }}
className={styles.root}
data-status={active ? "active" : "inactive"}
onClick={onClick}
>
<div className={styles.content} data-variant={variant}>
<div className={styles.contentTop}>
<Typography className={styles.title}>{title}</Typography>
{active && <CheckIcon className={styles.checkMark} />}
</div>
{description && (
<Typography
className={styles.description}
color="textSecondary"
variant="caption"
>
{ellipsizeText(description)}
</Typography>
)}
</div>
</ListItem>
</NavLink>
);
};
const iconSize = 20;
const useStyles = makeStyles((theme) => ({
root: {
cursor: "pointer",
padding: `0 ${theme.spacing(1)}`,
"&:hover": {
backgroundColor: "unset",
"& $content": {
backgroundColor: theme.palette.background.default,
},
},
"&[data-status='active']": {
color: theme.palette.secondary.dark,
"& .BorderedMenuRow-description": {
color: theme.palette.text.primary,
},
"& .BorderedMenuRow-icon": {
color: theme.palette.secondary.dark,
},
},
},
rootGutters: {
padding: `0 ${theme.spacing(1.5)}`,
},
content: {
borderRadius: theme.shape.borderRadius,
display: "flex",
flexDirection: "column",
padding: theme.spacing(2),
width: 320,
"&[data-variant='narrow']": {
width: 268,
},
},
contentTop: {
alignItems: "center",
display: "flex",
},
icon: {
color: theme.palette.text.secondary,
height: iconSize,
width: iconSize,
"& path": {
fill: theme.palette.text.secondary,
},
},
link: {
textDecoration: "none",
color: "inherit",
},
title: {
fontSize: 16,
fontWeight: 500,
lineHeight: 1.5,
marginLeft: theme.spacing(2),
},
checkMark: {
height: iconSize,
marginLeft: "auto",
width: iconSize,
},
description: {
marginLeft: theme.spacing(4.5),
marginTop: theme.spacing(0.5),
},
}));