code: tsx,nextjs,frontends (2 files)

This commit is contained in:
Richard Ward
2025-12-30 18:42:04 +00:00
parent 0a4d45b58d
commit 5d3c79d40f
2 changed files with 51 additions and 52 deletions
@@ -1,10 +1,12 @@
'use client'
import { Box, Collapse, List, Typography } from '@mui/material'
import { forwardRef, ReactNode, useState } from 'react'
import { Box, Collapse, List, Typography } from '@/fakemui'
import { ExpandLess, ExpandMore } from '@/fakemui/icons'
import styles from './SidebarGroup.module.scss'
// SidebarGroup
interface SidebarGroupProps {
children: ReactNode
@@ -15,27 +17,19 @@ interface SidebarGroupProps {
}
const SidebarGroup = forwardRef<HTMLDivElement, SidebarGroupProps>(
({ children, label, collapsible, defaultOpen = true, ...props }, ref) => {
({ children, label, collapsible, defaultOpen = true, className = '', ...props }, ref) => {
const [open, setOpen] = useState(defaultOpen)
return (
<Box ref={ref} sx={{ mb: 1 }} {...props}>
<Box ref={ref} className={`${styles.sidebarGroup} ${className}`} {...props}>
{label && (
<Box
onClick={collapsible ? () => setOpen(!open) : undefined}
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
px: 2,
py: 1,
cursor: collapsible ? 'pointer' : 'default',
}}
className={`${styles.sidebarGroupHeader} ${collapsible ? styles.collapsible : ''}`}
>
<Typography
variant="overline"
color="text.secondary"
sx={{ fontSize: '0.7rem', letterSpacing: 1 }}
className={styles.sidebarGroupLabel}
>
{label}
</Typography>
@@ -45,12 +39,12 @@ const SidebarGroup = forwardRef<HTMLDivElement, SidebarGroupProps>(
)}
{collapsible ? (
<Collapse in={open}>
<List dense disablePadding>
<List dense className={styles.sidebarGroupList}>
{children}
</List>
</Collapse>
) : (
<List dense disablePadding>
<List dense className={styles.sidebarGroupList}>
{children}
</List>
)}
@@ -62,13 +56,12 @@ SidebarGroup.displayName = 'SidebarGroup'
// SidebarGroupLabel
const SidebarGroupLabel = forwardRef<HTMLDivElement, { children: ReactNode; className?: string }>(
({ children, ...props }, ref) => {
({ children, className = '', ...props }, ref) => {
return (
<Typography
ref={ref}
variant="overline"
color="text.secondary"
sx={{ px: 2, py: 1, fontSize: '0.7rem', letterSpacing: 1 }}
className={`${styles.sidebarGroupLabelStandalone} ${className}`}
{...props}
>
{children}
@@ -80,10 +73,10 @@ SidebarGroupLabel.displayName = 'SidebarGroupLabel'
// SidebarGroupContent
const SidebarGroupContent = forwardRef<HTMLDivElement, { children: ReactNode; className?: string }>(
({ children, ...props }, ref) => {
({ children, className = '', ...props }, ref) => {
return (
<Box ref={ref} {...props}>
<List dense disablePadding>
<Box ref={ref} className={className} {...props}>
<List dense className={styles.sidebarGroupList}>
{children}
</List>
</Box>
@@ -1,14 +1,17 @@
'use client'
import { Box, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'
import { forwardRef, ReactNode } from 'react'
import { Box, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@/fakemui'
import styles from './SidebarMenu.module.scss'
// SidebarMenu (alias for List)
const SidebarMenu = forwardRef<HTMLDivElement, { children: ReactNode; className?: string }>(
({ children, ...props }, ref) => {
({ children, className = '', ...props }, ref) => {
return (
<Box ref={ref} {...props}>
<List dense disablePadding>
<Box ref={ref} className={className} {...props}>
<List dense className={styles.sidebarMenuList}>
{children}
</List>
</Box>
@@ -30,36 +33,39 @@ interface SidebarMenuItemProps {
}
const SidebarMenuItem = forwardRef<HTMLDivElement, SidebarMenuItemProps>(
({ children, icon, label, href, active, disabled, onClick, ...props }, ref) => {
({ children, icon, label, href, active, disabled, onClick, className = '', ...props }, ref) => {
const content = children || label
const activeClass = active ? styles.active : ''
const buttonContent = (
<>
{icon && <ListItemIcon className={styles.sidebarMenuIcon}>{icon}</ListItemIcon>}
<ListItemText primary={content} className={styles.sidebarMenuText} />
</>
)
return (
<ListItem disablePadding>
<Box ref={ref} sx={{ width: '100%' }} {...props}>
<ListItemButton
selected={active}
disabled={disabled}
onClick={onClick}
href={href}
component={href ? 'a' : 'button'}
sx={{
mx: 1,
borderRadius: 1,
'&.Mui-selected': {
bgcolor: 'primary.main',
color: 'primary.contrastText',
'& .MuiListItemIcon-root': {
color: 'primary.contrastText',
},
'&:hover': {
bgcolor: 'primary.dark',
},
},
}}
>
{icon && <ListItemIcon sx={{ minWidth: 36 }}>{icon}</ListItemIcon>}
<ListItemText primary={content} primaryTypographyProps={{ fontSize: '0.875rem' }} />
</ListItemButton>
<ListItem className={styles.sidebarMenuListItem}>
<Box ref={ref} className={`${styles.sidebarMenuItemWrapper} ${className}`} {...props}>
{href ? (
<a
href={href}
onClick={onClick}
className={`${styles.sidebarMenuButton} ${activeClass} ${disabled ? styles.disabled : ''}`}
aria-disabled={disabled}
>
{buttonContent}
</a>
) : (
<ListItemButton
selected={active}
disabled={disabled}
onClick={onClick}
className={`${styles.sidebarMenuButton} ${activeClass}`}
>
{buttonContent}
</ListItemButton>
)}
</Box>
</ListItem>
)