Files
react-test/docs/data/joy/getting-started/templates/profile-dashboard/components/Sidebar.tsx
how2ice 005cf56baf
Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
Scorecards supply-chain security / Scorecards analysis (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
init project
2025-12-12 14:26:25 +09:00

325 lines
10 KiB
TypeScript

import * as React from 'react';
import GlobalStyles from '@mui/joy/GlobalStyles';
import Avatar from '@mui/joy/Avatar';
import Box from '@mui/joy/Box';
import Button from '@mui/joy/Button';
import Card from '@mui/joy/Card';
import Chip from '@mui/joy/Chip';
import Divider from '@mui/joy/Divider';
import IconButton from '@mui/joy/IconButton';
import Input from '@mui/joy/Input';
import LinearProgress from '@mui/joy/LinearProgress';
import List from '@mui/joy/List';
import ListItem from '@mui/joy/ListItem';
import ListItemButton, { listItemButtonClasses } from '@mui/joy/ListItemButton';
import ListItemContent from '@mui/joy/ListItemContent';
import Typography from '@mui/joy/Typography';
import Sheet from '@mui/joy/Sheet';
import Stack from '@mui/joy/Stack';
import SearchRoundedIcon from '@mui/icons-material/SearchRounded';
import HomeRoundedIcon from '@mui/icons-material/HomeRounded';
import DashboardRoundedIcon from '@mui/icons-material/DashboardRounded';
import ShoppingCartRoundedIcon from '@mui/icons-material/ShoppingCartRounded';
import AssignmentRoundedIcon from '@mui/icons-material/AssignmentRounded';
import QuestionAnswerRoundedIcon from '@mui/icons-material/QuestionAnswerRounded';
import GroupRoundedIcon from '@mui/icons-material/GroupRounded';
import SupportRoundedIcon from '@mui/icons-material/SupportRounded';
import SettingsRoundedIcon from '@mui/icons-material/SettingsRounded';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
import LogoutRoundedIcon from '@mui/icons-material/LogoutRounded';
import BrightnessAutoRoundedIcon from '@mui/icons-material/BrightnessAutoRounded';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import ColorSchemeToggle from './ColorSchemeToggle';
import { closeSidebar } from '../utils';
function Toggler({
defaultExpanded = false,
renderToggle,
children,
}: {
defaultExpanded?: boolean;
children: React.ReactNode;
renderToggle: (params: {
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
}) => React.ReactNode;
}) {
const [open, setOpen] = React.useState(defaultExpanded);
return (
<React.Fragment>
{renderToggle({ open, setOpen })}
<Box
sx={[
{
display: 'grid',
transition: '0.2s ease',
'& > *': {
overflow: 'hidden',
},
},
open ? { gridTemplateRows: '1fr' } : { gridTemplateRows: '0fr' },
]}
>
{children}
</Box>
</React.Fragment>
);
}
export default function Sidebar() {
return (
<Sheet
className="Sidebar"
sx={{
position: { xs: 'fixed', md: 'sticky' },
transform: {
xs: 'translateX(calc(100% * (var(--SideNavigation-slideIn, 0) - 1)))',
md: 'none',
},
transition: 'transform 0.4s, width 0.4s',
zIndex: 10000,
height: '100dvh',
width: 'var(--Sidebar-width)',
top: 0,
p: 2,
flexShrink: 0,
display: 'flex',
flexDirection: 'column',
gap: 2,
borderRight: '1px solid',
borderColor: 'divider',
}}
>
<GlobalStyles
styles={(theme) => ({
':root': {
'--Sidebar-width': '220px',
[theme.breakpoints.up('lg')]: {
'--Sidebar-width': '240px',
},
},
})}
/>
<Box
className="Sidebar-overlay"
sx={{
position: 'fixed',
zIndex: 9998,
top: 0,
left: 0,
width: '100vw',
height: '100vh',
opacity: 'var(--SideNavigation-slideIn)',
backgroundColor: 'var(--joy-palette-background-backdrop)',
transition: 'opacity 0.4s',
transform: {
xs: 'translateX(calc(100% * (var(--SideNavigation-slideIn, 0) - 1) + var(--SideNavigation-slideIn, 0) * var(--Sidebar-width, 0px)))',
lg: 'translateX(-100%)',
},
}}
onClick={() => closeSidebar()}
/>
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center' }}>
<IconButton variant="soft" color="primary" size="sm">
<BrightnessAutoRoundedIcon />
</IconButton>
<Typography level="title-lg">Acme Co.</Typography>
<ColorSchemeToggle sx={{ ml: 'auto' }} />
</Box>
<Input size="sm" startDecorator={<SearchRoundedIcon />} placeholder="Search" />
<Box
sx={{
minHeight: 0,
overflow: 'hidden auto',
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
[`& .${listItemButtonClasses.root}`]: {
gap: 1.5,
},
}}
>
<List
size="sm"
sx={{
gap: 1,
'--List-nestedInsetStart': '30px',
'--ListItem-radius': (theme) => theme.vars.radius.sm,
}}
>
<ListItem>
<ListItemButton>
<HomeRoundedIcon />
<ListItemContent>
<Typography level="title-sm">Home</Typography>
</ListItemContent>
</ListItemButton>
</ListItem>
<ListItem>
<ListItemButton>
<DashboardRoundedIcon />
<ListItemContent>
<Typography level="title-sm">Dashboard</Typography>
</ListItemContent>
</ListItemButton>
</ListItem>
<ListItem>
<ListItemButton
role="menuitem"
component="a"
href="/joy-ui/getting-started/templates/order-dashboard/"
>
<ShoppingCartRoundedIcon />
<ListItemContent>
<Typography level="title-sm">Orders</Typography>
</ListItemContent>
</ListItemButton>
</ListItem>
<ListItem nested>
<Toggler
renderToggle={({ open, setOpen }) => (
<ListItemButton onClick={() => setOpen(!open)}>
<AssignmentRoundedIcon />
<ListItemContent>
<Typography level="title-sm">Tasks</Typography>
</ListItemContent>
<KeyboardArrowDownIcon
sx={[
open ? { transform: 'rotate(180deg)' } : { transform: 'none' },
]}
/>
</ListItemButton>
)}
>
<List sx={{ gap: 0.5 }}>
<ListItem sx={{ mt: 0.5 }}>
<ListItemButton>All tasks</ListItemButton>
</ListItem>
<ListItem>
<ListItemButton>Backlog</ListItemButton>
</ListItem>
<ListItem>
<ListItemButton>In progress</ListItemButton>
</ListItem>
<ListItem>
<ListItemButton>Done</ListItemButton>
</ListItem>
</List>
</Toggler>
</ListItem>
<ListItem>
<ListItemButton
role="menuitem"
component="a"
href="/joy-ui/getting-started/templates/messages/"
>
<QuestionAnswerRoundedIcon />
<ListItemContent>
<Typography level="title-sm">Messages</Typography>
</ListItemContent>
<Chip size="sm" color="primary" variant="solid">
4
</Chip>
</ListItemButton>
</ListItem>
<ListItem nested>
<Toggler
defaultExpanded
renderToggle={({ open, setOpen }) => (
<ListItemButton onClick={() => setOpen(!open)}>
<GroupRoundedIcon />
<ListItemContent>
<Typography level="title-sm">Users</Typography>
</ListItemContent>
<KeyboardArrowDownIcon
sx={[
open ? { transform: 'rotate(180deg)' } : { transform: 'none' },
]}
/>
</ListItemButton>
)}
>
<List sx={{ gap: 0.5 }}>
<ListItem sx={{ mt: 0.5 }}>
<ListItemButton selected>My profile</ListItemButton>
</ListItem>
<ListItem>
<ListItemButton>Create a new user</ListItemButton>
</ListItem>
<ListItem>
<ListItemButton>Roles & permission</ListItemButton>
</ListItem>
</List>
</Toggler>
</ListItem>
</List>
<List
size="sm"
sx={{
mt: 'auto',
flexGrow: 0,
'--ListItem-radius': (theme) => theme.vars.radius.sm,
'--List-gap': '8px',
mb: 2,
}}
>
<ListItem>
<ListItemButton>
<SupportRoundedIcon />
Support
</ListItemButton>
</ListItem>
<ListItem>
<ListItemButton>
<SettingsRoundedIcon />
Settings
</ListItemButton>
</ListItem>
</List>
<Card
invertedColors
variant="soft"
color="warning"
size="sm"
sx={{ boxShadow: 'none' }}
>
<Stack
direction="row"
sx={{ justifyContent: 'space-between', alignItems: 'center' }}
>
<Typography level="title-sm">Used space</Typography>
<IconButton size="sm">
<CloseRoundedIcon />
</IconButton>
</Stack>
<Typography level="body-xs">
Your team has used 80% of your available space. Need more?
</Typography>
<LinearProgress variant="outlined" value={80} determinate sx={{ my: 1 }} />
<Button size="sm" variant="solid">
Upgrade plan
</Button>
</Card>
</Box>
<Divider />
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center' }}>
<Avatar
variant="outlined"
size="sm"
src="https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?auto=format&fit=crop&w=286"
/>
<Box sx={{ minWidth: 0, flex: 1 }}>
<Typography level="title-sm">Siriwat K.</Typography>
<Typography level="body-xs">siriwatk@test.com</Typography>
</Box>
<IconButton size="sm" variant="plain" color="neutral">
<LogoutRoundedIcon />
</IconButton>
</Box>
</Sheet>
);
}