-
- Notifications
You must be signed in to change notification settings - Fork 412
[account] [docs] Add <Account /> in sidebarFooter #4255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
38ecc17 7fea561 01c7fa6 49d756a 8098608 6c1c073 f5edc05 43a0978 7277cbf 129b679 f909067 e337ac0 2e321ba 1086869 7938e3f 6807254 c2703a7 884ad56 d76eebf 840362c c71f5ba 6e34be8 a80df48 882b07b 0b2e4f8 77d8eb7 cb9debf 986298c eee948a b93270a cd6a2a0 81e5304 b94774f 67b83fd 2dc6584 cf1276f cc743e5 28b71d5 3c01cde 0aff5f9 0363c00 ce95f41 83cd903 96c760c 2ff572d 86fa603 879f7a7 868eb6e 429b3dc ad12efc 5be7914 637d637 a941719 bdc8e4f a6b4ba9 1c8523d 7334340 73590d7 07d48a8 4e7fdc8 fcd1025 86a84d9 2a1d6d5 d21ac77 6107c53 58f14d6 3eead4a 4b5f4de 6f1499c ef3f403 d8fa6be 8603a43 fd826b3 7b86697 299eb7f 81f6346 2aa87b7 64acd1d 5b21e45 01194bc 45f0499 cbe1024 d64ffae c7949d3 f9a5297 7dd2eb3 1615ae1 File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,295 @@ | ||
| import * as React from 'react'; | ||
| import PropTypes from 'prop-types'; | ||
| import Box from '@mui/material/Box'; | ||
| import Typography from '@mui/material/Typography'; | ||
| import Stack from '@mui/material/Stack'; | ||
| import MenuList from '@mui/material/MenuList'; | ||
| import MenuItem from '@mui/material/MenuItem'; | ||
| import ListItemText from '@mui/material/ListItemText'; | ||
| import ListItemIcon from '@mui/material/ListItemIcon'; | ||
| import Avatar from '@mui/material/Avatar'; | ||
| import Divider from '@mui/material/Divider'; | ||
| import { createTheme } from '@mui/material/styles'; | ||
| import DashboardIcon from '@mui/icons-material/Dashboard'; | ||
| import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; | ||
| import { AppProvider } from '@toolpad/core/AppProvider'; | ||
| import { DashboardLayout } from '@toolpad/core/DashboardLayout'; | ||
| import { | ||
| Account, | ||
| AccountPreview, | ||
| AccountPopoverFooter, | ||
| SignOutButton, | ||
| } from '@toolpad/core/Account'; | ||
| | ||
| const NAVIGATION = [ | ||
| { | ||
| kind: 'header', | ||
| title: 'Main items', | ||
| }, | ||
| { | ||
| segment: 'dashboard', | ||
| title: 'Dashboard', | ||
| icon: <DashboardIcon />, | ||
| }, | ||
| { | ||
| segment: 'orders', | ||
| title: 'Orders', | ||
| icon: <ShoppingCartIcon />, | ||
| }, | ||
| ]; | ||
| | ||
| const demoTheme = createTheme({ | ||
| cssVariables: { | ||
| colorSchemeSelector: 'data-toolpad-color-scheme', | ||
| }, | ||
| colorSchemes: { light: true, dark: true }, | ||
| breakpoints: { | ||
| values: { | ||
| xs: 0, | ||
| sm: 600, | ||
| md: 600, | ||
| lg: 1200, | ||
| xl: 1536, | ||
| }, | ||
| }, | ||
| }); | ||
| | ||
| function DemoPageContent({ pathname }) { | ||
| return ( | ||
| <Box | ||
| sx={{ | ||
| py: 4, | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| alignItems: 'center', | ||
| textAlign: 'center', | ||
| }} | ||
| > | ||
| <Typography>Dashboard content for {pathname}</Typography> | ||
| </Box> | ||
| ); | ||
| } | ||
| | ||
| DemoPageContent.propTypes = { | ||
| pathname: PropTypes.string.isRequired, | ||
| }; | ||
| | ||
| function AccountSidebarPreview(props) { | ||
| const { handleClick, open, mini } = props; | ||
| return ( | ||
| <Stack direction="column" p={0} overflow="hidden"> | ||
| <Divider /> | ||
| <AccountPreview | ||
| variant={mini ? 'condensed' : 'expanded'} | ||
| handleClick={handleClick} | ||
| open={open} | ||
| /> | ||
| </Stack> | ||
| ); | ||
| } | ||
| | ||
| AccountSidebarPreview.propTypes = { | ||
| /** | ||
| * The handler used when the preview is expanded | ||
| */ | ||
| handleClick: PropTypes.func, | ||
| mini: PropTypes.bool.isRequired, | ||
| /** | ||
| * The state of the Account popover | ||
| * @default false | ||
| */ | ||
| open: PropTypes.bool, | ||
| }; | ||
| | ||
| const accounts = [ | ||
| { | ||
| id: 1, | ||
| name: 'Bharat Kashyap', | ||
| email: 'bharatkashyap@outlook.com', | ||
| image: 'https://avatars.githubusercontent.com/u/19550456', | ||
| projects: [ | ||
| { | ||
| id: 3, | ||
| title: 'Project X', | ||
| }, | ||
| ], | ||
| }, | ||
| { | ||
| id: 2, | ||
| name: 'Bharat MUI', | ||
| email: 'bharat@mui.com', | ||
| color: '#8B4513', // Brown color | ||
| projects: [{ id: 4, title: 'Project A' }], | ||
| }, | ||
| ]; | ||
| | ||
| function SidebarFooterAccountPopover() { | ||
| return ( | ||
| <Stack direction="column"> | ||
| <Typography variant="body2" mx={2} mt={1}> | ||
| Accounts | ||
| </Typography> | ||
| <MenuList> | ||
| {accounts.map((account) => ( | ||
| <MenuItem | ||
| key={account.id} | ||
| component="button" | ||
| sx={{ | ||
| justifyContent: 'flex-start', | ||
| width: '100%', | ||
| columnGap: 2, | ||
| }} | ||
| > | ||
| <ListItemIcon> | ||
| <Avatar | ||
| sx={{ | ||
| width: 32, | ||
| height: 32, | ||
| fontSize: '0.95rem', | ||
| bgcolor: account.color, | ||
| }} | ||
| src={account.image ?? ''} | ||
| alt={account.name ?? ''} | ||
| > | ||
| {account.name[0]} | ||
| </Avatar> | ||
| </ListItemIcon> | ||
| <ListItemText | ||
| sx={{ | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| alignItems: 'flex-start', | ||
| width: '100%', | ||
| }} | ||
| primary={account.name} | ||
| secondary={account.email} | ||
| primaryTypographyProps={{ variant: 'body2' }} | ||
| secondaryTypographyProps={{ variant: 'caption' }} | ||
| /> | ||
| </MenuItem> | ||
| ))} | ||
| </MenuList> | ||
| <Divider /> | ||
| <AccountPopoverFooter> | ||
| <SignOutButton /> | ||
| </AccountPopoverFooter> | ||
| </Stack> | ||
| ); | ||
| } | ||
| | ||
| const createPreviewComponent = (mini) => { | ||
| function PreviewComponent(props) { | ||
| return <AccountSidebarPreview {...props} mini={mini} />; | ||
| } | ||
| return PreviewComponent; | ||
| }; | ||
| | ||
| function SidebarFooterAccount({ mini }) { | ||
| const PreviewComponent = React.useMemo(() => createPreviewComponent(mini), [mini]); | ||
| return ( | ||
| <Account | ||
| slots={{ | ||
| preview: PreviewComponent, | ||
| popoverContent: SidebarFooterAccountPopover, | ||
| Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In these docs demos, opening and closing the popover automatically scrolls unless they have the Collaborator Author There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great find! I've added Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I'm not 100% sure if we'd need it in a normal app though, maybe it's just a problem in the demo iframes. | ||
| }} | ||
| slotProps={{ | ||
| popover: { | ||
| transformOrigin: { horizontal: 'left', vertical: 'bottom' }, | ||
| anchorOrigin: { horizontal: 'right', vertical: 'bottom' }, | ||
| disableAutoFocus: true, | ||
| slotProps: { | ||
| paper: { | ||
| elevation: 0, | ||
| sx: { | ||
| overflow: 'visible', | ||
| filter: (theme) => | ||
| `drop-shadow(0px 2px 8px ${theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.10)' : 'rgba(0,0,0,0.32)'})`, | ||
| mt: 1, | ||
| '&::before': { | ||
| content: '""', | ||
| display: 'block', | ||
| position: 'absolute', | ||
| bottom: 10, | ||
| left: 0, | ||
| width: 10, | ||
| height: 10, | ||
| bgcolor: 'background.paper', | ||
| transform: 'translate(-50%, -50%) rotate(45deg)', | ||
| zIndex: 0, | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| }} | ||
| /> | ||
| ); | ||
| } | ||
| | ||
| SidebarFooterAccount.propTypes = { | ||
| mini: PropTypes.bool.isRequired, | ||
| }; | ||
| | ||
| const demoSession = { | ||
| user: { | ||
| name: 'Bharat Kashyap', | ||
| email: 'bharatkashyap@outlook.com', | ||
| image: 'https://avatars.githubusercontent.com/u/19550456', | ||
| }, | ||
| }; | ||
| | ||
| function DashboardLayoutAccountSidebar(props) { | ||
| const { window } = props; | ||
| | ||
| const [pathname, setPathname] = React.useState('/dashboard'); | ||
| | ||
| const router = React.useMemo(() => { | ||
| return { | ||
| pathname, | ||
| searchParams: new URLSearchParams(), | ||
| navigate: (path) => setPathname(String(path)), | ||
| }; | ||
| }, [pathname]); | ||
| | ||
| // Remove this const when copying and pasting into your project. | ||
| const demoWindow = window !== undefined ? window() : undefined; | ||
| | ||
| const [session, setSession] = React.useState(demoSession); | ||
| const authentication = React.useMemo(() => { | ||
| return { | ||
| signIn: () => { | ||
| setSession(demoSession); | ||
| }, | ||
| signOut: () => { | ||
| setSession(null); | ||
| }, | ||
| }; | ||
| }, []); | ||
| | ||
| return ( | ||
| <AppProvider | ||
| navigation={NAVIGATION} | ||
| router={router} | ||
| theme={demoTheme} | ||
| window={demoWindow} | ||
| authentication={authentication} | ||
| session={session} | ||
| > | ||
| <DashboardLayout | ||
| slots={{ toolbarAccount: () => null, sidebarFooter: SidebarFooterAccount }} | ||
| > | ||
| <DemoPageContent pathname={pathname} /> | ||
| </DashboardLayout> | ||
| </AppProvider> | ||
| ); | ||
| } | ||
| | ||
| DashboardLayoutAccountSidebar.propTypes = { | ||
| /** | ||
| * Injected by the documentation to work in an iframe. | ||
| * Remove this when copying and pasting into your project. | ||
| */ | ||
| window: PropTypes.func, | ||
| }; | ||
| | ||
| export default DashboardLayoutAccountSidebar; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 3 dots icon doesn't seem vertically centered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also the popover isn't pointing to / coming from the 3 dots icon, I guess it should?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, I've tweaked the demo to reflect this in both states:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the
expandedvariant, could there be an option to choose whether the popup appears on the right or the top side?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to customize the popover's position (as well as the placement of the arrow) using the
slotProps- the demo on the docs will showcase this using thetransformOriginandanchorOriginprops