diff --git a/.changeset/purple-queens-breathe.md b/.changeset/purple-queens-breathe.md new file mode 100644 index 0000000000..04e030dc29 --- /dev/null +++ b/.changeset/purple-queens-breathe.md @@ -0,0 +1,5 @@ +--- +"@comet/admin": major +--- + +Delete "secondaryText" from "MenuItemClassKey" diff --git a/packages/admin/admin/src/mui/menu/Item.tsx b/packages/admin/admin/src/mui/menu/Item.tsx index f23cf11ecb..7f7f955ffd 100644 --- a/packages/admin/admin/src/mui/menu/Item.tsx +++ b/packages/admin/admin/src/mui/menu/Item.tsx @@ -1,144 +1,175 @@ -import { ComponentsOverrides, ListItem, ListItemIcon, ListItemProps, ListItemText, Theme } from "@mui/material"; -import { createStyles, WithStyles, withStyles } from "@mui/styles"; +import { ListItemButton, ListItemButtonProps, ListItemIcon, ListItemText } from "@mui/material"; +import { ComponentsOverrides, css, styled, Theme, useThemeProps } from "@mui/material/styles"; +import { ThemedComponentBaseProps } from "helpers/ThemedComponentBaseProps"; import * as React from "react"; import { MenuLevel } from "./CollapsibleItem"; import { MenuContext } from "./Context"; -export type MenuItemClassKey = "root" | "level1" | "level2" | "hasIcon" | "hasSecondaryText" | "hasSecondaryAction"; +export type MenuItemClassKey = "root" | "level1" | "level2" | "hasIcon" | "hasSecondaryAction"; + +type OwnerState = Pick; const colors = { textLevel1: "#242424", textLevel2: "#17181A", }; -const styles = (theme: Theme) => - createStyles({ - root: { - flexShrink: 0, - "&:after": { - content: "''", - position: "absolute", - top: 0, - right: 0, - bottom: 0, - width: 2, - }, - "& [class*='MuiListItemIcon-root']": { - color: colors.textLevel1, - minWidth: 28, - }, - "& [class*='MuiListItemText-inset']": { - paddingLeft: 28, - }, - "& [class*='MuiSvgIcon-root']": { - fontSize: 16, - }, - }, - level1: { - borderBottom: `1px solid ${theme.palette.grey[50]}`, - boxSizing: "border-box", - color: colors.textLevel1, - paddingLeft: 20, - paddingRight: 20, - paddingTop: 16, - paddingBottom: 16, - "&[class*='Mui-selected']": { - backgroundColor: theme.palette.grey[50], - color: theme.palette.primary.main, - "&:after": { - backgroundColor: theme.palette.primary.main, - }, - "& [class*='MuiListItemIcon-root']": { - color: theme.palette.primary.main, - }, - }, - "& [class*='MuiListItemText-primary']": { - fontWeight: theme.typography.fontWeightMedium, - fontSize: 16, - lineHeight: "20px", - }, - }, - level2: { - color: colors.textLevel2, - paddingLeft: 20, - paddingRight: 20, - paddingTop: 10, - paddingBottom: 10, - "&:last-child": { - borderBottom: `1px solid ${theme.palette.grey[50]}`, - boxSizing: "border-box", - }, - "&[class*='Mui-selected']": { - backgroundColor: theme.palette.primary.main, - color: "#fff", - "&:after": { - backgroundColor: theme.palette.primary.dark, - }, - "&:hover": { - backgroundColor: theme.palette.primary.dark, - }, - "& [class*='MuiListItemText-primary']": { - fontWeight: theme.typography.fontWeightBold, - }, - }, - "& [class*='MuiListItemText-root']": { - margin: 0, - }, - "& [class*='MuiListItemText-primary']": { - fontWeight: theme.typography.fontWeightRegular, - fontSize: 14, - lineHeight: "20px", - }, - }, - hasIcon: {}, - hasSecondaryText: {}, - hasSecondaryAction: { - paddingRight: 18, - }, - }); +const Root = styled(ListItemButton, { + name: "CometAdminMenuItem", + slot: "root", + overridesResolver({ ownerState }: { ownerState: OwnerState }, styles) { + return [ + styles.root, + ownerState.level === 1 && styles.level1, + ownerState.level === 2 && styles.level2, + ownerState.icon && styles.hasIcon, + ownerState.secondaryAction && styles.hasSecondaryAction, + ]; + }, +})<{ ownerState: OwnerState }>( + ({ theme, ownerState }) => css` + flex-shrink: 0; + flex-grow: 0; + + &:after { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 2px; + } + + .MuiListItemIcon-root { + color: ${colors.textLevel1}; + min-width: 28px; + } + + .MuiListItemText-inset { + padding-left: 28px; + } + + .MuiSvgIcon-root { + font-size: 16px; + } + + ${ownerState.level === 1 && + css` + border-bottom: 1px solid ${theme.palette.grey[50]}; + box-sizing: border-box; + color: ${colors.textLevel1}; + padding-left: 20px; + padding-right: 20px; + padding-top: 16px; + padding-bottom: 16px; + + &.Mui-selected { + background-color: ${theme.palette.grey[50]}; + color: ${theme.palette.primary.main}; + + &:after { + background-color: ${theme.palette.primary.main}; + } + .MuiListItemIcon-root { + color: ${theme.palette.primary.main}; + } + } + + .MuiListItemText-primary { + font-weight: ${theme.typography.fontWeightMedium}; + font-size: 16px; + line-height: 20px; + } + `} + + ${ownerState.level === 2 && + css` + color: ${colors.textLevel2}; + padding-left: 20px; + padding-right: 20px; + padding-top: 10px; + padding-bottom: 10px; + + &:last-child { + border-bottom: 1px solid ${theme.palette.grey[50]}; + box-sizing: border-box; + } + + &.Mui-selected { + background-color: ${theme.palette.primary.main}; + color: #fff; + + &:after { + background-color: ${theme.palette.primary.dark}; + } + &:hover { + background-color: ${theme.palette.primary.dark}; + } + &.MuiListItemText-primary { + font-weight: ${theme.typography.fontWeightBold}; + } + } -export interface MenuItemProps extends MenuLevel { + .MuiListItemText-root { + margin: 0; + } + + .MuiListItemText-primary { + font-weight: ${theme.typography.fontWeightRegular}; + font-size: 14px; + line-height: 20px; + } + `}; + + ${ownerState.secondaryAction && + css` + padding-right: 18px; + `} + `, +); + +export interface MenuItemProps extends ThemedComponentBaseProps<{ root: typeof ListItemButton }>, MenuLevel, ListItemButtonProps { primary: React.ReactNode; secondary?: React.ReactNode; icon?: React.ReactElement; secondaryAction?: React.ReactNode; + secondaryText?: boolean; } -type MuiListItemProps = Pick> & { component?: React.ElementType }; - -const Item: React.FC & MenuItemProps & MuiListItemProps> = ({ - classes, - primary, - secondary, - icon, - level = 1, - secondaryAction, - ...otherProps -}) => { - const context = React.useContext(MenuContext); - if (!context) throw new Error("Could not find context for menu"); - if (level > 2) throw new Error("Maximum nesting level of 2 exceeded."); +export function MenuItem(inProps: MenuItemProps) { + const { + primary, + icon, + level = 1, + secondaryAction, + slotProps, + ...otherProps + } = useThemeProps({ + props: inProps, + name: "CometAdminMenuItem", + }); + + const ownerState: OwnerState = { + level, + icon, + secondaryAction, + }; const hasIcon = !!icon; - const listItemClasses = [classes.root]; - if (level === 1) listItemClasses.push(classes.level1); - if (level === 2) listItemClasses.push(classes.level2); - if (hasIcon) listItemClasses.push(classes.hasIcon); - if (secondary) listItemClasses.push(classes.hasSecondaryText); - if (secondaryAction) listItemClasses.push(classes.hasSecondaryAction); + const context = React.useContext(MenuContext); + if (!context) throw new Error("Could not find context for menu"); + if (level > 2) throw new Error("Maximum nesting level of 2 exceeded."); return ( - + {hasIcon && {icon}} - + {!!secondaryAction && secondaryAction} - + ); -}; - -export const MenuItem = withStyles(styles, { name: "CometAdminMenuItem" })(Item); +} declare module "@mui/material/styles" { interface ComponentNameToClassKey { diff --git a/packages/admin/admin/src/mui/menu/ItemAnchorLink.tsx b/packages/admin/admin/src/mui/menu/ItemAnchorLink.tsx index 7ef7a12bdc..e2273806c5 100644 --- a/packages/admin/admin/src/mui/menu/ItemAnchorLink.tsx +++ b/packages/admin/admin/src/mui/menu/ItemAnchorLink.tsx @@ -1,8 +1,10 @@ -import { ListItemProps } from "@mui/material/ListItem"; +import { ListItemButtonProps } from "@mui/material"; import * as React from "react"; import { MenuItem, MenuItemProps } from "./Item"; -export const MenuItemAnchorLink: React.FC> = (props) => ( +export const MenuItemAnchorLink: React.FC> = (props) => ( + // @ts-expect-error "component"-property is used as described in the documentation https://mui.com/material-ui/react-list/, but type is missing in ListItemButtonProps + );