From 1086869b73d7ee8e328314f20f914edcb487e740 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 3 Oct 2024 13:15:31 +0200 Subject: [PATCH 01/28] fix: CI --- pnpm-lock.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1667da1e83c..c9c9d105c04 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2066,7 +2066,7 @@ packages: resolution: {integrity: sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==} engines: {node: '>=6.9.0'} peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/core': ^7.25.2 '@babel/preset-typescript@7.24.7': resolution: {integrity: sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==} @@ -2139,7 +2139,7 @@ packages: '@docsearch/react@3.6.2': resolution: {integrity: sha512-rtZce46OOkVflCQH71IdbXSFK+S8iJZlUF56XBW5rIgx/eG5qoomC7Ag3anZson1bBac/JFQn7XOBfved/IMRA==} peerDependencies: - '@types/react': '>= 16.8.0 < 19.0.0' + '@types/react': ^18.3.4 react: '>= 16.8.0 < 19.0.0' react-dom: '>= 16.8.0 < 19.0.0' search-insights: '>= 1 < 3' @@ -3939,8 +3939,8 @@ packages: engines: {node: '>=18'} peerDependencies: '@testing-library/dom': ^10.0.0 - '@types/react': ^18.0.0 - '@types/react-dom': ^18.0.0 + '@types/react': ^18.3.4 + '@types/react-dom': 18.3.0 react: ^18.0.0 react-dom: ^18.0.0 peerDependenciesMeta: From 7938e3f3466c5d0885b6604868aa55ac5aee7ee5 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 3 Oct 2024 13:28:30 +0200 Subject: [PATCH 02/28] fix: WIP `menuItems` -> `content` --- .../core/components/account/AccountSlots.tsx | 4 ++-- .../toolpad/core/components/account/account.md | 16 ++++++++++++++-- packages/toolpad-core/src/Account/Account.tsx | 6 +++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/data/toolpad/core/components/account/AccountSlots.tsx b/docs/data/toolpad/core/components/account/AccountSlots.tsx index 43f9af3a30f..2605403ead2 100644 --- a/docs/data/toolpad/core/components/account/AccountSlots.tsx +++ b/docs/data/toolpad/core/components/account/AccountSlots.tsx @@ -5,7 +5,7 @@ import { SessionContext, Session, } from '@toolpad/core'; -import CustomMenuItems from './CustomMenu'; +import CustomMenu from './CustomMenu'; const demoSession = { user: { @@ -33,7 +33,7 @@ export default function AccountSlots() { diff --git a/docs/data/toolpad/core/components/account/account.md b/docs/data/toolpad/core/components/account/account.md index 7b5121fb8d3..85fece53242 100644 --- a/docs/data/toolpad/core/components/account/account.md +++ b/docs/data/toolpad/core/components/account/account.md @@ -40,6 +40,18 @@ Labels for the sign in and sign out buttons can be customized through the `local ### Slots -You can pass in your own items to the `Account` menu through the `menuItems` slot to add additional menu items in the space between the user's account details and the sign out button, to create larger, more complex menus: +You can pass in your own components to completely override the default components inside the `Account` popover through the `slots` prop. -{{"demo": "AccountSlots.js", "bg": "gradient"}} +#### Content + +Use the `content` slot to add any additional options in the space between the user's account details and the sign out button, to create larger, more complex menus: + +##### Account Switcher + +{{"demo": "AccountSlotsAccountSwitcher.js", "bg": "gradient"}} + +The `content` prop can take any React component, so you can use it to display information instead of adding menu items: + +##### Crypto Wallet + +{{"demo": "AccountSlotsInfo.js", "bg": "outlined" }} diff --git a/packages/toolpad-core/src/Account/Account.tsx b/packages/toolpad-core/src/Account/Account.tsx index 7ea40743f0e..827ee4e1ccf 100644 --- a/packages/toolpad-core/src/Account/Account.tsx +++ b/packages/toolpad-core/src/Account/Account.tsx @@ -42,7 +42,7 @@ export interface AccountSlots { * The component used for the custom menu items. * @default null */ - menuItems?: React.ElementType; + content?: React.ElementType; } export interface AccountProps { @@ -168,13 +168,13 @@ function Account(props: AccountProps) { > -
+
{session.user.name} {session.user.email}
- {slots?.menuItems ? : null} + {slots?.content ? : null} {slots?.signOutButton ? ( ) : ( From 680725409c82983c289f9a162bb677536d6debc9 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 3 Oct 2024 13:30:37 +0200 Subject: [PATCH 03/28] wip: Move demos over --- ...ts.tsx => AccountSlotsAccountSwitcher.tsx} | 2 +- .../components/account/AccountSlotsInfo.tsx | 119 ++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) rename docs/data/toolpad/core/components/account/{AccountSlots.tsx => AccountSlotsAccountSwitcher.tsx} (94%) create mode 100644 docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx diff --git a/docs/data/toolpad/core/components/account/AccountSlots.tsx b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx similarity index 94% rename from docs/data/toolpad/core/components/account/AccountSlots.tsx rename to docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx index 2605403ead2..ea03da06080 100644 --- a/docs/data/toolpad/core/components/account/AccountSlots.tsx +++ b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx @@ -15,7 +15,7 @@ const demoSession = { }, }; -export default function AccountSlots() { +export default function AccountSlotsAccountSwitcher() { const [session, setSession] = React.useState(demoSession); const authentication = React.useMemo(() => { return { diff --git a/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx b/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx new file mode 100644 index 00000000000..861c6332880 --- /dev/null +++ b/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx @@ -0,0 +1,119 @@ +import * as React from 'react'; +import { + Avatar, + Button, + Divider, + Typography, + Stack, + IconButton, +} from '@mui/material'; +import WalletIcon from '@mui/icons-material/AccountBalance'; +import SendIcon from '@mui/icons-material/Send'; +import ShoppingCart from '@mui/icons-material/ShoppingCart'; +import CopyIcon from '@mui/icons-material/ContentCopy'; + +import { + Account, + AuthenticationContext, + SessionContext, + Session, +} from '@toolpad/core'; + +const demoSession = { + user: { + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + }, +}; + +const mockData = { + address: '0x1234...5678', + balance: '1,234.56 ETH', + usdBalance: '$2,345,678.90 USD', +}; + +function CryptoWalletInfo() { + return ( +
+ + + + + + + + {mockData.address} + + + + + + Main Account + + + + + + + {mockData.balance} + + + {mockData.usdBalance} + + + + + + + + + +
+ ); +} + +export default function AccountSlotsInfo() { + const [session, setSession] = React.useState(demoSession); + const authentication = React.useMemo(() => { + return { + signIn: () => { + setSession(demoSession); + }, + signOut: () => { + setSession(null); + }, + }; + }, []); + + return ( + + + + + + ); +} From c2703a76bfba6a62020668dccf599d286d610e11 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 3 Oct 2024 13:31:16 +0200 Subject: [PATCH 04/28] fix: Move demos to new API --- .../core/components/account/CustomMenu.tsx | 98 ++++++++++++++++--- 1 file changed, 83 insertions(+), 15 deletions(-) diff --git a/docs/data/toolpad/core/components/account/CustomMenu.tsx b/docs/data/toolpad/core/components/account/CustomMenu.tsx index bdf09af5c13..7db92408f3d 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.tsx +++ b/docs/data/toolpad/core/components/account/CustomMenu.tsx @@ -1,9 +1,19 @@ import * as React from 'react'; -import { Menu, MenuItem, MenuList, Divider, ListItemIcon } from '@mui/material'; +import { + Menu, + MenuItem, + MenuList, + Divider, + ListItemIcon, + ListItemText, + Typography, + Avatar, +} from '@mui/material'; +import PersonIcon from '@mui/icons-material/Person'; +import ExitToAppIcon from '@mui/icons-material/ExitToApp'; import SettingsIcon from '@mui/icons-material/Settings'; -import AddIcon from '@mui/icons-material/Add'; -interface CustomSettingsMenuProps { +interface AccountSwitcherProps { open: boolean; anchorEl: HTMLButtonElement | null; handleMenuClose: () => void; @@ -11,7 +21,23 @@ interface CustomSettingsMenuProps { handleEnter: () => void; } -function CustomSettingsMenu(props: CustomSettingsMenuProps) { +// Function to generate a random color +const getRandomColor = () => { + const letters = '0123456789ABCDEF'; + let color = '#'; + for (let i = 0; i < 6; i += 1) { + color += letters[Math.floor(Math.random() * 16)]; + } + return color; +}; + +const accounts = [ + { id: 1, name: 'John Doe', email: 'john@example.com', color: getRandomColor() }, + { id: 2, name: 'Jane Smith', email: 'jane@example.com', color: getRandomColor() }, + { id: 3, name: 'Bob Johnson', email: 'bob@example.com', color: getRandomColor() }, +]; + +function AccountSwitcher(props: AccountSwitcherProps) { const { open, anchorEl, handleMenuClose, handleEnter, handleLeave } = props; return ( @@ -31,16 +57,45 @@ function CustomSettingsMenu(props: CustomSettingsMenuProps) { }} > { handleEnter(); }} onMouseLeave={handleLeave} > - Profile - My account + + Accounts + + + {accounts.map((account) => ( + + + + {account.name.charAt(0)} + + + + + ))} ); @@ -49,7 +104,7 @@ function CustomSettingsMenu(props: CustomSettingsMenuProps) { export default function CustomMenu() { const handleMenuNavigation = (route: string) => () => { console.log( - 'Toolpad Core Account Demo --- CustomMenuItems --- handleMenuNavigation --- route: ', + 'Toolpad Core Account Demo --- CustomContent --- handleMenuNavigation --- route: ', route, ); }; @@ -96,8 +151,20 @@ export default function CustomMenu() { return ( + + + + Profile + + - + - Add another account + Switch Account - Date: Mon, 7 Oct 2024 10:44:36 +0530 Subject: [PATCH 05/28] wip: Better account switcher --- ...lots.js => AccountSlotsAccountSwitcher.js} | 6 +- ...> AccountSlotsAccountSwitcher.tsx.preview} | 2 +- .../components/account/AccountSlotsInfo.js | 114 +++++++++++ .../account/AccountSlotsInfo.tsx.preview | 9 + .../core/components/account/CustomMenu.js | 192 +++++++++++++----- .../core/components/account/CustomMenu.tsx | 186 ++++++++++------- docs/pages/toolpad/core/api/account.json | 4 +- .../toolpad/core/api/dashboard-layout.json | 2 +- .../api-docs/account/account.json | 2 +- packages/toolpad-core/src/Account/Account.tsx | 4 +- .../src/DashboardLayout/DashboardLayout.tsx | 2 +- 11 files changed, 386 insertions(+), 137 deletions(-) rename docs/data/toolpad/core/components/account/{AccountSlots.js => AccountSlotsAccountSwitcher.js} (86%) rename docs/data/toolpad/core/components/account/{AccountSlots.tsx.preview => AccountSlotsAccountSwitcher.tsx.preview} (85%) create mode 100644 docs/data/toolpad/core/components/account/AccountSlotsInfo.js create mode 100644 docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx.preview diff --git a/docs/data/toolpad/core/components/account/AccountSlots.js b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js similarity index 86% rename from docs/data/toolpad/core/components/account/AccountSlots.js rename to docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js index 31051b0adab..97b3aa14b99 100644 --- a/docs/data/toolpad/core/components/account/AccountSlots.js +++ b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js @@ -1,6 +1,6 @@ import * as React from 'react'; import { Account, AuthenticationContext, SessionContext } from '@toolpad/core'; -import CustomMenuItems from './CustomMenu'; +import CustomMenu from './CustomMenu'; const demoSession = { user: { @@ -10,7 +10,7 @@ const demoSession = { }, }; -export default function AccountSlots() { +export default function AccountSlotsAccountSwitcher() { const [session, setSession] = React.useState(demoSession); const authentication = React.useMemo(() => { return { @@ -28,7 +28,7 @@ export default function AccountSlots() { diff --git a/docs/data/toolpad/core/components/account/AccountSlots.tsx.preview b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview similarity index 85% rename from docs/data/toolpad/core/components/account/AccountSlots.tsx.preview rename to docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview index 5e8ecca9f06..18a06d57ca7 100644 --- a/docs/data/toolpad/core/components/account/AccountSlots.tsx.preview +++ b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview @@ -2,7 +2,7 @@ diff --git a/docs/data/toolpad/core/components/account/AccountSlotsInfo.js b/docs/data/toolpad/core/components/account/AccountSlotsInfo.js new file mode 100644 index 00000000000..a6506788fd8 --- /dev/null +++ b/docs/data/toolpad/core/components/account/AccountSlotsInfo.js @@ -0,0 +1,114 @@ +import * as React from 'react'; +import { + Avatar, + Button, + Divider, + Typography, + Stack, + IconButton, +} from '@mui/material'; +import WalletIcon from '@mui/icons-material/AccountBalance'; +import SendIcon from '@mui/icons-material/Send'; +import ShoppingCart from '@mui/icons-material/ShoppingCart'; +import CopyIcon from '@mui/icons-material/ContentCopy'; + +import { Account, AuthenticationContext, SessionContext } from '@toolpad/core'; + +const demoSession = { + user: { + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + }, +}; + +const mockData = { + address: '0x1234...5678', + balance: '1,234.56 ETH', + usdBalance: '$2,345,678.90 USD', +}; + +function CryptoWalletInfo() { + return ( +
+ + + + + + + + {mockData.address} + + + + + + Main Account + + + + + + + {mockData.balance} + + + {mockData.usdBalance} + + + + + + + + + +
+ ); +} + +export default function AccountSlotsInfo() { + const [session, setSession] = React.useState(demoSession); + const authentication = React.useMemo(() => { + return { + signIn: () => { + setSession(demoSession); + }, + signOut: () => { + setSession(null); + }, + }; + }, []); + + return ( + + + + + + ); +} diff --git a/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx.preview b/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx.preview new file mode 100644 index 00000000000..29ceba32bb0 --- /dev/null +++ b/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx.preview @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/docs/data/toolpad/core/components/account/CustomMenu.js b/docs/data/toolpad/core/components/account/CustomMenu.js index 2bbee81379a..bc13f2c6b29 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.js +++ b/docs/data/toolpad/core/components/account/CustomMenu.js @@ -1,11 +1,54 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import { Menu, MenuItem, MenuList, Divider, ListItemIcon } from '@mui/material'; -import SettingsIcon from '@mui/icons-material/Settings'; +import { + Menu, + MenuItem, + MenuList, + Button, + Divider, + ListItemIcon, + ListItemText, + Typography, + Avatar, +} from '@mui/material'; import AddIcon from '@mui/icons-material/Add'; -function CustomSettingsMenu(props) { - const { open, anchorEl, handleMenuClose, handleEnter, handleLeave } = props; +// Function to generate a random color +const getRandomColor = () => { + const letters = '0123456789ABCDEF'; + let color = '#'; + for (let i = 0; i < 6; i += 1) { + color += letters[Math.floor(Math.random() * 16)]; + } + return color; +}; + +const accounts = [ + { + id: 1, + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + color: getRandomColor(), + projects: [ + { + id: 3, + title: 'Project X', + }, + ], + }, + { + id: 2, + name: 'Bharat MUI', + email: 'bharat@mui.com', + color: getRandomColor(), + projects: [{ id: 4, title: 'Project A' }], + }, +]; + +function ProjectsList(props) { + const { open, anchorEl, handleMenuClose, handleEnter, handleLeave, projects } = + props; return ( { handleEnter(); }} onMouseLeave={handleLeave} > - Profile - My account + + Projects + + + {projects?.map((project) => ( + + + + ))} + + ); } -CustomSettingsMenu.propTypes = { +ProjectsList.propTypes = { anchorEl: PropTypes.object, handleEnter: PropTypes.func.isRequired, handleLeave: PropTypes.func.isRequired, handleMenuClose: PropTypes.func.isRequired, open: PropTypes.bool.isRequired, + projects: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.number.isRequired, + title: PropTypes.string.isRequired, + }), + ).isRequired, }; export default function CustomMenu() { - const handleMenuNavigation = (route) => () => { - console.log( - 'Toolpad Core Account Demo --- CustomMenuItems --- handleMenuNavigation --- route: ', - route, - ); - }; - const mouseOnSubMenu = React.useRef(false); + const [selectedProjects, setSelectedProjects] = React.useState([]); + + const handleSelectProjects = React.useCallback((id) => { + setSelectedProjects( + accounts.find((account) => account.id === id)?.projects ?? [], + ); + }, []); + const [subMenuAnchorEl, setSubMenuAnchorEl] = React.useState(null); const subMenuOpen = Boolean(subMenuAnchorEl); - const handleTriggerEnter = React.useCallback((event) => { - setSubMenuAnchorEl(event.currentTarget); - }, []); + const handleTriggerEnter = React.useCallback( + (event, id) => { + handleSelectProjects(id); + setSubMenuAnchorEl(event.currentTarget); + }, + [handleSelectProjects], + ); const handleTriggerLeave = React.useCallback(() => { // Wait for 300ms to see if the mouse has moved to the sub menu @@ -92,41 +172,59 @@ export default function CustomMenu() { return ( - - - - - Settings - - - - - - Add another account - + + Accounts + + {accounts.map((account) => ( + handleSelectProjects(account.id)} + onMouseEnter={(event) => handleTriggerEnter(event, account.id)} + onMouseLeave={handleTriggerLeave} + > + + + {account.name[0]} + + + + + ))} - ); diff --git a/docs/data/toolpad/core/components/account/CustomMenu.tsx b/docs/data/toolpad/core/components/account/CustomMenu.tsx index 7db92408f3d..3e36e619022 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.tsx +++ b/docs/data/toolpad/core/components/account/CustomMenu.tsx @@ -1,24 +1,30 @@ import * as React from 'react'; import { Menu, + Box, MenuItem, MenuList, + Button, Divider, ListItemIcon, ListItemText, Typography, Avatar, } from '@mui/material'; -import PersonIcon from '@mui/icons-material/Person'; -import ExitToAppIcon from '@mui/icons-material/ExitToApp'; -import SettingsIcon from '@mui/icons-material/Settings'; +import AddIcon from '@mui/icons-material/Add'; -interface AccountSwitcherProps { +interface Project { + id: number; + title: string; +} + +interface ProjectsListProps { open: boolean; anchorEl: HTMLButtonElement | null; handleMenuClose: () => void; handleLeave: (event: React.MouseEvent) => void; handleEnter: () => void; + projects: Project[]; } // Function to generate a random color @@ -32,13 +38,31 @@ const getRandomColor = () => { }; const accounts = [ - { id: 1, name: 'John Doe', email: 'john@example.com', color: getRandomColor() }, - { id: 2, name: 'Jane Smith', email: 'jane@example.com', color: getRandomColor() }, - { id: 3, name: 'Bob Johnson', email: 'bob@example.com', color: getRandomColor() }, + { + id: 1, + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + color: getRandomColor(), + projects: [ + { + id: 3, + title: 'Project X', + }, + ], + }, + { + id: 2, + name: 'Bharat MUI', + email: 'bharat@mui.com', + color: getRandomColor(), + projects: [{ id: 4, title: 'Project A' }], + }, ]; -function AccountSwitcher(props: AccountSwitcherProps) { - const { open, anchorEl, handleMenuClose, handleEnter, handleLeave } = props; +function ProjectsList(props: ProjectsListProps) { + const { open, anchorEl, handleMenuClose, handleEnter, handleLeave, projects } = + props; return ( { @@ -66,60 +91,58 @@ function AccountSwitcher(props: AccountSwitcherProps) { }} onMouseLeave={handleLeave} > - - Accounts + + Projects - {accounts.map((account) => ( + {projects?.map((project) => ( - - - {account.name.charAt(0)} - - ))} + + ); } export default function CustomMenu() { - const handleMenuNavigation = (route: string) => () => { - console.log( - 'Toolpad Core Account Demo --- CustomContent --- handleMenuNavigation --- route: ', - route, - ); - }; - const mouseOnSubMenu = React.useRef(false); + const [selectedProjects, setSelectedProjects] = React.useState([]); + + const handleSelectProjects = React.useCallback((id: number) => { + setSelectedProjects( + accounts.find((account) => account.id === id)?.projects ?? [], + ); + }, []); + const [subMenuAnchorEl, setSubMenuAnchorEl] = React.useState(null); const subMenuOpen = Boolean(subMenuAnchorEl); const handleTriggerEnter = React.useCallback( - (event: React.MouseEvent) => { + (event: React.MouseEvent, id: number) => { + handleSelectProjects(id); setSubMenuAnchorEl(event.currentTarget); }, - [], + [handleSelectProjects], ); const handleTriggerLeave = React.useCallback(() => { @@ -150,54 +173,59 @@ export default function CustomMenu() { return ( - - - - - Profile - - - - - - Settings - - - - - - Switch Account - + + Accounts + + {accounts.map((account) => ( + handleSelectProjects(account.id)} + onMouseEnter={(event) => handleTriggerEnter(event, account.id)} + onMouseLeave={handleTriggerLeave} + > + + + {account.name[0]} + + + + + ))} - ); diff --git a/docs/pages/toolpad/core/api/account.json b/docs/pages/toolpad/core/api/account.json index 16f12682220..0d67c143d07 100644 --- a/docs/pages/toolpad/core/api/account.json +++ b/docs/pages/toolpad/core/api/account.json @@ -13,7 +13,7 @@ "slots": { "type": { "name": "shape", - "description": "{ menuItems?: elementType, signInButton?: elementType, signOutButton?: elementType }" + "description": "{ content?: elementType, signInButton?: elementType, signOutButton?: elementType }" }, "additionalInfo": { "slotsApi": true } } @@ -37,7 +37,7 @@ "class": null }, { - "name": "menuItems", + "name": "content", "description": "The component used for the custom menu items.", "default": "null", "class": null diff --git a/docs/pages/toolpad/core/api/dashboard-layout.json b/docs/pages/toolpad/core/api/dashboard-layout.json index 8e5707511f8..225a1e63df0 100644 --- a/docs/pages/toolpad/core/api/dashboard-layout.json +++ b/docs/pages/toolpad/core/api/dashboard-layout.json @@ -5,7 +5,7 @@ "slotProps": { "type": { "name": "shape", - "description": "{ toolbarAccount?: { localeText?: { signInLabel: string, signOutLabel: string }, slotProps?: { iconButton?: object, signInButton?: object, signOutButton?: object }, slots?: { menuItems?: elementType, signInButton?: elementType, signOutButton?: elementType } }, toolbarActions?: object }" + "description": "{ toolbarAccount?: { localeText?: { signInLabel: string, signOutLabel: string }, slotProps?: { iconButton?: object, signInButton?: object, signOutButton?: object }, slots?: { content?: elementType, signInButton?: elementType, signOutButton?: elementType } }, toolbarActions?: object }" }, "default": "{}" }, diff --git a/docs/translations/api-docs/account/account.json b/docs/translations/api-docs/account/account.json index 58620d755a2..46ed24ed1fc 100644 --- a/docs/translations/api-docs/account/account.json +++ b/docs/translations/api-docs/account/account.json @@ -7,7 +7,7 @@ }, "classDescriptions": {}, "slotDescriptions": { - "menuItems": "The component used for the custom menu items.", + "content": "The component used for the custom menu items.", "signInButton": "The component used for the sign in button.", "signOutButton": "The component used for the sign out button." } diff --git a/packages/toolpad-core/src/Account/Account.tsx b/packages/toolpad-core/src/Account/Account.tsx index 827ee4e1ccf..8912016befc 100644 --- a/packages/toolpad-core/src/Account/Account.tsx +++ b/packages/toolpad-core/src/Account/Account.tsx @@ -15,7 +15,7 @@ import DEFAULT_LOCALE_TEXT from '../shared/locales/en'; const AccountInfoContainer = styled('div')(({ theme }) => ({ display: 'flex', flexDirection: 'row', - justifyContent: 'space-between', + justifyContent: 'flex-start', padding: theme.spacing(2), gap: theme.spacing(2), })); @@ -231,7 +231,7 @@ Account.propTypes /* remove-proptypes */ = { * The components used for each slot inside. */ slots: PropTypes.shape({ - menuItems: PropTypes.elementType, + content: PropTypes.elementType, signInButton: PropTypes.elementType, signOutButton: PropTypes.elementType, }), diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx index b21df1beee3..e963918e059 100644 --- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx +++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx @@ -681,7 +681,7 @@ DashboardLayout.propTypes /* remove-proptypes */ = { signOutButton: PropTypes.object, }), slots: PropTypes.shape({ - menuItems: PropTypes.elementType, + content: PropTypes.elementType, signInButton: PropTypes.elementType, signOutButton: PropTypes.elementType, }), From d76eebfdda69a4753938426e6000d730406884f0 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Mon, 7 Oct 2024 14:10:30 +0530 Subject: [PATCH 06/28] fix: CI --- pnpm-lock.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c9c9d105c04..1e1352faec8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -195,7 +195,7 @@ importers: version: 7.37.0(eslint@8.57.1) eslint-plugin-react-compiler: specifier: latest - version: 0.0.0-experimental-42acc6a-20241001(eslint@8.57.1) + version: 0.0.0-experimental-9a75bad-20241003(eslint@8.57.1) eslint-plugin-react-hooks: specifier: 4.6.2 version: 4.6.2(eslint@8.57.1) @@ -2066,7 +2066,7 @@ packages: resolution: {integrity: sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==} engines: {node: '>=6.9.0'} peerDependencies: - '@babel/core': ^7.25.2 + '@babel/core': ^7.0.0-0 '@babel/preset-typescript@7.24.7': resolution: {integrity: sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==} @@ -5932,8 +5932,8 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-plugin-react-compiler@0.0.0-experimental-42acc6a-20241001: - resolution: {integrity: sha512-pzkTsWowlHK4yKHsK1d9tTKOUtApZzL7wI6jT5iN31d00DhI9JGDD0pkLohQ6Wfkll+2aiqTPGj9esJoGYmRaw==} + eslint-plugin-react-compiler@0.0.0-experimental-9a75bad-20241003: + resolution: {integrity: sha512-qZ/oEuECrXt3J4+13TvHEOBfrizBuUborCMFccZFn64UcWgbLzn+6Yb4xVx80YQiT1GT6UiKh62OkvnP6yYR2w==} engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} peerDependencies: eslint: '>=7' @@ -5984,6 +5984,7 @@ packages: eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true espree@9.6.1: @@ -15739,7 +15740,7 @@ snapshots: globals: 13.24.0 rambda: 7.5.0 - eslint-plugin-react-compiler@0.0.0-experimental-42acc6a-20241001(eslint@8.57.1): + eslint-plugin-react-compiler@0.0.0-experimental-9a75bad-20241003(eslint@8.57.1): dependencies: '@babel/core': 7.25.2 '@babel/parser': 7.25.6 From c71f5ba98b18f94118719dbaa6c728d31195263a Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Mon, 7 Oct 2024 17:13:07 +0530 Subject: [PATCH 07/28] fix: Complete better account switcher --- .../core/components/account/CustomMenu.js | 34 ++++++++++--------- .../core/components/account/CustomMenu.tsx | 34 ++++++++++--------- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/docs/data/toolpad/core/components/account/CustomMenu.js b/docs/data/toolpad/core/components/account/CustomMenu.js index bc13f2c6b29..5f0870331af 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.js +++ b/docs/data/toolpad/core/components/account/CustomMenu.js @@ -11,25 +11,15 @@ import { Typography, Avatar, } from '@mui/material'; +import FolderIcon from '@mui/icons-material/Folder'; import AddIcon from '@mui/icons-material/Add'; -// Function to generate a random color -const getRandomColor = () => { - const letters = '0123456789ABCDEF'; - let color = '#'; - for (let i = 0; i < 6; i += 1) { - color += letters[Math.floor(Math.random() * 16)]; - } - return color; -}; - const accounts = [ { id: 1, name: 'Bharat Kashyap', email: 'bharatkashyap@outlook.com', image: 'https://avatars.githubusercontent.com/u/19550456', - color: getRandomColor(), projects: [ { id: 3, @@ -41,7 +31,7 @@ const accounts = [ id: 2, name: 'Bharat MUI', email: 'bharat@mui.com', - color: getRandomColor(), + color: '#8B4513', // Brown color projects: [{ id: 4, title: 'Project A' }], }, ]; @@ -87,6 +77,9 @@ function ProjectsList(props) { onClick={handleMenuClose} sx={{ px: 1, my: 1, columnGap: '1.25rem' }} > + + + - ); } diff --git a/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx b/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx index fa92c9d1db8..8e4fe42d2cf 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx +++ b/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx @@ -38,6 +38,7 @@ function CryptoWalletInfo() { return ( + @@ -96,8 +97,7 @@ function CryptoWalletInfo() { Buy - - + ); } diff --git a/docs/data/toolpad/core/components/account/CustomMenu.js b/docs/data/toolpad/core/components/account/CustomMenu.js index 30dadaecdf5..9637ac5c1a0 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.js +++ b/docs/data/toolpad/core/components/account/CustomMenu.js @@ -177,6 +177,7 @@ export default function CustomMenu() { return ( + Accounts @@ -190,7 +191,6 @@ export default function CustomMenu() { width: '100%', columnGap: 2, }} - // onClick={() => handleSelectProjects(account.id)} onMouseEnter={(event) => handleTriggerEnter(event, account.id)} onMouseLeave={handleTriggerLeave} > @@ -222,8 +222,6 @@ export default function CustomMenu() { />
))} - - + Accounts @@ -188,9 +189,8 @@ export default function CustomMenu() { sx={{ justifyContent: 'flex-start', width: '100%', - columnGap: 2, - }} - // onClick={() => handleSelectProjects(account.id)} + columnGap: 2, + }} onMouseEnter={(event) => handleTriggerEnter(event, account.id)} onMouseLeave={handleTriggerLeave} > @@ -221,9 +221,7 @@ export default function CustomMenu() { secondaryTypographyProps={{ variant: 'caption' }} /> - ))} - - + ))} {slots?.content ? : } + {slots?.signOutButton ? ( ) : ( diff --git a/packages/toolpad-core/src/Account/AccountDetails.tsx b/packages/toolpad-core/src/Account/AccountDetails.tsx index 14f8b5833a8..085a78feff1 100644 --- a/packages/toolpad-core/src/Account/AccountDetails.tsx +++ b/packages/toolpad-core/src/Account/AccountDetails.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import Avatar, { AvatarProps } from '@mui/material/Avatar'; -import Divider from '@mui/material/Divider'; import Typography from '@mui/material/Typography'; import Stack from '@mui/material/Stack'; import { SessionContext } from '../AppProvider'; @@ -36,8 +35,7 @@ function AccountDetails(props: AvatarProps) { {session.user?.name} {session.user?.email}
- - + ); } From 0363c0000311acfc71d9b4c86b5260308f876824 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Sun, 13 Oct 2024 14:42:55 +0530 Subject: [PATCH 16/28] fix: Remove `Divider` from `AccountDetails` --- .../toolpad/core/components/account/AccountSlotsInfo.tsx | 2 +- docs/data/toolpad/core/components/account/CustomMenu.tsx | 6 +++--- packages/toolpad-core/src/Account/AccountDetails.test.tsx | 6 +++--- packages/toolpad-core/src/Account/AccountDetails.tsx | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx b/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx index 8e4fe42d2cf..c68f837d08f 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx +++ b/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx @@ -97,7 +97,7 @@ function CryptoWalletInfo() { Buy - + ); } diff --git a/docs/data/toolpad/core/components/account/CustomMenu.tsx b/docs/data/toolpad/core/components/account/CustomMenu.tsx index 5e29086047d..b0f2c2418c3 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.tsx +++ b/docs/data/toolpad/core/components/account/CustomMenu.tsx @@ -189,8 +189,8 @@ export default function CustomMenu() { sx={{ justifyContent: 'flex-start', width: '100%', - columnGap: 2, - }} + columnGap: 2, + }} onMouseEnter={(event) => handleTriggerEnter(event, account.id)} onMouseLeave={handleTriggerLeave} > @@ -221,7 +221,7 @@ export default function CustomMenu() { secondaryTypographyProps={{ variant: 'caption' }} /> - ))} + ))} { render( - + , ); const avatar = screen.getByRole('img', { name: 'John Doe' }); @@ -55,9 +55,9 @@ describe('AccountDetails', () => { render( - + , ); - + expect(screen.getByText('Jane Smith')).toBeInTheDocument(); expect(screen.getByText('jane@example.com')).toBeInTheDocument(); }); diff --git a/packages/toolpad-core/src/Account/AccountDetails.tsx b/packages/toolpad-core/src/Account/AccountDetails.tsx index 085a78feff1..db2c63e6a11 100644 --- a/packages/toolpad-core/src/Account/AccountDetails.tsx +++ b/packages/toolpad-core/src/Account/AccountDetails.tsx @@ -35,7 +35,7 @@ function AccountDetails(props: AvatarProps) { {session.user?.name} {session.user?.email} - + ); } From 2ff572d30d661efe4140475088921316e4615cc5 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Sun, 13 Oct 2024 17:02:26 +0530 Subject: [PATCH 17/28] fix: Move `AccountDetails` into separate component and `slots` --- .../toolpad/core/api/account-details.json | 62 ++++--------- .../account-details/account-details.json | 36 ++------ packages/toolpad-core/src/Account/Account.tsx | 2 +- .../src/Account/AccountDetails.tsx | 43 --------- packages/toolpad-core/src/Account/index.ts | 1 - .../AccountDetails.test.tsx | 0 .../src/AccountDetails/AccountDetails.tsx | 87 +++++++++++++++++++ .../toolpad-core/src/AccountDetails/index.ts | 1 + packages/toolpad-core/src/index.ts | 2 + 9 files changed, 115 insertions(+), 119 deletions(-) delete mode 100644 packages/toolpad-core/src/Account/AccountDetails.tsx rename packages/toolpad-core/src/{Account => AccountDetails}/AccountDetails.test.tsx (100%) create mode 100644 packages/toolpad-core/src/AccountDetails/AccountDetails.tsx create mode 100644 packages/toolpad-core/src/AccountDetails/index.ts diff --git a/docs/pages/toolpad/core/api/account-details.json b/docs/pages/toolpad/core/api/account-details.json index fdc059e5508..3aedce76907 100644 --- a/docs/pages/toolpad/core/api/account-details.json +++ b/docs/pages/toolpad/core/api/account-details.json @@ -1,55 +1,29 @@ { - "props": {}, + "props": { + "slotProps": { "type": { "name": "shape", "description": "{ avatar: object }" } }, + "slots": { + "type": { "name": "shape", "description": "{ avatar?: elementType }" }, + "additionalInfo": { "slotsApi": true } + } + }, "name": "AccountDetails", - "imports": ["import { AccountDetails } from '@toolpad/core/Account';"], - "classes": [ - { - "key": "circular", - "className": "", - "description": "Styles applied to the root element if `variant=\"circular\"`.", - "isGlobal": false - }, - { - "key": "colorDefault", - "className": "", - "description": "Styles applied to the root element if not `src` or `srcSet`.", - "isGlobal": false - }, - { - "key": "fallback", - "className": "", - "description": "Styles applied to the fallback icon", - "isGlobal": false - }, - { - "key": "img", - "className": "", - "description": "Styles applied to the img element if either `src` or `srcSet` is defined.", - "isGlobal": false - }, - { - "key": "root", - "className": "", - "description": "Styles applied to the root element.", - "isGlobal": false - }, - { - "key": "rounded", - "className": "", - "description": "Styles applied to the root element if `variant=\"rounded\"`.", - "isGlobal": false - }, + "imports": [ + "import { AccountDetails } from '@toolpad/core/AccountDetails';", + "import { AccountDetails } from '@toolpad/core';" + ], + "slots": [ { - "key": "square", - "className": "", - "description": "Styles applied to the root element if `variant=\"square\"`.", - "isGlobal": false + "name": "avatar", + "description": "The component used for the Avatar", + "default": "Avatar", + "class": null } ], + "classes": [], "spread": true, "themeDefaultProps": false, "muiName": "AccountDetails", - "filename": "/packages/toolpad-core/src/Account/AccountDetails.tsx", + "filename": "/packages/toolpad-core/src/AccountDetails/AccountDetails.tsx", "inheritance": null, "demos": "", "cssComponent": false diff --git a/docs/translations/api-docs/account-details/account-details.json b/docs/translations/api-docs/account-details/account-details.json index eff5b0507e7..64306d52dd6 100644 --- a/docs/translations/api-docs/account-details/account-details.json +++ b/docs/translations/api-docs/account-details/account-details.json @@ -1,33 +1,9 @@ { "componentDescription": "", - "propDescriptions": {}, - "classDescriptions": { - "circular": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"circular\"" - }, - "colorDefault": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "not src or srcSet" - }, - "fallback": { "description": "Styles applied to the fallback icon" }, - "img": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the img element", - "conditions": "either src or srcSet is defined" - }, - "root": { "description": "Styles applied to the root element." }, - "rounded": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"rounded\"" - }, - "square": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"square\"" - } - } + "propDescriptions": { + "slotProps": { "description": "The props used for each slot inside." }, + "slots": { "description": "The components used for each slot inside." } + }, + "classDescriptions": {}, + "slotDescriptions": { "avatar": "The component used for the Avatar" } } diff --git a/packages/toolpad-core/src/Account/Account.tsx b/packages/toolpad-core/src/Account/Account.tsx index f98af4125a6..1c5fb9d9b11 100644 --- a/packages/toolpad-core/src/Account/Account.tsx +++ b/packages/toolpad-core/src/Account/Account.tsx @@ -8,7 +8,7 @@ import Button, { ButtonProps } from '@mui/material/Button'; import IconButton, { IconButtonProps } from '@mui/material/IconButton'; import Tooltip from '@mui/material/Tooltip'; import Logout from '@mui/icons-material/Logout'; -import { AccountDetails } from './AccountDetails'; +import { AccountDetails } from '../AccountDetails/AccountDetails'; import { SessionContext, AuthenticationContext } from '../AppProvider/AppProvider'; import DEFAULT_LOCALE_TEXT from '../shared/locales/en'; diff --git a/packages/toolpad-core/src/Account/AccountDetails.tsx b/packages/toolpad-core/src/Account/AccountDetails.tsx deleted file mode 100644 index db2c63e6a11..00000000000 --- a/packages/toolpad-core/src/Account/AccountDetails.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import * as React from 'react'; -import Avatar, { AvatarProps } from '@mui/material/Avatar'; -import Typography from '@mui/material/Typography'; -import Stack from '@mui/material/Stack'; -import { SessionContext } from '../AppProvider'; - -/** - * - * Demos: - * - * - [Account](https://mui.com/toolpad/core/react-account/) - * - * API: - * - * - [AccountDetails API](https://mui.com/toolpad/core/api/account-details) - */ - -function AccountDetails(props: AvatarProps) { - const session = React.useContext(SessionContext); - - if (!session) { - return null; - } - - return ( - - - -
- {session.user?.name} - {session.user?.email} -
-
-
- ); -} - -export { AccountDetails }; diff --git a/packages/toolpad-core/src/Account/index.ts b/packages/toolpad-core/src/Account/index.ts index 2bdc9eeff61..4c71833ffeb 100644 --- a/packages/toolpad-core/src/Account/index.ts +++ b/packages/toolpad-core/src/Account/index.ts @@ -1,2 +1 @@ export * from './Account'; -export * from './AccountDetails'; diff --git a/packages/toolpad-core/src/Account/AccountDetails.test.tsx b/packages/toolpad-core/src/AccountDetails/AccountDetails.test.tsx similarity index 100% rename from packages/toolpad-core/src/Account/AccountDetails.test.tsx rename to packages/toolpad-core/src/AccountDetails/AccountDetails.test.tsx diff --git a/packages/toolpad-core/src/AccountDetails/AccountDetails.tsx b/packages/toolpad-core/src/AccountDetails/AccountDetails.tsx new file mode 100644 index 00000000000..532bd7e5ddc --- /dev/null +++ b/packages/toolpad-core/src/AccountDetails/AccountDetails.tsx @@ -0,0 +1,87 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import Avatar, { AvatarProps } from '@mui/material/Avatar'; +import Typography from '@mui/material/Typography'; +import Stack from '@mui/material/Stack'; +import { SessionContext } from '../AppProvider'; + +export interface AccountDetailsSlots { + /** + * The component used for the Avatar + * @default Avatar + */ + avatar?: React.ElementType; +} + +export interface AccountDetailsProps { + /** + * The components used for each slot inside. + */ + slots?: AccountDetailsSlots; + /** + * The props used for each slot inside. + */ + slotProps?: { + avatar: AvatarProps; + }; +} +/** + * + * Demos: + * + * - [Account](https://mui.com/toolpad/core/react-account/) + * + * API: + * + * - [AccountDetails API](https://mui.com/toolpad/core/api/account-details) + */ +function AccountDetails(props: AccountDetailsProps) { + const { slots, slotProps } = props; + const session = React.useContext(SessionContext); + + if (!session) { + return null; + } + + return ( + + + {slots?.avatar ? ( + + ) : ( + + )} + + {session.user?.name} + {session.user?.email} + + + + ); +} + +AccountDetails.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * The props used for each slot inside. + */ + slotProps: PropTypes.shape({ + avatar: PropTypes.object.isRequired, + }), + /** + * The components used for each slot inside. + */ + slots: PropTypes.shape({ + avatar: PropTypes.elementType, + }), +} as any; + +export { AccountDetails }; diff --git a/packages/toolpad-core/src/AccountDetails/index.ts b/packages/toolpad-core/src/AccountDetails/index.ts new file mode 100644 index 00000000000..262f413926f --- /dev/null +++ b/packages/toolpad-core/src/AccountDetails/index.ts @@ -0,0 +1 @@ +export * from './AccountDetails'; diff --git a/packages/toolpad-core/src/index.ts b/packages/toolpad-core/src/index.ts index dcb98090703..422e84d0527 100644 --- a/packages/toolpad-core/src/index.ts +++ b/packages/toolpad-core/src/index.ts @@ -6,6 +6,8 @@ export * from './SignInPage'; export * from './Account'; +export * from './AccountDetails'; + export * from './PageContainer'; export * from './useActivePage'; From 429b3dc5b8bbf62f5aefc7a9937a9d50bc79021d Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 17 Oct 2024 18:24:25 +0530 Subject: [PATCH 18/28] fix: Move to completely new component architecture --- .../core/components/account/AccountCustom.js | 126 ------ .../core/components/account/AccountCustom.tsx | 133 ------- .../account/AccountCustom.tsx.preview | 22 -- .../account/AccountCustomLocaleText.js | 46 +++ .../account/AccountCustomLocaleText.tsx | 51 +++ .../AccountCustomLocaleText.tsx.preview | 6 + .../account/AccountCustomSlotProps.js | 66 ++++ .../account/AccountCustomSlotProps.tsx | 71 ++++ .../AccountCustomSlotProps.tsx.preview | 25 ++ .../account/AccountSlotsAccountSwitcher.js | 2 +- .../account/AccountSlotsAccountSwitcher.tsx | 2 +- .../AccountSlotsAccountSwitcher.tsx.preview | 2 +- ...ountSlotsInfo.js => AccountSlotsWallet.js} | 46 ++- ...ntSlotsInfo.tsx => AccountSlotsWallet.tsx} | 46 ++- ...preview => AccountSlotsWallet.tsx.preview} | 2 +- .../core/components/account/CustomMenu.js | 17 +- .../core/components/account/CustomMenu.tsx | 17 +- .../core/components/account/account.md | 41 +- docs/data/toolpad/core/pagesApi.js | 6 +- .../toolpad/core/api/account-details.json | 30 -- .../core/api/account-popover-footer.js | 23 ++ .../core/api/account-popover-footer.json | 11 + .../core/api/account-popover-header.js | 23 ++ .../core/api/account-popover-header.json | 11 + ...{account-details.js => account-preview.js} | 6 +- .../toolpad/core/api/account-preview.json | 50 +++ docs/pages/toolpad/core/api/account.json | 30 +- .../toolpad/core/api/dashboard-layout.json | 2 +- docs/pages/toolpad/core/api/sign-in-button.js | 23 ++ .../toolpad/core/api/sign-in-button.json | 369 ++++++++++++++++++ .../pages/toolpad/core/api/sign-out-button.js | 23 ++ .../toolpad/core/api/sign-out-button.json | 369 ++++++++++++++++++ .../account-details/account-details.json | 9 - .../account-popover-footer.json | 1 + .../account-popover-header.json | 1 + .../account-preview/account-preview.json | 16 + .../api-docs/account/account.json | 4 +- .../sign-in-button/sign-in-button.json | 301 ++++++++++++++ .../sign-out-button/sign-out-button.json | 301 ++++++++++++++ packages/toolpad-core/src/Account/Account.tsx | 255 ++++++------ .../src/Account/AccountPopoverFooter.tsx | 27 ++ .../src/Account/AccountPopoverHeader.tsx | 20 + .../AccountPreview.test.tsx} | 10 +- .../src/Account/AccountPreview.tsx | 181 +++++++++ .../toolpad-core/src/Account/SignInButton.tsx | 38 ++ .../src/Account/SignOutButton.tsx | 44 +++ packages/toolpad-core/src/Account/index.ts | 5 + .../src/AccountDetails/AccountDetails.tsx | 87 ----- .../toolpad-core/src/AccountDetails/index.ts | 1 - .../src/DashboardLayout/DashboardLayout.tsx | 12 +- packages/toolpad-core/src/index.ts | 2 - .../src/shared/locales/LocaleContext.tsx | 37 ++ .../toolpad-core/src/shared/locales/en.tsx | 2 + 53 files changed, 2413 insertions(+), 638 deletions(-) delete mode 100644 docs/data/toolpad/core/components/account/AccountCustom.js delete mode 100644 docs/data/toolpad/core/components/account/AccountCustom.tsx delete mode 100644 docs/data/toolpad/core/components/account/AccountCustom.tsx.preview create mode 100644 docs/data/toolpad/core/components/account/AccountCustomLocaleText.js create mode 100644 docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx create mode 100644 docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx.preview create mode 100644 docs/data/toolpad/core/components/account/AccountCustomSlotProps.js create mode 100644 docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx create mode 100644 docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx.preview rename docs/data/toolpad/core/components/account/{AccountSlotsInfo.js => AccountSlotsWallet.js} (77%) rename docs/data/toolpad/core/components/account/{AccountSlotsInfo.tsx => AccountSlotsWallet.tsx} (77%) rename docs/data/toolpad/core/components/account/{AccountSlotsInfo.tsx.preview => AccountSlotsWallet.tsx.preview} (83%) delete mode 100644 docs/pages/toolpad/core/api/account-details.json create mode 100644 docs/pages/toolpad/core/api/account-popover-footer.js create mode 100644 docs/pages/toolpad/core/api/account-popover-footer.json create mode 100644 docs/pages/toolpad/core/api/account-popover-header.js create mode 100644 docs/pages/toolpad/core/api/account-popover-header.json rename docs/pages/toolpad/core/api/{account-details.js => account-preview.js} (78%) create mode 100644 docs/pages/toolpad/core/api/account-preview.json create mode 100644 docs/pages/toolpad/core/api/sign-in-button.js create mode 100644 docs/pages/toolpad/core/api/sign-in-button.json create mode 100644 docs/pages/toolpad/core/api/sign-out-button.js create mode 100644 docs/pages/toolpad/core/api/sign-out-button.json delete mode 100644 docs/translations/api-docs/account-details/account-details.json create mode 100644 docs/translations/api-docs/account-popover-footer/account-popover-footer.json create mode 100644 docs/translations/api-docs/account-popover-header/account-popover-header.json create mode 100644 docs/translations/api-docs/account-preview/account-preview.json create mode 100644 docs/translations/api-docs/sign-in-button/sign-in-button.json create mode 100644 docs/translations/api-docs/sign-out-button/sign-out-button.json create mode 100644 packages/toolpad-core/src/Account/AccountPopoverFooter.tsx create mode 100644 packages/toolpad-core/src/Account/AccountPopoverHeader.tsx rename packages/toolpad-core/src/{AccountDetails/AccountDetails.test.tsx => Account/AccountPreview.test.tsx} (89%) create mode 100644 packages/toolpad-core/src/Account/AccountPreview.tsx create mode 100644 packages/toolpad-core/src/Account/SignInButton.tsx create mode 100644 packages/toolpad-core/src/Account/SignOutButton.tsx delete mode 100644 packages/toolpad-core/src/AccountDetails/AccountDetails.tsx delete mode 100644 packages/toolpad-core/src/AccountDetails/index.ts create mode 100644 packages/toolpad-core/src/shared/locales/LocaleContext.tsx diff --git a/docs/data/toolpad/core/components/account/AccountCustom.js b/docs/data/toolpad/core/components/account/AccountCustom.js deleted file mode 100644 index a28fc6d7756..00000000000 --- a/docs/data/toolpad/core/components/account/AccountCustom.js +++ /dev/null @@ -1,126 +0,0 @@ -import * as React from 'react'; -import Typography from '@mui/material/Typography'; -import { Account, AuthenticationContext, SessionContext } from '@toolpad/core'; - -const demoSession = { - user: { - name: 'Bharat Kashyap', - email: 'bharatkashyap@outlook.com', - image: 'https://avatars.githubusercontent.com/u/19550456', - }, -}; - -export default function AccountCustom() { - const [session, setSession] = React.useState(demoSession); - const [signedOutSession, setSignedOutSession] = React.useState(null); - - const authenticationSignedIn = React.useMemo(() => { - return { - signIn: () => { - setSession({ - user: { - name: 'Bharat Kashyap', - email: 'bharatkashyap@outlook.com', - image: 'https://avatars.githubusercontent.com/u/19550456', - }, - }); - }, - signOut: () => { - setSession(null); - setSignedOutSession(null); - }, - }; - }, []); - - const authenticationSignedOut = React.useMemo(() => { - return { - signIn: () => { - setSignedOutSession(demoSession); - }, - signOut: () => { - setSignedOutSession(null); - }, - }; - }, []); - - return ( -
- - - Signed in - - - - - - - Signed out - - - - - {/* preview-start */} - - {/* preview-end */} - - -
- ); -} diff --git a/docs/data/toolpad/core/components/account/AccountCustom.tsx b/docs/data/toolpad/core/components/account/AccountCustom.tsx deleted file mode 100644 index 9bc161b8c96..00000000000 --- a/docs/data/toolpad/core/components/account/AccountCustom.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import * as React from 'react'; -import Typography from '@mui/material/Typography'; -import { - Account, - AuthenticationContext, - SessionContext, - Session, -} from '@toolpad/core'; - -const demoSession = { - user: { - name: 'Bharat Kashyap', - email: 'bharatkashyap@outlook.com', - image: 'https://avatars.githubusercontent.com/u/19550456', - }, -}; - -export default function AccountCustom() { - const [session, setSession] = React.useState(demoSession); - const [signedOutSession, setSignedOutSession] = React.useState( - null, - ); - - const authenticationSignedIn = React.useMemo(() => { - return { - signIn: () => { - setSession({ - user: { - name: 'Bharat Kashyap', - email: 'bharatkashyap@outlook.com', - image: 'https://avatars.githubusercontent.com/u/19550456', - }, - }); - }, - signOut: () => { - setSession(null); - setSignedOutSession(null); - }, - }; - }, []); - - const authenticationSignedOut = React.useMemo(() => { - return { - signIn: () => { - setSignedOutSession(demoSession); - }, - signOut: () => { - setSignedOutSession(null); - }, - }; - }, []); - - return ( -
- - - Signed in - - - - - - - Signed out - - - - - {/* preview-start */} - - {/* preview-end */} - - -
- ); -} diff --git a/docs/data/toolpad/core/components/account/AccountCustom.tsx.preview b/docs/data/toolpad/core/components/account/AccountCustom.tsx.preview deleted file mode 100644 index 1143a6ea501..00000000000 --- a/docs/data/toolpad/core/components/account/AccountCustom.tsx.preview +++ /dev/null @@ -1,22 +0,0 @@ - \ No newline at end of file diff --git a/docs/data/toolpad/core/components/account/AccountCustomLocaleText.js b/docs/data/toolpad/core/components/account/AccountCustomLocaleText.js new file mode 100644 index 00000000000..b902a11f37a --- /dev/null +++ b/docs/data/toolpad/core/components/account/AccountCustomLocaleText.js @@ -0,0 +1,46 @@ +import * as React from 'react'; +import { Account, AuthenticationContext, SessionContext } from '@toolpad/core'; + +const demoSession = { + user: { + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + }, +}; + +export default function AccountCustomLocaleText() { + const [session, setSession] = React.useState(demoSession); + + const authentication = React.useMemo(() => { + return { + signIn: () => { + setSession({ + user: { + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + }, + }); + }, + signOut: () => { + setSession(null); + }, + }; + }, []); + + return ( + + + {/* preview-start */} + + {/* preview-end */} + + + ); +} diff --git a/docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx b/docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx new file mode 100644 index 00000000000..4054145ff3d --- /dev/null +++ b/docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; +import { + Account, + AuthenticationContext, + SessionContext, + Session, +} from '@toolpad/core'; + +const demoSession = { + user: { + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + }, +}; + +export default function AccountCustomLocaleText() { + const [session, setSession] = React.useState(demoSession); + + const authentication = React.useMemo(() => { + return { + signIn: () => { + setSession({ + user: { + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + }, + }); + }, + signOut: () => { + setSession(null); + }, + }; + }, []); + + return ( + + + {/* preview-start */} + + {/* preview-end */} + + + ); +} diff --git a/docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx.preview b/docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx.preview new file mode 100644 index 00000000000..882b98486be --- /dev/null +++ b/docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx.preview @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/docs/data/toolpad/core/components/account/AccountCustomSlotProps.js b/docs/data/toolpad/core/components/account/AccountCustomSlotProps.js new file mode 100644 index 00000000000..fc680952444 --- /dev/null +++ b/docs/data/toolpad/core/components/account/AccountCustomSlotProps.js @@ -0,0 +1,66 @@ +import * as React from 'react'; +import Logout from '@mui/icons-material/Logout'; +import { Account, AuthenticationContext, SessionContext } from '@toolpad/core'; + +const demoSession = { + user: { + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + }, +}; + +export default function AccountCustomSlotProps() { + const [session, setSession] = React.useState(demoSession); + + const authentication = React.useMemo(() => { + return { + signIn: () => { + setSession({ + user: { + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + }, + }); + }, + signOut: () => { + setSession(null); + }, + }; + }, []); + + return ( + + + {/* preview-start */} + , + }, + preview: { + variant: 'expanded', + slotProps: { + avatarIconButton: { + sx: { + width: 'fit-content', + margin: 'auto', + }, + }, + avatar: { + variant: 'rounded', + }, + }, + }, + }} + /> + {/* preview-end */} + + + ); +} diff --git a/docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx b/docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx new file mode 100644 index 00000000000..028be4c62b5 --- /dev/null +++ b/docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx @@ -0,0 +1,71 @@ +import * as React from 'react'; +import Logout from '@mui/icons-material/Logout'; +import { + Account, + AuthenticationContext, + SessionContext, + Session, +} from '@toolpad/core'; + +const demoSession = { + user: { + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + }, +}; + +export default function AccountCustomSlotProps() { + const [session, setSession] = React.useState(demoSession); + + const authentication = React.useMemo(() => { + return { + signIn: () => { + setSession({ + user: { + name: 'Bharat Kashyap', + email: 'bharatkashyap@outlook.com', + image: 'https://avatars.githubusercontent.com/u/19550456', + }, + }); + }, + signOut: () => { + setSession(null); + }, + }; + }, []); + + return ( + + + {/* preview-start */} + , + }, + preview: { + variant: 'expanded', + slotProps: { + avatarIconButton: { + sx: { + width: 'fit-content', + margin: 'auto', + }, + }, + avatar: { + variant: 'rounded', + }, + }, + }, + }} + /> + {/* preview-end */} + + + ); +} diff --git a/docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx.preview b/docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx.preview new file mode 100644 index 00000000000..2730a8c4c9b --- /dev/null +++ b/docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx.preview @@ -0,0 +1,25 @@ +, + }, + preview: { + variant: 'expanded', + slotProps: { + avatarIconButton: { + sx: { + width: 'fit-content', + margin: 'auto', + }, + }, + avatar: { + variant: 'rounded', + }, + }, + }, + }} +/> \ No newline at end of file diff --git a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js index 97b3aa14b99..69f05bdcb2d 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js +++ b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js @@ -28,7 +28,7 @@ export default function AccountSlotsAccountSwitcher() { diff --git a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx index ea03da06080..1542d48bc8f 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx +++ b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx @@ -33,7 +33,7 @@ export default function AccountSlotsAccountSwitcher() { diff --git a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview index 18a06d57ca7..6dd2f4d2c70 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview +++ b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview @@ -2,7 +2,7 @@ diff --git a/docs/data/toolpad/core/components/account/AccountSlotsInfo.js b/docs/data/toolpad/core/components/account/AccountSlotsWallet.js similarity index 77% rename from docs/data/toolpad/core/components/account/AccountSlotsInfo.js rename to docs/data/toolpad/core/components/account/AccountSlotsWallet.js index 5933ee187bc..9f75276879b 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsInfo.js +++ b/docs/data/toolpad/core/components/account/AccountSlotsWallet.js @@ -14,10 +14,12 @@ import CopyIcon from '@mui/icons-material/ContentCopy'; import { Account, - AccountDetails, + AccountPreview, AuthenticationContext, SessionContext, + SignOutButton, } from '@toolpad/core'; +import { AccountPopoverFooter } from '../../../../../../packages/toolpad-core/src/Account/AccountPopoverFooter'; const demoSession = { user: { @@ -36,7 +38,7 @@ const mockData = { function CryptoWalletInfo() { return ( - + @@ -76,32 +78,28 @@ function CryptoWalletInfo() { {mockData.usdBalance} - - - - - + + + + + + ); } -export default function AccountSlotsInfo() { +export default function AccountSlotsWallet() { const [session, setSession] = React.useState(demoSession); const authentication = React.useMemo(() => { return { @@ -119,7 +117,7 @@ export default function AccountSlotsInfo() { diff --git a/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx b/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx similarity index 77% rename from docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx rename to docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx index c68f837d08f..3a4a5ff96e2 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx +++ b/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx @@ -14,11 +14,13 @@ import CopyIcon from '@mui/icons-material/ContentCopy'; import { Account, - AccountDetails, + AccountPreview, AuthenticationContext, SessionContext, Session, + SignOutButton, } from '@toolpad/core'; +import { AccountPopoverFooter } from '../../../../../../packages/toolpad-core/src/Account/AccountPopoverFooter'; const demoSession = { user: { @@ -37,7 +39,7 @@ const mockData = { function CryptoWalletInfo() { return ( - + @@ -77,32 +79,28 @@ function CryptoWalletInfo() { {mockData.usdBalance} - - - - - + + + + + + ); } -export default function AccountSlotsInfo() { +export default function AccountSlotsWallet() { const [session, setSession] = React.useState(demoSession); const authentication = React.useMemo(() => { return { @@ -120,7 +118,7 @@ export default function AccountSlotsInfo() { diff --git a/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx.preview b/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx.preview similarity index 83% rename from docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx.preview rename to docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx.preview index 29ceba32bb0..7241ae7a264 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsInfo.tsx.preview +++ b/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx.preview @@ -2,7 +2,7 @@ diff --git a/docs/data/toolpad/core/components/account/CustomMenu.js b/docs/data/toolpad/core/components/account/CustomMenu.js index 9637ac5c1a0..e6aa0bd65cc 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.js +++ b/docs/data/toolpad/core/components/account/CustomMenu.js @@ -12,9 +12,10 @@ import { Avatar, Stack, } from '@mui/material'; -import { AccountDetails } from '@toolpad/core'; +import { AccountPreview, SignOutButton } from '@toolpad/core'; import FolderIcon from '@mui/icons-material/Folder'; import AddIcon from '@mui/icons-material/Add'; +import { AccountPopoverFooter } from '../../../../../../packages/toolpad-core/src/Account/AccountPopoverFooter'; const accounts = [ { @@ -176,12 +177,12 @@ export default function CustomMenu() { return ( - + - - - Accounts - + + Accounts + + {accounts.map((account) => ( + + + + ); } diff --git a/docs/data/toolpad/core/components/account/CustomMenu.tsx b/docs/data/toolpad/core/components/account/CustomMenu.tsx index b0f2c2418c3..200ca474361 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.tsx +++ b/docs/data/toolpad/core/components/account/CustomMenu.tsx @@ -11,9 +11,10 @@ import { Avatar, Stack, } from '@mui/material'; -import { AccountDetails } from '@toolpad/core'; +import { AccountPreview, SignOutButton } from '@toolpad/core'; import FolderIcon from '@mui/icons-material/Folder'; import AddIcon from '@mui/icons-material/Add'; +import { AccountPopoverFooter } from '../../../../../../packages/toolpad-core/src/Account/AccountPopoverFooter'; interface Project { id: number; @@ -176,12 +177,12 @@ export default function CustomMenu() { return ( - + - - - Accounts - + + Accounts + + {accounts.map((account) => ( + + + + ); } diff --git a/docs/data/toolpad/core/components/account/account.md b/docs/data/toolpad/core/components/account/account.md index e3b6a65720e..34a901289a1 100644 --- a/docs/data/toolpad/core/components/account/account.md +++ b/docs/data/toolpad/core/components/account/account.md @@ -1,7 +1,7 @@ --- productId: toolpad-core title: Account -components: Account, AccountDetails +components: Account, AccountPreview, AccountPopoverHeader, AccountPopoverFooter, SignInButton, SignOutButton --- # Account @@ -30,28 +30,45 @@ When signed out, the component renders as an inline sign in button within the da ## Customization +The `` component is composed of multiple sub-components: + +- `` +- `` +- `` +- `` + +You can pass extra props to them through the `slotProps` prop on the `` component. You may also completely override them by passing your own custom components to `` through the `slots` prop. + +The labels can be customized through the `localeText` prop. + ### Slot Props -The underlying `signInButton`, `signOutButton` and `iconButton` components can be customized by passing in `slotProps` to the `Account` component. +The `AccountPreview` component has two variants, `condensed` (the default) and `expanded`. You can change the variant used inside `` by passing in custom props through `slotProps`: -Labels for the sign in and sign out buttons can be customized through the `localeText` prop. +{{"demo": "AccountCustomSlotProps.js", "bg": "outlined" }} -{{"demo": "AccountCustom.js", "bg": "outlined" }} +### Labels + +You can pass in custom labels – including of different languages – using the `localeText` prop. + +{{"demo": "AccountCustomLocaleText.js", "bg": "outlined" }} ### Slots -You can pass in your own components to completely override the default components inside the `Account` popover through the `slots` prop. +You can pass in your own components inside the `Account` popover through the `slots` prop. -#### Content +#### Popover Content -Use the `content` slot to customize the entire content of the account popover. If you want to continue using the default account details section along with your custom content, you can use the `AccountDetails` component exported by `@toolpad/core` in your custom component: +You can wrap the default sub-components – such as `SignOutButton` and `AccountPreview` – and wrap them in `AccountPopoverHeader` and `AccountPopoverFooter` components to create custom account popovers, as shown in the following demos: -##### Account Switcher +##### Crypto Wallet -{{"demo": "AccountSlotsAccountSwitcher.js", "bg": "outlined"}} +You can wrap the default `SignOutButton` with your own action buttons inside `AccountPopoverFooter` to customize the popover footer section: -The `content` prop can take any React component, so you can use it to display information instead of adding menu items: +{{"demo": "AccountSlotsWallet.js", "bg": "outlined" }} -##### Crypto Wallet +##### Account Switcher + +You can build advanced menus – such as a tenant switcher – by passing in a component that wraps `AccountPreview` and `SignOutButton` with a custom menu: -{{"demo": "AccountSlotsInfo.js", "bg": "outlined" }} +{{"demo": "AccountSlotsAccountSwitcher.js", "bg": "outlined"}} diff --git a/docs/data/toolpad/core/pagesApi.js b/docs/data/toolpad/core/pagesApi.js index 31c5d67e954..ea749c0aff6 100644 --- a/docs/data/toolpad/core/pagesApi.js +++ b/docs/data/toolpad/core/pagesApi.js @@ -1,11 +1,15 @@ module.exports = [ { pathname: '/toolpad/core/api/account' }, - { pathname: '/toolpad/core/api/account-details' }, + { pathname: '/toolpad/core/api/account-popover-footer' }, + { pathname: '/toolpad/core/api/account-popover-header' }, + { pathname: '/toolpad/core/api/account-preview' }, { pathname: '/toolpad/core/api/app-provider' }, { pathname: '/toolpad/core/api/dashboard-layout' }, { pathname: '/toolpad/core/api/dialogs-provider' }, { pathname: '/toolpad/core/api/notifications-provider' }, { pathname: '/toolpad/core/api/page-container' }, { pathname: '/toolpad/core/api/page-container-toolbar' }, + { pathname: '/toolpad/core/api/sign-in-button' }, { pathname: '/toolpad/core/api/sign-in-page' }, + { pathname: '/toolpad/core/api/sign-out-button' }, ]; diff --git a/docs/pages/toolpad/core/api/account-details.json b/docs/pages/toolpad/core/api/account-details.json deleted file mode 100644 index 3aedce76907..00000000000 --- a/docs/pages/toolpad/core/api/account-details.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "props": { - "slotProps": { "type": { "name": "shape", "description": "{ avatar: object }" } }, - "slots": { - "type": { "name": "shape", "description": "{ avatar?: elementType }" }, - "additionalInfo": { "slotsApi": true } - } - }, - "name": "AccountDetails", - "imports": [ - "import { AccountDetails } from '@toolpad/core/AccountDetails';", - "import { AccountDetails } from '@toolpad/core';" - ], - "slots": [ - { - "name": "avatar", - "description": "The component used for the Avatar", - "default": "Avatar", - "class": null - } - ], - "classes": [], - "spread": true, - "themeDefaultProps": false, - "muiName": "AccountDetails", - "filename": "/packages/toolpad-core/src/AccountDetails/AccountDetails.tsx", - "inheritance": null, - "demos": "", - "cssComponent": false -} diff --git a/docs/pages/toolpad/core/api/account-popover-footer.js b/docs/pages/toolpad/core/api/account-popover-footer.js new file mode 100644 index 00000000000..c3052dec403 --- /dev/null +++ b/docs/pages/toolpad/core/api/account-popover-footer.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './account-popover-footer.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docs-toolpad/translations/api-docs/account-popover-footer', + false, + /\.\/account-popover-footer.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/toolpad/core/api/account-popover-footer.json b/docs/pages/toolpad/core/api/account-popover-footer.json new file mode 100644 index 00000000000..4d4b4d99d00 --- /dev/null +++ b/docs/pages/toolpad/core/api/account-popover-footer.json @@ -0,0 +1,11 @@ +{ + "props": {}, + "name": "AccountPopoverFooter", + "imports": ["import { AccountPopoverFooter } from '@toolpad/core/Account';"], + "classes": [], + "muiName": "AccountPopoverFooter", + "filename": "/packages/toolpad-core/src/Account/AccountPopoverFooter.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/toolpad/core/api/account-popover-header.js b/docs/pages/toolpad/core/api/account-popover-header.js new file mode 100644 index 00000000000..4206c8ca54a --- /dev/null +++ b/docs/pages/toolpad/core/api/account-popover-header.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './account-popover-header.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docs-toolpad/translations/api-docs/account-popover-header', + false, + /\.\/account-popover-header.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/toolpad/core/api/account-popover-header.json b/docs/pages/toolpad/core/api/account-popover-header.json new file mode 100644 index 00000000000..e2ec37ec671 --- /dev/null +++ b/docs/pages/toolpad/core/api/account-popover-header.json @@ -0,0 +1,11 @@ +{ + "props": {}, + "name": "AccountPopoverHeader", + "imports": ["import { AccountPopoverHeader } from '@toolpad/core/Account';"], + "classes": [], + "muiName": "AccountPopoverHeader", + "filename": "/packages/toolpad-core/src/Account/AccountPopoverHeader.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/toolpad/core/api/account-details.js b/docs/pages/toolpad/core/api/account-preview.js similarity index 78% rename from docs/pages/toolpad/core/api/account-details.js rename to docs/pages/toolpad/core/api/account-preview.js index 6d691ade852..44cb65528d1 100644 --- a/docs/pages/toolpad/core/api/account-details.js +++ b/docs/pages/toolpad/core/api/account-preview.js @@ -1,7 +1,7 @@ import * as React from 'react'; import ApiPage from 'docs/src/modules/components/ApiPage'; import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; -import jsonPageContent from './account-details.json'; +import jsonPageContent from './account-preview.json'; export default function Page(props) { const { descriptions, pageContent } = props; @@ -10,9 +10,9 @@ export default function Page(props) { Page.getInitialProps = () => { const req = require.context( - 'docs-toolpad/translations/api-docs/account-details', + 'docs-toolpad/translations/api-docs/account-preview', false, - /\.\/account-details.*.json$/, + /\.\/account-preview.*.json$/, ); const descriptions = mapApiPageTranslations(req); diff --git a/docs/pages/toolpad/core/api/account-preview.json b/docs/pages/toolpad/core/api/account-preview.json new file mode 100644 index 00000000000..c9d8aa4e912 --- /dev/null +++ b/docs/pages/toolpad/core/api/account-preview.json @@ -0,0 +1,50 @@ +{ + "props": { + "handleClick": { "type": { "name": "func" } }, + "open": { "type": { "name": "bool" }, "default": "false" }, + "slotProps": { + "type": { + "name": "shape", + "description": "{ avatar?: object, avatarIconButton?: object, moreIconButton?: object }" + } + }, + "slots": { + "type": { "name": "shape", "description": "{ avatar?: elementType }" }, + "additionalInfo": { "slotsApi": true } + }, + "variant": { + "type": { "name": "enum", "description": "'condensed'
| 'expanded'" }, + "default": "'condensed'" + } + }, + "name": "AccountPreview", + "imports": ["import { AccountPreview } from '@toolpad/core/Account';"], + "slots": [ + { + "name": "avatar", + "description": "The component used for the Avatar", + "default": "Avatar", + "class": null + }, + { + "name": "moreIconButton", + "description": "The component used for the overflow icon button in the expanded variant", + "default": "IconButton", + "class": null + }, + { + "name": "avatarIconButton", + "description": "The component used for the avatar icon button in the condensed variant", + "default": "IconButton", + "class": null + } + ], + "classes": [], + "spread": true, + "themeDefaultProps": false, + "muiName": "AccountPreview", + "filename": "/packages/toolpad-core/src/Account/AccountPreview.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/toolpad/core/api/account.json b/docs/pages/toolpad/core/api/account.json index fa8fa88afa2..3c263c99ff6 100644 --- a/docs/pages/toolpad/core/api/account.json +++ b/docs/pages/toolpad/core/api/account.json @@ -1,19 +1,21 @@ { "props": { "localeText": { - "type": { "name": "shape", "description": "{ signInLabel: string, signOutLabel: string }" }, - "default": "DEFAULT_LOCALE_TEXT" + "type": { + "name": "shape", + "description": "{ iconButtonAriaLabel?: string, signInLabel?: string, signOutLabel?: string }" + } }, "slotProps": { "type": { "name": "shape", - "description": "{ iconButton?: object, signInButton?: object, signOutButton?: object }" + "description": "{ popover?: object, preview?: { handleClick?: func, open?: bool, slotProps?: { avatar?: object, avatarIconButton?: object, moreIconButton?: object }, slots?: { avatar?: elementType, avatarIconButton?: elementType, moreIconButton?: elementType }, variant?: 'condensed'
| 'expanded' }, signInButton?: object, signOutButton?: object }" } }, "slots": { "type": { "name": "shape", - "description": "{ content?: elementType, iconButton?: elementType, signInButton?: elementType, signOutButton?: elementType }" + "description": "{ popoverContent?: elementType, preview?: elementType, signInButton?: elementType, signOutButton?: elementType }" }, "additionalInfo": { "slotsApi": true } } @@ -25,9 +27,15 @@ ], "slots": [ { - "name": "iconButton", - "description": "The component used for the icon button", - "default": "IconButton", + "name": "preview", + "description": "The component used for the account preview", + "default": "AccountPreview", + "class": null + }, + { + "name": "popoverContent", + "description": "The component used for the content of account popover", + "default": "Popover", "class": null }, { @@ -39,13 +47,7 @@ { "name": "signOutButton", "description": "The component used for the sign out button.", - "default": "MenuItem", - "class": null - }, - { - "name": "content", - "description": "The component used for the content of the popover", - "default": "null", + "default": "Button", "class": null } ], diff --git a/docs/pages/toolpad/core/api/dashboard-layout.json b/docs/pages/toolpad/core/api/dashboard-layout.json index 0e960377a81..350223f0779 100644 --- a/docs/pages/toolpad/core/api/dashboard-layout.json +++ b/docs/pages/toolpad/core/api/dashboard-layout.json @@ -6,7 +6,7 @@ "slotProps": { "type": { "name": "shape", - "description": "{ sidebarFooter?: { mini: bool }, toolbarAccount?: { localeText?: { signInLabel: string, signOutLabel: string }, slotProps?: { iconButton?: object, signInButton?: object, signOutButton?: object }, slots?: { content?: elementType, iconButton?: elementType, signInButton?: elementType, signOutButton?: elementType } }, toolbarActions?: object }" + "description": "{ sidebarFooter?: { mini: bool }, toolbarAccount?: { localeText?: { iconButtonAriaLabel?: string, signInLabel?: string, signOutLabel?: string }, slotProps?: { popover?: object, preview?: object, signInButton?: object, signOutButton?: object }, slots?: { popoverContent?: elementType, preview?: elementType, signInButton?: elementType, signOutButton?: elementType } }, toolbarActions?: object }" }, "default": "{}" }, diff --git a/docs/pages/toolpad/core/api/sign-in-button.js b/docs/pages/toolpad/core/api/sign-in-button.js new file mode 100644 index 00000000000..aab4d5111ca --- /dev/null +++ b/docs/pages/toolpad/core/api/sign-in-button.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './sign-in-button.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docs-toolpad/translations/api-docs/sign-in-button', + false, + /\.\/sign-in-button.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/toolpad/core/api/sign-in-button.json b/docs/pages/toolpad/core/api/sign-in-button.json new file mode 100644 index 00000000000..72ccc67fc4a --- /dev/null +++ b/docs/pages/toolpad/core/api/sign-in-button.json @@ -0,0 +1,369 @@ +{ + "props": {}, + "name": "SignInButton", + "imports": ["import { SignInButton } from '@toolpad/core/Account';"], + "classes": [ + { + "key": "colorError", + "className": "", + "description": "Styles applied to the root element if `color=\"error\"`.", + "isGlobal": false + }, + { + "key": "colorInfo", + "className": "", + "description": "Styles applied to the root element if `color=\"info\"`.", + "isGlobal": false + }, + { + "key": "colorInherit", + "className": "", + "description": "Styles applied to the root element if `color=\"inherit\"`.", + "isGlobal": false + }, + { + "key": "colorPrimary", + "className": "", + "description": "Styles applied to the root element if `color=\"primary\"`.", + "isGlobal": false + }, + { + "key": "colorSecondary", + "className": "", + "description": "Styles applied to the root element if `color=\"secondary\"`.", + "isGlobal": false + }, + { + "key": "colorSuccess", + "className": "", + "description": "Styles applied to the root element if `color=\"success\"`.", + "isGlobal": false + }, + { + "key": "colorWarning", + "className": "", + "description": "Styles applied to the root element if `color=\"warning\"`.", + "isGlobal": false + }, + { + "key": "contained", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"`.", + "isGlobal": false + }, + { + "key": "containedError", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"error\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedInfo", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"info\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedInherit", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"inherit\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedPrimary", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"primary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedSecondary", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"secondary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedSizeLarge", + "className": "", + "description": "Styles applied to the root element if `size=\"large\"` and `variant=\"contained\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedSizeMedium", + "className": "", + "description": "Styles applied to the root element if `size=\"medium\"` and `variant=\"contained\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedSizeSmall", + "className": "", + "description": "Styles applied to the root element if `size=\"small\"` and `variant=\"contained\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedSuccess", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"success\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedWarning", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"warning\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "disabled", + "className": "", + "description": "State class applied to the root element if `disabled={true}`.", + "isGlobal": false + }, + { + "key": "disableElevation", + "className": "", + "description": "Styles applied to the root element if `disableElevation={true}`.", + "isGlobal": false + }, + { + "key": "endIcon", + "className": "", + "description": "Styles applied to the endIcon element if supplied.", + "isGlobal": false + }, + { + "key": "focusVisible", + "className": "", + "description": "State class applied to the ButtonBase root element if the button is keyboard focused.", + "isGlobal": false + }, + { + "key": "fullWidth", + "className": "", + "description": "Styles applied to the root element if `fullWidth={true}`.", + "isGlobal": false + }, + { + "key": "icon", + "className": "", + "description": "Styles applied to the icon element if supplied", + "isGlobal": false + }, + { + "key": "iconSizeLarge", + "className": "", + "description": "Styles applied to the icon element if supplied and `size=\"large\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "iconSizeMedium", + "className": "", + "description": "Styles applied to the icon element if supplied and `size=\"medium\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "iconSizeSmall", + "className": "", + "description": "Styles applied to the icon element if supplied and `size=\"small\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlined", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"`.", + "isGlobal": false + }, + { + "key": "outlinedError", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"error\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedInfo", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"info\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedInherit", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"inherit\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedPrimary", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"primary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedSecondary", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"secondary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedSizeLarge", + "className": "", + "description": "Styles applied to the root element if `size=\"large\"` and `variant=\"outlined\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedSizeMedium", + "className": "", + "description": "Styles applied to the root element if `size=\"medium\"` and `variant=\"outlined\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedSizeSmall", + "className": "", + "description": "Styles applied to the root element if `size=\"small\"` and `variant=\"outlined\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedSuccess", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"success\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedWarning", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"warning\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "root", + "className": "", + "description": "Styles applied to the root element.", + "isGlobal": false + }, + { + "key": "sizeLarge", + "className": "", + "description": "Styles applied to the root element if `size=\"large\"`.", + "isGlobal": false + }, + { + "key": "sizeMedium", + "className": "", + "description": "Styles applied to the root element if `size=\"medium\"`.", + "isGlobal": false + }, + { + "key": "sizeSmall", + "className": "", + "description": "Styles applied to the root element if `size=\"small\"`.", + "isGlobal": false + }, + { + "key": "startIcon", + "className": "", + "description": "Styles applied to the startIcon element if supplied.", + "isGlobal": false + }, + { + "key": "text", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"`.", + "isGlobal": false + }, + { + "key": "textError", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"error\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textInfo", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"info\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textInherit", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"inherit\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textPrimary", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"primary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textSecondary", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"secondary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textSizeLarge", + "className": "", + "description": "Styles applied to the root element if `size=\"large\"` and `variant=\"text\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textSizeMedium", + "className": "", + "description": "Styles applied to the root element if `size=\"medium\"` and `variant=\"text\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textSizeSmall", + "className": "", + "description": "Styles applied to the root element if `size=\"small\"` and `variant=\"text\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textSuccess", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"success\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textWarning", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"warning\"`.", + "isGlobal": false, + "isDeprecated": true + } + ], + "muiName": "SignInButton", + "filename": "/packages/toolpad-core/src/Account/SignInButton.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/toolpad/core/api/sign-out-button.js b/docs/pages/toolpad/core/api/sign-out-button.js new file mode 100644 index 00000000000..8f0e9e7e8fe --- /dev/null +++ b/docs/pages/toolpad/core/api/sign-out-button.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './sign-out-button.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docs-toolpad/translations/api-docs/sign-out-button', + false, + /\.\/sign-out-button.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/toolpad/core/api/sign-out-button.json b/docs/pages/toolpad/core/api/sign-out-button.json new file mode 100644 index 00000000000..9305dc4de49 --- /dev/null +++ b/docs/pages/toolpad/core/api/sign-out-button.json @@ -0,0 +1,369 @@ +{ + "props": {}, + "name": "SignOutButton", + "imports": ["import { SignOutButton } from '@toolpad/core/Account';"], + "classes": [ + { + "key": "colorError", + "className": "", + "description": "Styles applied to the root element if `color=\"error\"`.", + "isGlobal": false + }, + { + "key": "colorInfo", + "className": "", + "description": "Styles applied to the root element if `color=\"info\"`.", + "isGlobal": false + }, + { + "key": "colorInherit", + "className": "", + "description": "Styles applied to the root element if `color=\"inherit\"`.", + "isGlobal": false + }, + { + "key": "colorPrimary", + "className": "", + "description": "Styles applied to the root element if `color=\"primary\"`.", + "isGlobal": false + }, + { + "key": "colorSecondary", + "className": "", + "description": "Styles applied to the root element if `color=\"secondary\"`.", + "isGlobal": false + }, + { + "key": "colorSuccess", + "className": "", + "description": "Styles applied to the root element if `color=\"success\"`.", + "isGlobal": false + }, + { + "key": "colorWarning", + "className": "", + "description": "Styles applied to the root element if `color=\"warning\"`.", + "isGlobal": false + }, + { + "key": "contained", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"`.", + "isGlobal": false + }, + { + "key": "containedError", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"error\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedInfo", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"info\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedInherit", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"inherit\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedPrimary", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"primary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedSecondary", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"secondary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedSizeLarge", + "className": "", + "description": "Styles applied to the root element if `size=\"large\"` and `variant=\"contained\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedSizeMedium", + "className": "", + "description": "Styles applied to the root element if `size=\"medium\"` and `variant=\"contained\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedSizeSmall", + "className": "", + "description": "Styles applied to the root element if `size=\"small\"` and `variant=\"contained\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedSuccess", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"success\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "containedWarning", + "className": "", + "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"warning\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "disabled", + "className": "", + "description": "State class applied to the root element if `disabled={true}`.", + "isGlobal": false + }, + { + "key": "disableElevation", + "className": "", + "description": "Styles applied to the root element if `disableElevation={true}`.", + "isGlobal": false + }, + { + "key": "endIcon", + "className": "", + "description": "Styles applied to the endIcon element if supplied.", + "isGlobal": false + }, + { + "key": "focusVisible", + "className": "", + "description": "State class applied to the ButtonBase root element if the button is keyboard focused.", + "isGlobal": false + }, + { + "key": "fullWidth", + "className": "", + "description": "Styles applied to the root element if `fullWidth={true}`.", + "isGlobal": false + }, + { + "key": "icon", + "className": "", + "description": "Styles applied to the icon element if supplied", + "isGlobal": false + }, + { + "key": "iconSizeLarge", + "className": "", + "description": "Styles applied to the icon element if supplied and `size=\"large\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "iconSizeMedium", + "className": "", + "description": "Styles applied to the icon element if supplied and `size=\"medium\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "iconSizeSmall", + "className": "", + "description": "Styles applied to the icon element if supplied and `size=\"small\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlined", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"`.", + "isGlobal": false + }, + { + "key": "outlinedError", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"error\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedInfo", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"info\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedInherit", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"inherit\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedPrimary", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"primary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedSecondary", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"secondary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedSizeLarge", + "className": "", + "description": "Styles applied to the root element if `size=\"large\"` and `variant=\"outlined\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedSizeMedium", + "className": "", + "description": "Styles applied to the root element if `size=\"medium\"` and `variant=\"outlined\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedSizeSmall", + "className": "", + "description": "Styles applied to the root element if `size=\"small\"` and `variant=\"outlined\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedSuccess", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"success\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "outlinedWarning", + "className": "", + "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"warning\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "root", + "className": "", + "description": "Styles applied to the root element.", + "isGlobal": false + }, + { + "key": "sizeLarge", + "className": "", + "description": "Styles applied to the root element if `size=\"large\"`.", + "isGlobal": false + }, + { + "key": "sizeMedium", + "className": "", + "description": "Styles applied to the root element if `size=\"medium\"`.", + "isGlobal": false + }, + { + "key": "sizeSmall", + "className": "", + "description": "Styles applied to the root element if `size=\"small\"`.", + "isGlobal": false + }, + { + "key": "startIcon", + "className": "", + "description": "Styles applied to the startIcon element if supplied.", + "isGlobal": false + }, + { + "key": "text", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"`.", + "isGlobal": false + }, + { + "key": "textError", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"error\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textInfo", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"info\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textInherit", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"inherit\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textPrimary", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"primary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textSecondary", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"secondary\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textSizeLarge", + "className": "", + "description": "Styles applied to the root element if `size=\"large\"` and `variant=\"text\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textSizeMedium", + "className": "", + "description": "Styles applied to the root element if `size=\"medium\"` and `variant=\"text\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textSizeSmall", + "className": "", + "description": "Styles applied to the root element if `size=\"small\"` and `variant=\"text\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textSuccess", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"success\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "textWarning", + "className": "", + "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"warning\"`.", + "isGlobal": false, + "isDeprecated": true + } + ], + "muiName": "SignOutButton", + "filename": "/packages/toolpad-core/src/Account/SignOutButton.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/translations/api-docs/account-details/account-details.json b/docs/translations/api-docs/account-details/account-details.json deleted file mode 100644 index 64306d52dd6..00000000000 --- a/docs/translations/api-docs/account-details/account-details.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "componentDescription": "", - "propDescriptions": { - "slotProps": { "description": "The props used for each slot inside." }, - "slots": { "description": "The components used for each slot inside." } - }, - "classDescriptions": {}, - "slotDescriptions": { "avatar": "The component used for the Avatar" } -} diff --git a/docs/translations/api-docs/account-popover-footer/account-popover-footer.json b/docs/translations/api-docs/account-popover-footer/account-popover-footer.json new file mode 100644 index 00000000000..f93d4cbd8c7 --- /dev/null +++ b/docs/translations/api-docs/account-popover-footer/account-popover-footer.json @@ -0,0 +1 @@ +{ "componentDescription": "", "propDescriptions": {}, "classDescriptions": {} } diff --git a/docs/translations/api-docs/account-popover-header/account-popover-header.json b/docs/translations/api-docs/account-popover-header/account-popover-header.json new file mode 100644 index 00000000000..f93d4cbd8c7 --- /dev/null +++ b/docs/translations/api-docs/account-popover-header/account-popover-header.json @@ -0,0 +1 @@ +{ "componentDescription": "", "propDescriptions": {}, "classDescriptions": {} } diff --git a/docs/translations/api-docs/account-preview/account-preview.json b/docs/translations/api-docs/account-preview/account-preview.json new file mode 100644 index 00000000000..8724209a3a9 --- /dev/null +++ b/docs/translations/api-docs/account-preview/account-preview.json @@ -0,0 +1,16 @@ +{ + "componentDescription": "The AccountPreview component displays user account information.", + "propDescriptions": { + "handleClick": { "description": "The handler used when the preview is expanded" }, + "open": { "description": "The state of the Account popover" }, + "slotProps": { "description": "The props used for each slot inside." }, + "slots": { "description": "The components used for each slot inside." }, + "variant": { "description": "The type of account details to display." } + }, + "classDescriptions": {}, + "slotDescriptions": { + "avatar": "The component used for the Avatar", + "avatarIconButton": "The component used for the avatar icon button in the condensed variant", + "moreIconButton": "The component used for the overflow icon button in the expanded variant" + } +} diff --git a/docs/translations/api-docs/account/account.json b/docs/translations/api-docs/account/account.json index 81044437ff1..49e8459811b 100644 --- a/docs/translations/api-docs/account/account.json +++ b/docs/translations/api-docs/account/account.json @@ -7,8 +7,8 @@ }, "classDescriptions": {}, "slotDescriptions": { - "content": "The component used for the content of the popover", - "iconButton": "The component used for the icon button", + "popoverContent": "The component used for the content of account popover", + "preview": "The component used for the account preview", "signInButton": "The component used for the sign in button.", "signOutButton": "The component used for the sign out button." } diff --git a/docs/translations/api-docs/sign-in-button/sign-in-button.json b/docs/translations/api-docs/sign-in-button/sign-in-button.json new file mode 100644 index 00000000000..18077dbb50a --- /dev/null +++ b/docs/translations/api-docs/sign-in-button/sign-in-button.json @@ -0,0 +1,301 @@ +{ + "componentDescription": "", + "propDescriptions": {}, + "classDescriptions": { + "colorError": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"error\"" + }, + "colorInfo": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"info\"" + }, + "colorInherit": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"inherit\"" + }, + "colorPrimary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"primary\"" + }, + "colorSecondary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"secondary\"" + }, + "colorSuccess": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"success\"" + }, + "colorWarning": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"warning\"" + }, + "contained": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\"" + }, + "containedError": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"error\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorError classes instead. See Migrating from deprecated APIs for more details." + }, + "containedInfo": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"info\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorInfo classes instead. See Migrating from deprecated APIs for more details." + }, + "containedInherit": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"inherit\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorInherit classes instead. See Migrating from deprecated APIs for more details." + }, + "containedPrimary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"primary\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorPrimary classes instead. See Migrating from deprecated APIs for more details." + }, + "containedSecondary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"secondary\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorSecondary classes instead. See Migrating from deprecated APIs for more details." + }, + "containedSizeLarge": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"large\" and variant=\"contained\"", + "deprecationInfo": "Combine the .MuiButton-sizeLarge and .MuiButton-contained classes instead. See Migrating from deprecated APIs for more details." + }, + "containedSizeMedium": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"medium\" and variant=\"contained\"", + "deprecationInfo": "Combine the .MuiButton-sizeMedium and .MuiButton-contained classes instead. See Migrating from deprecated APIs for more details." + }, + "containedSizeSmall": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"small\" and variant=\"contained\"", + "deprecationInfo": "Combine the .MuiButton-sizeSmall and .MuiButton-contained classes instead. See Migrating from deprecated APIs for more details." + }, + "containedSuccess": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"success\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorSuccess classes instead. See Migrating from deprecated APIs for more details." + }, + "containedWarning": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"warning\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorWarning classes instead. See Migrating from deprecated APIs for more details." + }, + "disabled": { + "description": "State class applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "disabled={true}" + }, + "disableElevation": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "disableElevation={true}" + }, + "endIcon": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the endIcon element", + "conditions": "supplied" + }, + "focusVisible": { + "description": "State class applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the ButtonBase root element", + "conditions": "the button is keyboard focused" + }, + "fullWidth": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "fullWidth={true}" + }, + "icon": { "description": "Styles applied to the icon element if supplied" }, + "iconSizeLarge": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the icon element", + "conditions": "supplied and size=\"large\"", + "deprecationInfo": "Combine the .MuiButton-icon and .MuiButtonSizeLarge classes instead. See Migrating from deprecated APIs for more details." + }, + "iconSizeMedium": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the icon element", + "conditions": "supplied and size=\"medium\"", + "deprecationInfo": "Combine the .MuiButton-icon and .MuiButtonSizeMedium classes instead. See Migrating from deprecated APIs for more details." + }, + "iconSizeSmall": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the icon element", + "conditions": "supplied and size=\"small\"", + "deprecationInfo": "Combine the .MuiButton-icon and .MuiButtonSizeSmall classes instead. See Migrating from deprecated APIs for more details." + }, + "outlined": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\"" + }, + "outlinedError": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"error\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorError classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedInfo": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"info\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorInfo classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedInherit": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"inherit\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorInherit classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedPrimary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"primary\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorPrimary classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedSecondary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"secondary\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorSecondary classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedSizeLarge": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"large\" and variant=\"outlined\"", + "deprecationInfo": "Combine the .MuiButton-sizeLarge and .MuiButton-outlined classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedSizeMedium": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"medium\" and variant=\"outlined\"", + "deprecationInfo": "Combine the .MuiButton-sizeMedium and .MuiButton-outlined classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedSizeSmall": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"small\" and variant=\"outlined\"", + "deprecationInfo": "Combine the .MuiButton-sizeSmall and .MuiButton-outlined classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedSuccess": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"success\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorSuccess classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedWarning": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"warning\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorWarning classes instead. See Migrating from deprecated APIs for more details." + }, + "root": { "description": "Styles applied to the root element." }, + "sizeLarge": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"large\"" + }, + "sizeMedium": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"medium\"" + }, + "sizeSmall": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"small\"" + }, + "startIcon": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the startIcon element", + "conditions": "supplied" + }, + "text": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\"" + }, + "textError": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"error\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorError classes instead. See Migrating from deprecated APIs for more details." + }, + "textInfo": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"info\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorInfo classes instead. See Migrating from deprecated APIs for more details." + }, + "textInherit": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"inherit\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorInherit classes instead. See Migrating from deprecated APIs for more details." + }, + "textPrimary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"primary\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorPrimary classes instead. See Migrating from deprecated APIs for more details." + }, + "textSecondary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"secondary\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorSecondary classes instead. See Migrating from deprecated APIs for more details." + }, + "textSizeLarge": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"large\" and variant=\"text\"", + "deprecationInfo": "Combine the .MuiButton-sizeLarge and .MuiButton-text classes instead. See Migrating from deprecated APIs for more details." + }, + "textSizeMedium": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"medium\" and variant=\"text\"", + "deprecationInfo": "Combine the .MuiButton-sizeMedium and .MuiButton-text classes instead. See Migrating from deprecated APIs for more details." + }, + "textSizeSmall": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"small\" and variant=\"text\"", + "deprecationInfo": "Combine the .MuiButton-sizeSmall and .MuiButton-text classes instead. See Migrating from deprecated APIs for more details." + }, + "textSuccess": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"success\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorSuccess classes instead. See Migrating from deprecated APIs for more details." + }, + "textWarning": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"warning\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorWarning classes instead. See Migrating from deprecated APIs for more details." + } + } +} diff --git a/docs/translations/api-docs/sign-out-button/sign-out-button.json b/docs/translations/api-docs/sign-out-button/sign-out-button.json new file mode 100644 index 00000000000..18077dbb50a --- /dev/null +++ b/docs/translations/api-docs/sign-out-button/sign-out-button.json @@ -0,0 +1,301 @@ +{ + "componentDescription": "", + "propDescriptions": {}, + "classDescriptions": { + "colorError": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"error\"" + }, + "colorInfo": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"info\"" + }, + "colorInherit": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"inherit\"" + }, + "colorPrimary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"primary\"" + }, + "colorSecondary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"secondary\"" + }, + "colorSuccess": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"success\"" + }, + "colorWarning": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "color=\"warning\"" + }, + "contained": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\"" + }, + "containedError": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"error\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorError classes instead. See Migrating from deprecated APIs for more details." + }, + "containedInfo": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"info\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorInfo classes instead. See Migrating from deprecated APIs for more details." + }, + "containedInherit": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"inherit\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorInherit classes instead. See Migrating from deprecated APIs for more details." + }, + "containedPrimary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"primary\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorPrimary classes instead. See Migrating from deprecated APIs for more details." + }, + "containedSecondary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"secondary\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorSecondary classes instead. See Migrating from deprecated APIs for more details." + }, + "containedSizeLarge": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"large\" and variant=\"contained\"", + "deprecationInfo": "Combine the .MuiButton-sizeLarge and .MuiButton-contained classes instead. See Migrating from deprecated APIs for more details." + }, + "containedSizeMedium": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"medium\" and variant=\"contained\"", + "deprecationInfo": "Combine the .MuiButton-sizeMedium and .MuiButton-contained classes instead. See Migrating from deprecated APIs for more details." + }, + "containedSizeSmall": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"small\" and variant=\"contained\"", + "deprecationInfo": "Combine the .MuiButton-sizeSmall and .MuiButton-contained classes instead. See Migrating from deprecated APIs for more details." + }, + "containedSuccess": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"success\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorSuccess classes instead. See Migrating from deprecated APIs for more details." + }, + "containedWarning": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"contained\" and color=\"warning\"", + "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorWarning classes instead. See Migrating from deprecated APIs for more details." + }, + "disabled": { + "description": "State class applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "disabled={true}" + }, + "disableElevation": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "disableElevation={true}" + }, + "endIcon": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the endIcon element", + "conditions": "supplied" + }, + "focusVisible": { + "description": "State class applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the ButtonBase root element", + "conditions": "the button is keyboard focused" + }, + "fullWidth": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "fullWidth={true}" + }, + "icon": { "description": "Styles applied to the icon element if supplied" }, + "iconSizeLarge": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the icon element", + "conditions": "supplied and size=\"large\"", + "deprecationInfo": "Combine the .MuiButton-icon and .MuiButtonSizeLarge classes instead. See Migrating from deprecated APIs for more details." + }, + "iconSizeMedium": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the icon element", + "conditions": "supplied and size=\"medium\"", + "deprecationInfo": "Combine the .MuiButton-icon and .MuiButtonSizeMedium classes instead. See Migrating from deprecated APIs for more details." + }, + "iconSizeSmall": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the icon element", + "conditions": "supplied and size=\"small\"", + "deprecationInfo": "Combine the .MuiButton-icon and .MuiButtonSizeSmall classes instead. See Migrating from deprecated APIs for more details." + }, + "outlined": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\"" + }, + "outlinedError": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"error\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorError classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedInfo": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"info\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorInfo classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedInherit": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"inherit\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorInherit classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedPrimary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"primary\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorPrimary classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedSecondary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"secondary\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorSecondary classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedSizeLarge": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"large\" and variant=\"outlined\"", + "deprecationInfo": "Combine the .MuiButton-sizeLarge and .MuiButton-outlined classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedSizeMedium": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"medium\" and variant=\"outlined\"", + "deprecationInfo": "Combine the .MuiButton-sizeMedium and .MuiButton-outlined classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedSizeSmall": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"small\" and variant=\"outlined\"", + "deprecationInfo": "Combine the .MuiButton-sizeSmall and .MuiButton-outlined classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedSuccess": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"success\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorSuccess classes instead. See Migrating from deprecated APIs for more details." + }, + "outlinedWarning": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"outlined\" and color=\"warning\"", + "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorWarning classes instead. See Migrating from deprecated APIs for more details." + }, + "root": { "description": "Styles applied to the root element." }, + "sizeLarge": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"large\"" + }, + "sizeMedium": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"medium\"" + }, + "sizeSmall": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"small\"" + }, + "startIcon": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the startIcon element", + "conditions": "supplied" + }, + "text": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\"" + }, + "textError": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"error\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorError classes instead. See Migrating from deprecated APIs for more details." + }, + "textInfo": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"info\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorInfo classes instead. See Migrating from deprecated APIs for more details." + }, + "textInherit": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"inherit\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorInherit classes instead. See Migrating from deprecated APIs for more details." + }, + "textPrimary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"primary\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorPrimary classes instead. See Migrating from deprecated APIs for more details." + }, + "textSecondary": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"secondary\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorSecondary classes instead. See Migrating from deprecated APIs for more details." + }, + "textSizeLarge": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"large\" and variant=\"text\"", + "deprecationInfo": "Combine the .MuiButton-sizeLarge and .MuiButton-text classes instead. See Migrating from deprecated APIs for more details." + }, + "textSizeMedium": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"medium\" and variant=\"text\"", + "deprecationInfo": "Combine the .MuiButton-sizeMedium and .MuiButton-text classes instead. See Migrating from deprecated APIs for more details." + }, + "textSizeSmall": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "size=\"small\" and variant=\"text\"", + "deprecationInfo": "Combine the .MuiButton-sizeSmall and .MuiButton-text classes instead. See Migrating from deprecated APIs for more details." + }, + "textSuccess": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"success\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorSuccess classes instead. See Migrating from deprecated APIs for more details." + }, + "textWarning": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "variant=\"text\" and color=\"warning\"", + "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorWarning classes instead. See Migrating from deprecated APIs for more details." + } + } +} diff --git a/packages/toolpad-core/src/Account/Account.tsx b/packages/toolpad-core/src/Account/Account.tsx index 1c5fb9d9b11..fc01c1df242 100644 --- a/packages/toolpad-core/src/Account/Account.tsx +++ b/packages/toolpad-core/src/Account/Account.tsx @@ -1,30 +1,27 @@ import * as React from 'react'; -import { styled } from '@mui/material/styles'; import PropTypes from 'prop-types'; +import Button from '@mui/material/Button'; import Popover from '@mui/material/Popover'; -import Avatar from '@mui/material/Avatar'; import Divider from '@mui/material/Divider'; -import Button, { ButtonProps } from '@mui/material/Button'; -import IconButton, { IconButtonProps } from '@mui/material/IconButton'; -import Tooltip from '@mui/material/Tooltip'; -import Logout from '@mui/icons-material/Logout'; -import { AccountDetails } from '../AccountDetails/AccountDetails'; +import { SignInButton } from './SignInButton'; +import { SignOutButton } from './SignOutButton'; +import { AccountPreview, AccountPreviewProps } from './AccountPreview'; +import { AccountPopoverHeader } from './AccountPopoverHeader'; +import { AccountPopoverFooter } from './AccountPopoverFooter'; import { SessionContext, AuthenticationContext } from '../AppProvider/AppProvider'; -import DEFAULT_LOCALE_TEXT from '../shared/locales/en'; - -const SignOutContainer = styled('div')(({ theme }) => ({ - display: 'flex', - flexDirection: 'row', - padding: theme.spacing(1), - justifyContent: 'flex-end', -})); +import { LocaleProvider, useLocaleText } from '../shared/locales/LocaleContext'; export interface AccountSlots { /** - * The component used for the icon button - * @default IconButton + * The component used for the account preview + * @default AccountPreview + */ + preview?: React.ElementType; + /** + * The component used for the content of account popover + * @default Popover */ - iconButton?: React.ElementType; + popoverContent?: React.ElementType; /** * The component used for the sign in button. * @default Button @@ -32,14 +29,9 @@ export interface AccountSlots { signInButton?: React.ElementType; /** * The component used for the sign out button. - * @default MenuItem + * @default Button */ signOutButton?: React.ElementType; - /** - * The component used for the content of the popover - * @default null - */ - content?: React.ElementType; } export interface AccountProps { @@ -51,40 +43,32 @@ export interface AccountProps { * The props used for each slot inside. */ slotProps?: { - signInButton?: ButtonProps; - signOutButton?: ButtonProps; - iconButton?: IconButtonProps; + preview?: AccountPreviewProps; + popover?: React.ComponentProps; + signInButton?: React.ComponentProps; + signOutButton?: React.ComponentProps; }; /** * The labels for the account component. - * @default DEFAULT_LOCALE_TEXT */ - localeText?: typeof DEFAULT_LOCALE_TEXT; + localeText?: Partial>; } -/** - * - * Demos: - * - * - [Account](https://mui.com/toolpad/core/react-account/) - * - [Dashboard Layout](https://mui.com/toolpad/core/react-dashboard-layout/) - * - [Sign-in Page](https://mui.com/toolpad/core/react-sign-in-page/) - * - * API: - * - * - [Account API](https://mui.com/toolpad/core/api/account) - */ -function Account(props: AccountProps) { - const { slots, slotProps, localeText = DEFAULT_LOCALE_TEXT } = props; - const [anchorEl, setAnchorEl] = React.useState(null); + +function AccountContent(props: Omit) { + const { slots, slotProps } = props; + const [anchorEl, setAnchorEl] = React.useState(null); const session = React.useContext(SessionContext); const authentication = React.useContext(AuthenticationContext); const open = Boolean(anchorEl); - const handleClick = (event: React.MouseEvent) => { + + const handleClick = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; + const handleClose = () => { setAnchorEl(null); }; + if (!authentication) { return null; } @@ -93,58 +77,28 @@ function Account(props: AccountProps) { return slots?.signInButton ? ( ) : ( - + ); } + return ( -
- - {slots?.iconButton ? ( - - ) : ( - - - - )} - -
+ {slots?.preview ? ( + + ) : ( + + )} - {slots?.content ? : } - - {slots?.signOutButton ? ( - + {slots?.popoverContent ? ( + ) : ( - - - + + + + + + + + + )}
); } +AccountContent.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * The props used for each slot inside. + */ + slotProps: PropTypes.shape({ + popover: PropTypes.object, + preview: PropTypes.shape({ + handleClick: PropTypes.func, + open: PropTypes.bool, + slotProps: PropTypes.shape({ + avatar: PropTypes.object, + avatarIconButton: PropTypes.object, + moreIconButton: PropTypes.object, + }), + slots: PropTypes.shape({ + avatar: PropTypes.elementType, + }), + variant: PropTypes.oneOf(['condensed', 'expanded']), + }), + signInButton: PropTypes.object, + signOutButton: PropTypes.object, + }), + /** + * The components used for each slot inside. + */ + slots: PropTypes.shape({ + popoverContent: PropTypes.elementType, + preview: PropTypes.elementType, + signInButton: PropTypes.elementType, + signOutButton: PropTypes.elementType, + }), +} as any; +/** + * + * Demos: + * + * - [Account](https://mui.com/toolpad/core/react-account/) + * - [Dashboard Layout](https://mui.com/toolpad/core/react-dashboard-layout/) + * - [Sign-in Page](https://mui.com/toolpad/core/react-sign-in-page/) + * + * API: + * + * - [Account API](https://mui.com/toolpad/core/api/account) + */ +function Account(props: AccountProps) { + const { localeText, ...rest } = props; + + return ( + + + + ); +} + Account.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ @@ -211,17 +209,32 @@ Account.propTypes /* remove-proptypes */ = { // └─────────────────────────────────────────────────────────────────────┘ /** * The labels for the account component. - * @default DEFAULT_LOCALE_TEXT */ localeText: PropTypes.shape({ - signInLabel: PropTypes.string.isRequired, - signOutLabel: PropTypes.string.isRequired, + iconButtonAriaLabel: PropTypes.string, + signInLabel: PropTypes.string, + signOutLabel: PropTypes.string, }), /** * The props used for each slot inside. */ slotProps: PropTypes.shape({ - iconButton: PropTypes.object, + popover: PropTypes.object, + preview: PropTypes.shape({ + handleClick: PropTypes.func, + open: PropTypes.bool, + slotProps: PropTypes.shape({ + avatar: PropTypes.object, + avatarIconButton: PropTypes.object, + moreIconButton: PropTypes.object, + }), + slots: PropTypes.shape({ + avatar: PropTypes.elementType, + avatarIconButton: PropTypes.elementType, + moreIconButton: PropTypes.elementType, + }), + variant: PropTypes.oneOf(['condensed', 'expanded']), + }), signInButton: PropTypes.object, signOutButton: PropTypes.object, }), @@ -229,8 +242,8 @@ Account.propTypes /* remove-proptypes */ = { * The components used for each slot inside. */ slots: PropTypes.shape({ - content: PropTypes.elementType, - iconButton: PropTypes.elementType, + popoverContent: PropTypes.elementType, + preview: PropTypes.elementType, signInButton: PropTypes.elementType, signOutButton: PropTypes.elementType, }), diff --git a/packages/toolpad-core/src/Account/AccountPopoverFooter.tsx b/packages/toolpad-core/src/Account/AccountPopoverFooter.tsx new file mode 100644 index 00000000000..62696b0b449 --- /dev/null +++ b/packages/toolpad-core/src/Account/AccountPopoverFooter.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import Box, { BoxProps } from '@mui/material/Box'; + +export interface AccountPopoverFooterProps extends BoxProps { + children?: React.ReactNode; +} + +export /** + * + * Demos: + * + * - [Account](https://mui.com/toolpad/core/react-account/) + * + * API: + * + * - [AccountPopoverFooter API](https://mui.com/toolpad/core/api/account-popover-footer) + */ function AccountPopoverFooter(props: AccountPopoverFooterProps) { + const { children, ...rest } = props; + return ( + + {children} + + ); +} diff --git a/packages/toolpad-core/src/Account/AccountPopoverHeader.tsx b/packages/toolpad-core/src/Account/AccountPopoverHeader.tsx new file mode 100644 index 00000000000..f22591550d3 --- /dev/null +++ b/packages/toolpad-core/src/Account/AccountPopoverHeader.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; +import Stack, { StackProps } from '@mui/material/Stack'; + +export interface AccountPopoverHeaderProps extends StackProps { + children?: React.ReactNode; +} + +export /** + * + * Demos: + * + * - [Account](https://mui.com/toolpad/core/react-account/) + * + * API: + * + * - [AccountPopoverHeader API](https://mui.com/toolpad/core/api/account-popover-header) + */ function AccountPopoverHeader(props: AccountPopoverHeaderProps) { + const { children, ...rest } = props; + return {children}; +} diff --git a/packages/toolpad-core/src/AccountDetails/AccountDetails.test.tsx b/packages/toolpad-core/src/Account/AccountPreview.test.tsx similarity index 89% rename from packages/toolpad-core/src/AccountDetails/AccountDetails.test.tsx rename to packages/toolpad-core/src/Account/AccountPreview.test.tsx index 5470eb2a127..f2f128c30ec 100644 --- a/packages/toolpad-core/src/AccountDetails/AccountDetails.test.tsx +++ b/packages/toolpad-core/src/Account/AccountPreview.test.tsx @@ -8,16 +8,16 @@ import * as React from 'react'; import { describe, test, expect } from 'vitest'; import { render, screen } from '@testing-library/react'; import describeConformance from '@toolpad/utils/describeConformance'; -import { AccountDetails } from './AccountDetails'; +import { AccountPreview } from './AccountPreview'; import { SessionContext } from '../AppProvider'; describe('AccountDetails', () => { - describeConformance(, () => ({ + describeConformance(, () => ({ skip: ['themeDefaultProps'], })); test('renders nothing when no session', () => { - render(); + render(); expect(screen.queryByRole('img')).not.toBeInTheDocument(); }); @@ -32,7 +32,7 @@ describe('AccountDetails', () => { render( - + , ); @@ -54,7 +54,7 @@ describe('AccountDetails', () => { render( - + , ); diff --git a/packages/toolpad-core/src/Account/AccountPreview.tsx b/packages/toolpad-core/src/Account/AccountPreview.tsx new file mode 100644 index 00000000000..1fb7d168c3d --- /dev/null +++ b/packages/toolpad-core/src/Account/AccountPreview.tsx @@ -0,0 +1,181 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import Avatar, { AvatarProps } from '@mui/material/Avatar'; +import Typography from '@mui/material/Typography'; +import Tooltip from '@mui/material/Tooltip'; +import Stack from '@mui/material/Stack'; +import IconButton, { IconButtonProps } from '@mui/material/IconButton'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; +import { SessionContext } from '../AppProvider'; +import { useLocaleText } from '../shared/locales/LocaleContext'; + +export type AccountPreviewVariant = 'condensed' | 'expanded'; + +export interface AccountPreviewSlots { + /** + * The component used for the Avatar + * @default Avatar + */ + avatar?: React.ElementType; + /** + * The component used for the overflow icon button in the expanded variant + * @default IconButton + */ + moreIconButton?: React.ElementType; + /** + * The component used for the avatar icon button in the condensed variant + * @default IconButton + */ + avatarIconButton: React.ElementType; +} + +export interface AccountPreviewProps { + /** + * The components used for each slot inside. + */ + slots?: AccountPreviewSlots; + /** + * The props used for each slot inside. + */ + slotProps?: { + avatar?: AvatarProps; + moreIconButton?: IconButtonProps; + avatarIconButton?: IconButtonProps; + }; + /** + * The type of account details to display. + * @property {'condensed'} condensed - Shows only the user's avatar. + * @property {'expanded'} expanded - Displays the user's avatar, name, and email if available. + * @default 'condensed' + */ + variant?: AccountPreviewVariant; + /** + * The handler used when the preview is expanded + */ + handleClick?: React.MouseEventHandler; + /** + * The state of the Account popover + * @default false + */ + open?: boolean; +} + +/** + * The AccountPreview component displays user account information. + * + * Demos: + * + * - [Account](https://mui.com/toolpad/core/react-account/) + * + * API: + * + * - [AccountPreview API](https://mui.com/toolpad/core/api/account-preview) + */ +function AccountPreview(props: AccountPreviewProps) { + const { slots, variant = 'condensed', slotProps, open, handleClick } = props; + const session = React.useContext(SessionContext); + const localeText = useLocaleText(); + + if (!session || !session.user) { + return null; + } + + const avatarContent = slots?.avatar ? ( + + ) : ( + + ); + + if (variant === 'expanded') { + return ( + + {avatarContent} + + + {session.user?.name} + + + {session.user?.email} + + + {handleClick && + (slots?.moreIconButton ? ( + + ) : ( + + + + ))} + + ); + } + + return ( + + {slots?.avatarIconButton ? ( + + ) : ( + + {avatarContent} + + )} + + ); +} + +AccountPreview.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * The handler used when the preview is expanded + */ + handleClick: PropTypes.func, + /** + * The state of the Account popover + * @default false + */ + open: PropTypes.bool, + /** + * The props used for each slot inside. + */ + slotProps: PropTypes.shape({ + avatar: PropTypes.object, + avatarIconButton: PropTypes.object, + moreIconButton: PropTypes.object, + }), + /** + * The components used for each slot inside. + */ + slots: PropTypes.shape({ + avatar: PropTypes.elementType, + }), + /** + * The type of account details to display. + * @property {'condensed'} condensed - Shows only the user's avatar. + * @property {'expanded'} expanded - Displays the user's avatar, name, and email if available. + * @default 'condensed' + */ + variant: PropTypes.oneOf(['condensed', 'expanded']), +} as any; + +export { AccountPreview }; diff --git a/packages/toolpad-core/src/Account/SignInButton.tsx b/packages/toolpad-core/src/Account/SignInButton.tsx new file mode 100644 index 00000000000..4dad29fb285 --- /dev/null +++ b/packages/toolpad-core/src/Account/SignInButton.tsx @@ -0,0 +1,38 @@ +import * as React from 'react'; +import Button, { ButtonProps } from '@mui/material/Button'; +import { AuthenticationContext } from '../AppProvider/AppProvider'; +import { useLocaleText } from '../shared/locales/LocaleContext'; + +export/** + * + * Demos: + * + * - [Account](https://mui.com/toolpad/core/react-account/) + * + * API: + * + * - [SignInButton API](https://mui.com/toolpad/core/api/sign-in-button) + */ function SignInButton(props: ButtonProps) { + const authentication = React.useContext(AuthenticationContext); + const localeText = useLocaleText(); + + return ( + + ); +} diff --git a/packages/toolpad-core/src/Account/SignOutButton.tsx b/packages/toolpad-core/src/Account/SignOutButton.tsx new file mode 100644 index 00000000000..03d87b1fcaf --- /dev/null +++ b/packages/toolpad-core/src/Account/SignOutButton.tsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import Button, { ButtonProps } from '@mui/material/Button'; +import LogoutIcon from '@mui/icons-material/Logout'; +import { AuthenticationContext } from '../AppProvider/AppProvider'; +import { useLocaleText } from '../shared/locales/LocaleContext'; + +export type SignOutButtonProps = ButtonProps; + +export /** + * + * Demos: + * + * - [Account](https://mui.com/toolpad/core/react-account/) + * + * API: + * + * - [SignOutButton API](https://mui.com/toolpad/core/api/sign-out-button) + */ function SignOutButton(props: SignOutButtonProps) { + const authentication = React.useContext(AuthenticationContext); + const localeText = useLocaleText(); + + return ( + + ); +} diff --git a/packages/toolpad-core/src/Account/index.ts b/packages/toolpad-core/src/Account/index.ts index 4c71833ffeb..cb01e597927 100644 --- a/packages/toolpad-core/src/Account/index.ts +++ b/packages/toolpad-core/src/Account/index.ts @@ -1 +1,6 @@ export * from './Account'; +export * from './AccountPreview'; +export * from './AccountPopoverHeader'; +export * from './AccountPopoverFooter'; +export * from './SignOutButton'; +export * from './SignInButton'; diff --git a/packages/toolpad-core/src/AccountDetails/AccountDetails.tsx b/packages/toolpad-core/src/AccountDetails/AccountDetails.tsx deleted file mode 100644 index 532bd7e5ddc..00000000000 --- a/packages/toolpad-core/src/AccountDetails/AccountDetails.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import Avatar, { AvatarProps } from '@mui/material/Avatar'; -import Typography from '@mui/material/Typography'; -import Stack from '@mui/material/Stack'; -import { SessionContext } from '../AppProvider'; - -export interface AccountDetailsSlots { - /** - * The component used for the Avatar - * @default Avatar - */ - avatar?: React.ElementType; -} - -export interface AccountDetailsProps { - /** - * The components used for each slot inside. - */ - slots?: AccountDetailsSlots; - /** - * The props used for each slot inside. - */ - slotProps?: { - avatar: AvatarProps; - }; -} -/** - * - * Demos: - * - * - [Account](https://mui.com/toolpad/core/react-account/) - * - * API: - * - * - [AccountDetails API](https://mui.com/toolpad/core/api/account-details) - */ -function AccountDetails(props: AccountDetailsProps) { - const { slots, slotProps } = props; - const session = React.useContext(SessionContext); - - if (!session) { - return null; - } - - return ( - - - {slots?.avatar ? ( - - ) : ( - - )} - - {session.user?.name} - {session.user?.email} - - - - ); -} - -AccountDetails.propTypes /* remove-proptypes */ = { - // ┌────────────────────────────── Warning ──────────────────────────────┐ - // │ These PropTypes are generated from the TypeScript type definitions. │ - // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ - // └─────────────────────────────────────────────────────────────────────┘ - /** - * The props used for each slot inside. - */ - slotProps: PropTypes.shape({ - avatar: PropTypes.object.isRequired, - }), - /** - * The components used for each slot inside. - */ - slots: PropTypes.shape({ - avatar: PropTypes.elementType, - }), -} as any; - -export { AccountDetails }; diff --git a/packages/toolpad-core/src/AccountDetails/index.ts b/packages/toolpad-core/src/AccountDetails/index.ts deleted file mode 100644 index 262f413926f..00000000000 --- a/packages/toolpad-core/src/AccountDetails/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './AccountDetails'; diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx index bfe59278904..3c029df5e93 100644 --- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx +++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx @@ -749,17 +749,19 @@ DashboardLayout.propTypes /* remove-proptypes */ = { }), toolbarAccount: PropTypes.shape({ localeText: PropTypes.shape({ - signInLabel: PropTypes.string.isRequired, - signOutLabel: PropTypes.string.isRequired, + iconButtonAriaLabel: PropTypes.string, + signInLabel: PropTypes.string, + signOutLabel: PropTypes.string, }), slotProps: PropTypes.shape({ - iconButton: PropTypes.object, + popover: PropTypes.object, + preview: PropTypes.object, signInButton: PropTypes.object, signOutButton: PropTypes.object, }), slots: PropTypes.shape({ - content: PropTypes.elementType, - iconButton: PropTypes.elementType, + popoverContent: PropTypes.elementType, + preview: PropTypes.elementType, signInButton: PropTypes.elementType, signOutButton: PropTypes.elementType, }), diff --git a/packages/toolpad-core/src/index.ts b/packages/toolpad-core/src/index.ts index 422e84d0527..dcb98090703 100644 --- a/packages/toolpad-core/src/index.ts +++ b/packages/toolpad-core/src/index.ts @@ -6,8 +6,6 @@ export * from './SignInPage'; export * from './Account'; -export * from './AccountDetails'; - export * from './PageContainer'; export * from './useActivePage'; diff --git a/packages/toolpad-core/src/shared/locales/LocaleContext.tsx b/packages/toolpad-core/src/shared/locales/LocaleContext.tsx new file mode 100644 index 00000000000..da349ee51b8 --- /dev/null +++ b/packages/toolpad-core/src/shared/locales/LocaleContext.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import DEFAULT_LOCALE_TEXT from './en'; + +export type LocaleContextType = { + // Account + signInLabel?: string; + signOutLabel?: string; + // Account Preview + iconButtonAriaLabel?: string; +}; + +export const LocaleContext = React.createContext(DEFAULT_LOCALE_TEXT); + +export interface LocaleProviderProps { + localeText?: Partial; + children: React.ReactNode; +} + +/** + * @ignore - internal component. + */ +export function LocaleProvider({ localeText, children }: LocaleProviderProps) { + const mergedLocaleText = React.useMemo( + () => ({ ...DEFAULT_LOCALE_TEXT, ...localeText }), + [localeText], + ); + + return {children}; +} + +/** + * @ignore - internal hook. + */ + +export function useLocaleText() { + return React.useContext(LocaleContext); +} diff --git a/packages/toolpad-core/src/shared/locales/en.tsx b/packages/toolpad-core/src/shared/locales/en.tsx index a3f075cdbf8..52f51eec0f1 100644 --- a/packages/toolpad-core/src/shared/locales/en.tsx +++ b/packages/toolpad-core/src/shared/locales/en.tsx @@ -2,6 +2,8 @@ const TOOLPAD_CORE_DEFAULT_LOCALE_TEXT = { // Account signInLabel: 'Sign In', signOutLabel: 'Sign Out', + // Account Preview + iconButtonAriaLabel: 'Current user', }; export default TOOLPAD_CORE_DEFAULT_LOCALE_TEXT; From 5be79144184c102869f3ce1c3e4ffdfbf7d3edfc Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 17 Oct 2024 18:33:54 +0530 Subject: [PATCH 19/28] fix: CI --- pnpm-lock.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c48da24f9d5..aa0cf1f4f27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -195,7 +195,7 @@ importers: version: 7.37.1(eslint@8.57.1) eslint-plugin-react-compiler: specifier: latest - version: 0.0.0-experimental-45ae4c3-20241011(eslint@8.57.1) + version: 0.0.0-experimental-fa06e2c-20241016(eslint@8.57.1) eslint-plugin-react-hooks: specifier: 4.6.2 version: 4.6.2(eslint@8.57.1) @@ -2013,7 +2013,7 @@ packages: resolution: {integrity: sha512-GjV0/mUEEXpi1U5ZgDprMRRgajGMRW3G5FjMr5KLKD8nT2fTG8+h/klV3+6Dm5739QE+K5+2e91qFKAYI3pmRg==} engines: {node: '>=6.9.0'} peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/core': ^7.25.8 '@babel/preset-typescript@7.25.7': resolution: {integrity: sha512-rkkpaXJZOFN45Fb+Gki0c+KMIglk4+zZXOoMJuyEK8y8Kkc8Jd3BDmP7qPsz0zQMJj+UD7EprF+AqAXcILnexw==} @@ -2899,7 +2899,7 @@ packages: resolution: {integrity: sha512-P0E7ZrxOuyYqBvVv9w8k7wm+Xzx/KRu+BGgFcR2htTsGCpJNQJCSUXNUZ50MUmSU9hzqhwbQWNXhV1MBTl6F7A==} engines: {node: '>=14.0.0'} peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 + '@types/react': ^18.3.11 react: ^17.0.0 || ^18.0.0 react-dom: ^17.0.0 || ^18.0.0 peerDependenciesMeta: @@ -5991,8 +5991,8 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-plugin-react-compiler@0.0.0-experimental-45ae4c3-20241011: - resolution: {integrity: sha512-m+BmeFtVWzrHt87sb5g5jLttHdo9YScPiuiingdEqLYtUv7pdVi6pQgY3nCOI4h09C4wmWS9xzpaVNEgiODOBg==} + eslint-plugin-react-compiler@0.0.0-experimental-fa06e2c-20241016: + resolution: {integrity: sha512-uQY1PmX7OqMqqAy4FG0fs2U9V9aF8dDN2RWP4WYc/u3ia9RKni2nZ9pnKzoSfT6w3wPggzH1nv9gmZAjDIzteQ==} engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} peerDependencies: eslint: '>=7' @@ -15780,7 +15780,7 @@ snapshots: globals: 13.24.0 rambda: 7.5.0 - eslint-plugin-react-compiler@0.0.0-experimental-45ae4c3-20241011(eslint@8.57.1): + eslint-plugin-react-compiler@0.0.0-experimental-fa06e2c-20241016(eslint@8.57.1): dependencies: '@babel/core': 7.25.8 '@babel/parser': 7.25.8 From 637d63720c421d731733647ad34b853f47e80718 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 17 Oct 2024 19:00:28 +0530 Subject: [PATCH 20/28] fix: update test, CI --- .../toolpad/core/api/account-preview.json | 2 +- .../src/Account/AccountPreview.test.tsx | 83 +++++++++++-------- .../src/Account/AccountPreview.tsx | 4 +- .../toolpad-core/src/shared/locales/en.tsx | 2 +- 4 files changed, 54 insertions(+), 37 deletions(-) diff --git a/docs/pages/toolpad/core/api/account-preview.json b/docs/pages/toolpad/core/api/account-preview.json index c9d8aa4e912..8608aa72476 100644 --- a/docs/pages/toolpad/core/api/account-preview.json +++ b/docs/pages/toolpad/core/api/account-preview.json @@ -41,7 +41,7 @@ ], "classes": [], "spread": true, - "themeDefaultProps": false, + "themeDefaultProps": null, "muiName": "AccountPreview", "filename": "/packages/toolpad-core/src/Account/AccountPreview.tsx", "inheritance": null, diff --git a/packages/toolpad-core/src/Account/AccountPreview.test.tsx b/packages/toolpad-core/src/Account/AccountPreview.test.tsx index f2f128c30ec..7634e77eade 100644 --- a/packages/toolpad-core/src/Account/AccountPreview.test.tsx +++ b/packages/toolpad-core/src/Account/AccountPreview.test.tsx @@ -5,60 +5,77 @@ */ import * as React from 'react'; -import { describe, test, expect } from 'vitest'; +import { describe, test, expect, vi } from 'vitest'; import { render, screen } from '@testing-library/react'; -import describeConformance from '@toolpad/utils/describeConformance'; +import userEvent from '@testing-library/user-event'; import { AccountPreview } from './AccountPreview'; -import { SessionContext } from '../AppProvider'; +import { AppProvider } from '../AppProvider'; -describe('AccountDetails', () => { - describeConformance(, () => ({ - skip: ['themeDefaultProps'], - })); +describe('AccountPreview', () => { + const auth = { signIn: vi.fn(), signOut: vi.fn() }; + const session = { + user: { name: 'John Doe', email: 'john@example.com', image: 'https://example.com/avatar.jpg' }, + }; - test('renders nothing when no session', () => { - render(); - expect(screen.queryByRole('img')).not.toBeInTheDocument(); - }); + test('renders nothing when no session is provided', () => { + render( + + + , + ); - test('renders account details correctly when there is a session', () => { - const session = { - user: { - name: 'John Doe', - email: 'john@example.com', - image: 'https://example.com/avatar.jpg', - }, - }; + expect(screen.queryByRole('button')).not.toBeInTheDocument(); + }); + test('displays condensed variant by default', () => { render( - + - , + , ); const avatar = screen.getByRole('img', { name: 'John Doe' }); expect(avatar).toBeInTheDocument(); expect(avatar).toHaveAttribute('src', 'https://example.com/avatar.jpg'); + }); + + test('displays user name, email, and avatar in expanded variant', () => { + render( + + + , + ); expect(screen.getByText('John Doe')).toBeInTheDocument(); expect(screen.getByText('john@example.com')).toBeInTheDocument(); + expect(screen.getByRole('img', { name: 'John Doe' })).toBeInTheDocument(); }); - test('renders account details with fallback when image is not provided', () => { - const session = { - user: { - name: 'Jane Smith', - email: 'jane@example.com', - }, - }; + test('calls handleClick when more icon button is clicked in expanded variant', async () => { + const handleClick = vi.fn(); + render( + + + , + ); + + const moreButton = screen.getByRole('button'); + await userEvent.click(moreButton); + expect(handleClick).toHaveBeenCalled(); + }); + + test('calls handleClick when avatar is clicked in condensed variant', async () => { + const handleClick = vi.fn(); render( - - - , + + + , ); - expect(screen.getByText('Jane Smith')).toBeInTheDocument(); - expect(screen.getByText('jane@example.com')).toBeInTheDocument(); + const avatarButton = screen.getByRole('button', { name: 'Current User' }); + await userEvent.click(avatarButton); + + expect(handleClick).toHaveBeenCalled(); }); }); diff --git a/packages/toolpad-core/src/Account/AccountPreview.tsx b/packages/toolpad-core/src/Account/AccountPreview.tsx index 1fb7d168c3d..903bbe568f8 100644 --- a/packages/toolpad-core/src/Account/AccountPreview.tsx +++ b/packages/toolpad-core/src/Account/AccountPreview.tsx @@ -26,7 +26,7 @@ export interface AccountPreviewSlots { * The component used for the avatar icon button in the condensed variant * @default IconButton */ - avatarIconButton: React.ElementType; + avatarIconButton?: React.ElementType; } export interface AccountPreviewProps { @@ -127,7 +127,7 @@ function AccountPreview(props: AccountPreviewProps) { ) : ( Date: Fri, 18 Oct 2024 00:43:02 +0530 Subject: [PATCH 21/28] fix: Pedro review --- .../account/AccountCustomLocaleText.js | 3 +- .../account/AccountCustomLocaleText.tsx | 6 +- .../components/account/AccountSlotsWallet.js | 10 +- .../components/account/AccountSlotsWallet.tsx | 11 +- .../core/components/account/CustomMenu.js | 2 +- .../core/components/account/CustomMenu.tsx | 2 +- .../core/components/account/account.md | 18 +-- docs/pages/toolpad/core/api/account.json | 12 +- .../toolpad/core/api/dashboard-layout.json | 2 +- .../api-docs/account/account.json | 1 + packages/toolpad-core/src/Account/Account.tsx | 105 ++++++++++-------- .../src/Account/AccountPreview.test.tsx | 1 + .../src/DashboardLayout/DashboardLayout.tsx | 2 + 13 files changed, 101 insertions(+), 74 deletions(-) diff --git a/docs/data/toolpad/core/components/account/AccountCustomLocaleText.js b/docs/data/toolpad/core/components/account/AccountCustomLocaleText.js index b902a11f37a..5ed35873c32 100644 --- a/docs/data/toolpad/core/components/account/AccountCustomLocaleText.js +++ b/docs/data/toolpad/core/components/account/AccountCustomLocaleText.js @@ -1,5 +1,6 @@ import * as React from 'react'; -import { Account, AuthenticationContext, SessionContext } from '@toolpad/core'; +import { AuthenticationContext, SessionContext } from '@toolpad/core/AppProvider'; +import { Account } from '@toolpad/core/Account'; const demoSession = { user: { diff --git a/docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx b/docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx index 4054145ff3d..c74db6789c7 100644 --- a/docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx +++ b/docs/data/toolpad/core/components/account/AccountCustomLocaleText.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import { - Account, AuthenticationContext, - SessionContext, Session, -} from '@toolpad/core'; + SessionContext, +} from '@toolpad/core/AppProvider'; +import { Account } from '@toolpad/core/Account'; const demoSession = { user: { diff --git a/docs/data/toolpad/core/components/account/AccountSlotsWallet.js b/docs/data/toolpad/core/components/account/AccountSlotsWallet.js index 9f75276879b..44de238600e 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsWallet.js +++ b/docs/data/toolpad/core/components/account/AccountSlotsWallet.js @@ -15,11 +15,11 @@ import CopyIcon from '@mui/icons-material/ContentCopy'; import { Account, AccountPreview, - AuthenticationContext, - SessionContext, + AccountPopoverFooter, SignOutButton, -} from '@toolpad/core'; -import { AccountPopoverFooter } from '../../../../../../packages/toolpad-core/src/Account/AccountPopoverFooter'; +} from '@toolpad/core/Account'; + +import { AuthenticationContext, SessionContext } from '@toolpad/core/AppProvider'; const demoSession = { user: { @@ -40,7 +40,7 @@ function CryptoWalletInfo() { - + diff --git a/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx b/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx index 3a4a5ff96e2..4e7c63e82cb 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx +++ b/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx @@ -15,12 +15,15 @@ import CopyIcon from '@mui/icons-material/ContentCopy'; import { Account, AccountPreview, + AccountPopoverFooter, + SignOutButton, +} from '@toolpad/core/Account'; + +import { AuthenticationContext, SessionContext, Session, - SignOutButton, -} from '@toolpad/core'; -import { AccountPopoverFooter } from '../../../../../../packages/toolpad-core/src/Account/AccountPopoverFooter'; +} from '@toolpad/core/AppProvider'; const demoSession = { user: { @@ -41,7 +44,7 @@ function CryptoWalletInfo() { - + diff --git a/docs/data/toolpad/core/components/account/CustomMenu.js b/docs/data/toolpad/core/components/account/CustomMenu.js index e6aa0bd65cc..ac4933589b9 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.js +++ b/docs/data/toolpad/core/components/account/CustomMenu.js @@ -179,7 +179,7 @@ export default function CustomMenu() { - + Accounts diff --git a/docs/data/toolpad/core/components/account/CustomMenu.tsx b/docs/data/toolpad/core/components/account/CustomMenu.tsx index 200ca474361..c1b6ebffe27 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.tsx +++ b/docs/data/toolpad/core/components/account/CustomMenu.tsx @@ -179,7 +179,7 @@ export default function CustomMenu() { - + Accounts diff --git a/docs/data/toolpad/core/components/account/account.md b/docs/data/toolpad/core/components/account/account.md index 34a901289a1..b1117f6f9f9 100644 --- a/docs/data/toolpad/core/components/account/account.md +++ b/docs/data/toolpad/core/components/account/account.md @@ -47,12 +47,6 @@ The `AccountPreview` component has two variants, `condensed` (the default) and ` {{"demo": "AccountCustomSlotProps.js", "bg": "outlined" }} -### Labels - -You can pass in custom labels – including of different languages – using the `localeText` prop. - -{{"demo": "AccountCustomLocaleText.js", "bg": "outlined" }} - ### Slots You can pass in your own components inside the `Account` popover through the `slots` prop. @@ -61,14 +55,20 @@ You can pass in your own components inside the `Account` popover through the `sl You can wrap the default sub-components – such as `SignOutButton` and `AccountPreview` – and wrap them in `AccountPopoverHeader` and `AccountPopoverFooter` components to create custom account popovers, as shown in the following demos: +##### Account Switcher + +You can build advanced menus – such as a tenant switcher – by passing in a component that wraps `AccountPreview` and `SignOutButton` with a custom menu: + +{{"demo": "AccountSlotsAccountSwitcher.js", "bg": "outlined"}} + ##### Crypto Wallet You can wrap the default `SignOutButton` with your own action buttons inside `AccountPopoverFooter` to customize the popover footer section: {{"demo": "AccountSlotsWallet.js", "bg": "outlined" }} -##### Account Switcher +### Labels -You can build advanced menus – such as a tenant switcher – by passing in a component that wraps `AccountPreview` and `SignOutButton` with a custom menu: +You can pass in custom labels – including of different languages – using the `localeText` prop. -{{"demo": "AccountSlotsAccountSwitcher.js", "bg": "outlined"}} +{{"demo": "AccountCustomLocaleText.js", "bg": "outlined" }} diff --git a/docs/pages/toolpad/core/api/account.json b/docs/pages/toolpad/core/api/account.json index 3c263c99ff6..87dc15cbe0e 100644 --- a/docs/pages/toolpad/core/api/account.json +++ b/docs/pages/toolpad/core/api/account.json @@ -9,13 +9,13 @@ "slotProps": { "type": { "name": "shape", - "description": "{ popover?: object, preview?: { handleClick?: func, open?: bool, slotProps?: { avatar?: object, avatarIconButton?: object, moreIconButton?: object }, slots?: { avatar?: elementType, avatarIconButton?: elementType, moreIconButton?: elementType }, variant?: 'condensed'
| 'expanded' }, signInButton?: object, signOutButton?: object }" + "description": "{ popover?: object, popoverContent?: object, preview?: { handleClick?: func, open?: bool, slotProps?: { avatar?: object, avatarIconButton?: object, moreIconButton?: object }, slots?: { avatar?: elementType, avatarIconButton?: elementType, moreIconButton?: elementType }, variant?: 'condensed'
| 'expanded' }, signInButton?: object, signOutButton?: object }" } }, "slots": { "type": { "name": "shape", - "description": "{ popoverContent?: elementType, preview?: elementType, signInButton?: elementType, signOutButton?: elementType }" + "description": "{ popover?: elementType, popoverContent?: elementType, preview?: elementType, signInButton?: elementType, signOutButton?: elementType }" }, "additionalInfo": { "slotsApi": true } } @@ -32,10 +32,16 @@ "default": "AccountPreview", "class": null }, + { + "name": "popover", + "description": "The component used for the account popover menu", + "default": "Popover", + "class": null + }, { "name": "popoverContent", "description": "The component used for the content of account popover", - "default": "Popover", + "default": "Stack", "class": null }, { diff --git a/docs/pages/toolpad/core/api/dashboard-layout.json b/docs/pages/toolpad/core/api/dashboard-layout.json index 8d5e4b39b1e..e8c7e9260b4 100644 --- a/docs/pages/toolpad/core/api/dashboard-layout.json +++ b/docs/pages/toolpad/core/api/dashboard-layout.json @@ -7,7 +7,7 @@ "slotProps": { "type": { "name": "shape", - "description": "{ sidebarFooter?: { mini: bool }, toolbarAccount?: { localeText?: { iconButtonAriaLabel?: string, signInLabel?: string, signOutLabel?: string }, slotProps?: { popover?: object, preview?: object, signInButton?: object, signOutButton?: object }, slots?: { popoverContent?: elementType, preview?: elementType, signInButton?: elementType, signOutButton?: elementType } }, toolbarActions?: object }" + "description": "{ sidebarFooter?: { mini: bool }, toolbarAccount?: { localeText?: { iconButtonAriaLabel?: string, signInLabel?: string, signOutLabel?: string }, slotProps?: { popover?: object, popoverContent?: object, preview?: object, signInButton?: object, signOutButton?: object }, slots?: { popover?: elementType, popoverContent?: elementType, preview?: elementType, signInButton?: elementType, signOutButton?: elementType } }, toolbarActions?: object }" }, "default": "{}" }, diff --git a/docs/translations/api-docs/account/account.json b/docs/translations/api-docs/account/account.json index 49e8459811b..de7187c1fcc 100644 --- a/docs/translations/api-docs/account/account.json +++ b/docs/translations/api-docs/account/account.json @@ -7,6 +7,7 @@ }, "classDescriptions": {}, "slotDescriptions": { + "popover": "The component used for the account popover menu", "popoverContent": "The component used for the content of account popover", "preview": "The component used for the account preview", "signInButton": "The component used for the sign in button.", diff --git a/packages/toolpad-core/src/Account/Account.tsx b/packages/toolpad-core/src/Account/Account.tsx index fc01c1df242..ceb81aa3527 100644 --- a/packages/toolpad-core/src/Account/Account.tsx +++ b/packages/toolpad-core/src/Account/Account.tsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import Button from '@mui/material/Button'; import Popover from '@mui/material/Popover'; import Divider from '@mui/material/Divider'; +import Stack from '@mui/material/Stack'; import { SignInButton } from './SignInButton'; import { SignOutButton } from './SignOutButton'; import { AccountPreview, AccountPreviewProps } from './AccountPreview'; @@ -18,9 +19,14 @@ export interface AccountSlots { */ preview?: React.ElementType; /** - * The component used for the content of account popover + * The component used for the account popover menu * @default Popover */ + popover?: React.ElementType; + /** + * The component used for the content of account popover + * @default Stack + */ popoverContent?: React.ElementType; /** * The component used for the sign in button. @@ -45,6 +51,7 @@ export interface AccountProps { slotProps?: { preview?: AccountPreviewProps; popover?: React.ComponentProps; + popoverContent?: React.ComponentProps; signInButton?: React.ComponentProps; signOutButton?: React.ComponentProps; }; @@ -93,53 +100,57 @@ function AccountContent(props: Omit) { {...slotProps?.preview} /> )} - + ) : ( + - {slots?.popoverContent ? ( - - ) : ( - - - - - - - - - - )} - + ...slotProps?.popover?.slotProps, + }} + > + {slots?.popoverContent ? ( + + ) : ( + + + + + + + + + + )} + + )} ); } @@ -220,6 +231,7 @@ Account.propTypes /* remove-proptypes */ = { */ slotProps: PropTypes.shape({ popover: PropTypes.object, + popoverContent: PropTypes.object, preview: PropTypes.shape({ handleClick: PropTypes.func, open: PropTypes.bool, @@ -242,6 +254,7 @@ Account.propTypes /* remove-proptypes */ = { * The components used for each slot inside. */ slots: PropTypes.shape({ + popover: PropTypes.elementType, popoverContent: PropTypes.elementType, preview: PropTypes.elementType, signInButton: PropTypes.elementType, diff --git a/packages/toolpad-core/src/Account/AccountPreview.test.tsx b/packages/toolpad-core/src/Account/AccountPreview.test.tsx index 7634e77eade..9024d9cef3a 100644 --- a/packages/toolpad-core/src/Account/AccountPreview.test.tsx +++ b/packages/toolpad-core/src/Account/AccountPreview.test.tsx @@ -36,6 +36,7 @@ describe('AccountPreview', () => { const avatar = screen.getByRole('img', { name: 'John Doe' }); expect(avatar).toBeInTheDocument(); + expect(screen.queryByText('John Doe')).not.toBeInTheDocument(); expect(avatar).toHaveAttribute('src', 'https://example.com/avatar.jpg'); }); diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx index 678aca83e20..3977ea9aeb4 100644 --- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx +++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx @@ -767,11 +767,13 @@ DashboardLayout.propTypes /* remove-proptypes */ = { }), slotProps: PropTypes.shape({ popover: PropTypes.object, + popoverContent: PropTypes.object, preview: PropTypes.object, signInButton: PropTypes.object, signOutButton: PropTypes.object, }), slots: PropTypes.shape({ + popover: PropTypes.elementType, popoverContent: PropTypes.elementType, preview: PropTypes.elementType, signInButton: PropTypes.elementType, From 1c8523d08e83bfc4615be570eaf44439a8fabfc2 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Fri, 18 Oct 2024 01:02:11 +0530 Subject: [PATCH 22/28] fix: Pedro review --- .../core/components/account/AccountCustomSlotProps.js | 3 ++- .../core/components/account/AccountCustomSlotProps.tsx | 4 ++-- docs/data/toolpad/core/components/account/CustomMenu.js | 7 +++++-- docs/data/toolpad/core/components/account/CustomMenu.tsx | 7 +++++-- packages/toolpad-core/src/Account/SignInButton.tsx | 2 +- packages/toolpad-core/src/internal/demo.tsx | 3 --- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/docs/data/toolpad/core/components/account/AccountCustomSlotProps.js b/docs/data/toolpad/core/components/account/AccountCustomSlotProps.js index fc680952444..3995c7e1345 100644 --- a/docs/data/toolpad/core/components/account/AccountCustomSlotProps.js +++ b/docs/data/toolpad/core/components/account/AccountCustomSlotProps.js @@ -1,6 +1,7 @@ import * as React from 'react'; import Logout from '@mui/icons-material/Logout'; -import { Account, AuthenticationContext, SessionContext } from '@toolpad/core'; +import { Account } from '@toolpad/core/Account'; +import { AuthenticationContext, SessionContext } from '@toolpad/core/AppProvider'; const demoSession = { user: { diff --git a/docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx b/docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx index 028be4c62b5..fcfa8bd028c 100644 --- a/docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx +++ b/docs/data/toolpad/core/components/account/AccountCustomSlotProps.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; import Logout from '@mui/icons-material/Logout'; +import { Account } from '@toolpad/core/Account'; import { - Account, AuthenticationContext, SessionContext, Session, -} from '@toolpad/core'; +} from '@toolpad/core/AppProvider'; const demoSession = { user: { diff --git a/docs/data/toolpad/core/components/account/CustomMenu.js b/docs/data/toolpad/core/components/account/CustomMenu.js index ac4933589b9..8325feff761 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.js +++ b/docs/data/toolpad/core/components/account/CustomMenu.js @@ -12,10 +12,13 @@ import { Avatar, Stack, } from '@mui/material'; -import { AccountPreview, SignOutButton } from '@toolpad/core'; +import { + AccountPreview, + SignOutButton, + AccountPopoverFooter, +} from '@toolpad/core/Account'; import FolderIcon from '@mui/icons-material/Folder'; import AddIcon from '@mui/icons-material/Add'; -import { AccountPopoverFooter } from '../../../../../../packages/toolpad-core/src/Account/AccountPopoverFooter'; const accounts = [ { diff --git a/docs/data/toolpad/core/components/account/CustomMenu.tsx b/docs/data/toolpad/core/components/account/CustomMenu.tsx index c1b6ebffe27..083e2df9c9b 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.tsx +++ b/docs/data/toolpad/core/components/account/CustomMenu.tsx @@ -11,10 +11,13 @@ import { Avatar, Stack, } from '@mui/material'; -import { AccountPreview, SignOutButton } from '@toolpad/core'; +import { + AccountPreview, + SignOutButton, + AccountPopoverFooter, +} from '@toolpad/core/Account'; import FolderIcon from '@mui/icons-material/Folder'; import AddIcon from '@mui/icons-material/Add'; -import { AccountPopoverFooter } from '../../../../../../packages/toolpad-core/src/Account/AccountPopoverFooter'; interface Project { id: number; diff --git a/packages/toolpad-core/src/Account/SignInButton.tsx b/packages/toolpad-core/src/Account/SignInButton.tsx index 4dad29fb285..9c67a964f05 100644 --- a/packages/toolpad-core/src/Account/SignInButton.tsx +++ b/packages/toolpad-core/src/Account/SignInButton.tsx @@ -3,7 +3,7 @@ import Button, { ButtonProps } from '@mui/material/Button'; import { AuthenticationContext } from '../AppProvider/AppProvider'; import { useLocaleText } from '../shared/locales/LocaleContext'; -export/** +export /** * * Demos: * diff --git a/packages/toolpad-core/src/internal/demo.tsx b/packages/toolpad-core/src/internal/demo.tsx index 18d629fbec6..0b41c363166 100644 --- a/packages/toolpad-core/src/internal/demo.tsx +++ b/packages/toolpad-core/src/internal/demo.tsx @@ -1,9 +1,6 @@ import * as React from 'react'; -import { DocsContext as Docs } from '../shared/context'; import { Router } from '../AppProvider'; -export const DocsContext = Docs; - /** * Internal utility for demos * @ignore - internal component. From 733434082e2566a1555b018ff8c4c6b80d02ed87 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Fri, 18 Oct 2024 01:10:32 +0530 Subject: [PATCH 23/28] fix: missed --- docs/pages/toolpad/core/react-sign-in-page/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/toolpad/core/react-sign-in-page/index.js b/docs/pages/toolpad/core/react-sign-in-page/index.js index 309f919b777..8c196df45e9 100644 --- a/docs/pages/toolpad/core/react-sign-in-page/index.js +++ b/docs/pages/toolpad/core/react-sign-in-page/index.js @@ -1,6 +1,6 @@ import * as React from 'react'; import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import { DocsContext } from '@toolpad/core/internals'; +import { DocsContext } from '@toolpad/core/internal'; import * as pageProps from '../../../../data/toolpad/core/components/sign-in-page/sign-in-page.md?muiMarkdown'; export default function Page() { From 9f3ae905f544a8cb59741375e5e52c1be183605e Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Fri, 18 Oct 2024 12:58:01 +0530 Subject: [PATCH 24/28] fix: App router support --- packages/toolpad-core/src/shared/locales/LocaleContext.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/toolpad-core/src/shared/locales/LocaleContext.tsx b/packages/toolpad-core/src/shared/locales/LocaleContext.tsx index da349ee51b8..abfb38d6d5d 100644 --- a/packages/toolpad-core/src/shared/locales/LocaleContext.tsx +++ b/packages/toolpad-core/src/shared/locales/LocaleContext.tsx @@ -1,3 +1,5 @@ +'use client'; + import * as React from 'react'; import DEFAULT_LOCALE_TEXT from './en'; From b95b1cf6608ab71e5c397566c308e26e9be6f66f Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Fri, 18 Oct 2024 13:09:09 +0530 Subject: [PATCH 25/28] fix: CI --- pnpm-lock.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd9cb2a2125..177e11a8b73 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -195,7 +195,7 @@ importers: version: 7.37.1(eslint@8.57.1) eslint-plugin-react-compiler: specifier: latest - version: 0.0.0-experimental-07a2ff2-20241017(eslint@8.57.1) + version: 19.0.0-beta-9ee70a1-20241017(eslint@8.57.1) eslint-plugin-react-hooks: specifier: 4.6.2 version: 4.6.2(eslint@8.57.1) @@ -6064,8 +6064,8 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-plugin-react-compiler@0.0.0-experimental-07a2ff2-20241017: - resolution: {integrity: sha512-rQq5RmA2ifLTh5XVdxksCfCzcisedUehoB0RX79pqt/c9yZO+p1ob4e2XFQ/ztz9hJmKuhPnu5g3zGZCXc7g1A==} + eslint-plugin-react-compiler@19.0.0-beta-9ee70a1-20241017: + resolution: {integrity: sha512-GdJHMa9Wqfc/JPiv4WW5JjQsuSISdBo7oM/6IjRO8uxaZncDrKK/RyFqbPvgEiNFzDcX8ZZvR8dgfSGvxh2Qpw==} engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} peerDependencies: eslint: '>=7' @@ -15886,7 +15886,7 @@ snapshots: globals: 13.24.0 rambda: 7.5.0 - eslint-plugin-react-compiler@0.0.0-experimental-07a2ff2-20241017(eslint@8.57.1): + eslint-plugin-react-compiler@19.0.0-beta-9ee70a1-20241017(eslint@8.57.1): dependencies: '@babel/core': 7.25.8 '@babel/parser': 7.25.8 From 18b0f3a06222ec6df07f41d0d841decced266482 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Fri, 18 Oct 2024 23:36:01 +0530 Subject: [PATCH 26/28] fix: Jan, Pedro review, CI --- .../components/account/AccountDemoSignedIn.js | 2 + .../account/AccountDemoSignedIn.tsx | 2 + .../account/AccountDemoSignedIn.tsx.preview | 6 +- .../account/AccountSlotsAccountSwitcher.js | 2 + .../account/AccountSlotsAccountSwitcher.tsx | 2 + .../AccountSlotsAccountSwitcher.tsx.preview | 14 +- .../components/account/AccountSlotsWallet.js | 126 ------------- .../components/account/AccountSlotsWallet.tsx | 130 -------------- .../account/AccountSlotsWallet.tsx.preview | 9 - .../core/components/account/CustomMenu.js | 165 ++---------------- .../core/components/account/CustomMenu.tsx | 165 ++---------------- .../core/components/account/account.md | 8 +- packages/toolpad-core/src/Account/Account.tsx | 4 +- .../src/Account/AccountPreview.tsx | 2 +- .../app/(dashboard)/SidebarFooterAccount.tsx | 104 +++++++++++ 15 files changed, 142 insertions(+), 599 deletions(-) delete mode 100644 docs/data/toolpad/core/components/account/AccountSlotsWallet.js delete mode 100644 docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx delete mode 100644 docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx.preview create mode 100644 playground/nextjs/src/app/(dashboard)/SidebarFooterAccount.tsx diff --git a/docs/data/toolpad/core/components/account/AccountDemoSignedIn.js b/docs/data/toolpad/core/components/account/AccountDemoSignedIn.js index c8b9b8a9c0c..5f8ea177353 100644 --- a/docs/data/toolpad/core/components/account/AccountDemoSignedIn.js +++ b/docs/data/toolpad/core/components/account/AccountDemoSignedIn.js @@ -26,7 +26,9 @@ export default function AccountDemoSignedIn() { return ( + {/* preview-start */} + {/* preview-end */} ); diff --git a/docs/data/toolpad/core/components/account/AccountDemoSignedIn.tsx b/docs/data/toolpad/core/components/account/AccountDemoSignedIn.tsx index 7cd00c266e1..718b4ed60fa 100644 --- a/docs/data/toolpad/core/components/account/AccountDemoSignedIn.tsx +++ b/docs/data/toolpad/core/components/account/AccountDemoSignedIn.tsx @@ -30,7 +30,9 @@ export default function AccountDemoSignedIn() { return ( + {/* preview-start */} + {/* preview-end */} ); diff --git a/docs/data/toolpad/core/components/account/AccountDemoSignedIn.tsx.preview b/docs/data/toolpad/core/components/account/AccountDemoSignedIn.tsx.preview index b0489ce20ca..e6abc8692e0 100644 --- a/docs/data/toolpad/core/components/account/AccountDemoSignedIn.tsx.preview +++ b/docs/data/toolpad/core/components/account/AccountDemoSignedIn.tsx.preview @@ -1,5 +1 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js index de8a60d8e3c..c938fa78e17 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js +++ b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.js @@ -27,11 +27,13 @@ export default function AccountSlotsAccountSwitcher() { return ( + {/* preview-start */} + {/* preview-end */} ); diff --git a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx index 1e934a7dff2..7e89f9663a3 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx +++ b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx @@ -31,11 +31,13 @@ export default function AccountSlotsAccountSwitcher() { return ( + {/* preview-start */} + {/* preview-end */} ); diff --git a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview index 6dd2f4d2c70..504347a380e 100644 --- a/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview +++ b/docs/data/toolpad/core/components/account/AccountSlotsAccountSwitcher.tsx.preview @@ -1,9 +1,5 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/toolpad/core/components/account/AccountSlotsWallet.js b/docs/data/toolpad/core/components/account/AccountSlotsWallet.js deleted file mode 100644 index 44de238600e..00000000000 --- a/docs/data/toolpad/core/components/account/AccountSlotsWallet.js +++ /dev/null @@ -1,126 +0,0 @@ -import * as React from 'react'; -import { - Avatar, - Button, - Divider, - Typography, - Stack, - IconButton, -} from '@mui/material'; -import WalletIcon from '@mui/icons-material/AccountBalance'; -import SendIcon from '@mui/icons-material/Send'; -import ShoppingCart from '@mui/icons-material/ShoppingCart'; -import CopyIcon from '@mui/icons-material/ContentCopy'; - -import { - Account, - AccountPreview, - AccountPopoverFooter, - SignOutButton, -} from '@toolpad/core/Account'; - -import { AuthenticationContext, SessionContext } from '@toolpad/core/AppProvider'; - -const demoSession = { - user: { - name: 'Bharat Kashyap', - email: 'bharatkashyap@outlook.com', - image: 'https://avatars.githubusercontent.com/u/19550456', - }, -}; - -const mockData = { - address: '0xb794f5ea0ba39494ce839613fffba74279579268', - balance: '1,234.56 ETH', - usdBalance: '$2,345,678.90 USD', -}; - -function CryptoWalletInfo() { - return ( - - - - - - - - - - - - {mockData.address} - - - - - - - Main Account - - - - - - - {mockData.balance} - - - {mockData.usdBalance} - - - - - - - - - - - ); -} - -export default function AccountSlotsWallet() { - const [session, setSession] = React.useState(demoSession); - const authentication = React.useMemo(() => { - return { - signIn: () => { - setSession(demoSession); - }, - signOut: () => { - setSession(null); - }, - }; - }, []); - - return ( - - - - - - ); -} diff --git a/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx b/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx deleted file mode 100644 index 4e7c63e82cb..00000000000 --- a/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import * as React from 'react'; -import { - Avatar, - Button, - Divider, - Typography, - Stack, - IconButton, -} from '@mui/material'; -import WalletIcon from '@mui/icons-material/AccountBalance'; -import SendIcon from '@mui/icons-material/Send'; -import ShoppingCart from '@mui/icons-material/ShoppingCart'; -import CopyIcon from '@mui/icons-material/ContentCopy'; - -import { - Account, - AccountPreview, - AccountPopoverFooter, - SignOutButton, -} from '@toolpad/core/Account'; - -import { - AuthenticationContext, - SessionContext, - Session, -} from '@toolpad/core/AppProvider'; - -const demoSession = { - user: { - name: 'Bharat Kashyap', - email: 'bharatkashyap@outlook.com', - image: 'https://avatars.githubusercontent.com/u/19550456', - }, -}; - -const mockData = { - address: '0xb794f5ea0ba39494ce839613fffba74279579268', - balance: '1,234.56 ETH', - usdBalance: '$2,345,678.90 USD', -}; - -function CryptoWalletInfo() { - return ( - - - - - - - - - - - - {mockData.address} - - - - - - - Main Account - - - - - - - {mockData.balance} - - - {mockData.usdBalance} - - - - - - - - - - - ); -} - -export default function AccountSlotsWallet() { - const [session, setSession] = React.useState(demoSession); - const authentication = React.useMemo(() => { - return { - signIn: () => { - setSession(demoSession); - }, - signOut: () => { - setSession(null); - }, - }; - }, []); - - return ( - - - - - - ); -} diff --git a/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx.preview b/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx.preview deleted file mode 100644 index 7241ae7a264..00000000000 --- a/docs/data/toolpad/core/components/account/AccountSlotsWallet.tsx.preview +++ /dev/null @@ -1,9 +0,0 @@ - - - - - \ No newline at end of file diff --git a/docs/data/toolpad/core/components/account/CustomMenu.js b/docs/data/toolpad/core/components/account/CustomMenu.js index 8325feff761..a06670c3be1 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.js +++ b/docs/data/toolpad/core/components/account/CustomMenu.js @@ -1,7 +1,5 @@ import * as React from 'react'; -import PropTypes from 'prop-types'; import { - Menu, MenuItem, MenuList, Button, @@ -17,7 +15,6 @@ import { SignOutButton, AccountPopoverFooter, } from '@toolpad/core/Account'; -import FolderIcon from '@mui/icons-material/Folder'; import AddIcon from '@mui/icons-material/Add'; const accounts = [ @@ -26,158 +23,16 @@ const accounts = [ 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 ProjectsList(props) { - const { open, anchorEl, handleMenuClose, handleEnter, handleLeave, projects } = - props; - - return ( - - { - handleEnter(); - }} - onMouseLeave={handleLeave} - > - - Projects - - - {projects?.map((project) => ( - - - - - - - ))} - - - - - ); -} - -ProjectsList.propTypes = { - anchorEl: PropTypes.object, - handleEnter: PropTypes.func.isRequired, - handleLeave: PropTypes.func.isRequired, - handleMenuClose: PropTypes.func.isRequired, - open: PropTypes.bool.isRequired, - projects: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.number.isRequired, - title: PropTypes.string.isRequired, - }), - ).isRequired, -}; - export default function CustomMenu() { - const mouseOnSubMenu = React.useRef(false); - const mouseOnMenuItem = React.useRef(false); - - const [selectedProjects, setSelectedProjects] = React.useState([]); - - const handleSelectProjects = React.useCallback((id) => { - setSelectedProjects( - accounts.find((account) => account.id === id)?.projects ?? [], - ); - }, []); - - const [subMenuAnchorEl, setSubMenuAnchorEl] = React.useState(null); - const subMenuOpen = Boolean(subMenuAnchorEl); - - const handleTriggerEnter = React.useCallback( - (event, id) => { - handleSelectProjects(id); - setSubMenuAnchorEl(event.currentTarget); - // Wait for 300ms to see if the mouse has moved to a menu item - setTimeout(() => { - mouseOnMenuItem.current = true; - }, 300); - }, - [handleSelectProjects], - ); - - const handleTriggerLeave = React.useCallback(() => { - mouseOnMenuItem.current = false; - // Wait for 320ms to see if the mouse has moved to the sub menu - // Timeout must be > 300ms to allow for `mouseOnMenuItem.current` to update - // inside `handleTriggerEnter` - setTimeout(() => { - if (mouseOnSubMenu.current || mouseOnMenuItem.current) { - return; - } - - setSubMenuAnchorEl(null); - }, 320); - }, []); - - const handleSubMenuEnter = React.useCallback(() => { - mouseOnSubMenu.current = true; - }, []); - - const handleSubMenuLeave = (event) => { - mouseOnSubMenu.current = false; - if (subMenuAnchorEl?.contains(event.relatedTarget)) { - return; - } - setSubMenuAnchorEl(null); - }; - - const handleSubMenuClose = React.useCallback(() => { - setSubMenuAnchorEl(null); - }, []); - return ( @@ -195,8 +50,6 @@ export default function CustomMenu() { width: '100%', columnGap: 2, }} - onMouseEnter={(event) => handleTriggerEnter(event, account.id)} - onMouseLeave={handleTriggerLeave} > ))} - + +
diff --git a/docs/data/toolpad/core/components/account/CustomMenu.tsx b/docs/data/toolpad/core/components/account/CustomMenu.tsx index 083e2df9c9b..a06670c3be1 100644 --- a/docs/data/toolpad/core/components/account/CustomMenu.tsx +++ b/docs/data/toolpad/core/components/account/CustomMenu.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { - Menu, MenuItem, MenuList, Button, @@ -16,168 +15,24 @@ import { SignOutButton, AccountPopoverFooter, } from '@toolpad/core/Account'; -import FolderIcon from '@mui/icons-material/Folder'; import AddIcon from '@mui/icons-material/Add'; -interface Project { - id: number; - title: string; -} - -interface ProjectsListProps { - open: boolean; - anchorEl: HTMLButtonElement | null; - handleMenuClose: () => void; - handleLeave: (event: React.MouseEvent) => void; - handleEnter: () => void; - projects: Project[]; -} - 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 ProjectsList(props: ProjectsListProps) { - const { open, anchorEl, handleMenuClose, handleEnter, handleLeave, projects } = - props; - - return ( - - { - handleEnter(); - }} - onMouseLeave={handleLeave} - > - - Projects - - - {projects?.map((project) => ( - - - - - - - ))} - - - - - ); -} - export default function CustomMenu() { - const mouseOnSubMenu = React.useRef(false); - const mouseOnMenuItem = React.useRef(false); - - const [selectedProjects, setSelectedProjects] = React.useState([]); - - const handleSelectProjects = React.useCallback((id: number) => { - setSelectedProjects( - accounts.find((account) => account.id === id)?.projects ?? [], - ); - }, []); - - const [subMenuAnchorEl, setSubMenuAnchorEl] = - React.useState(null); - const subMenuOpen = Boolean(subMenuAnchorEl); - - const handleTriggerEnter = React.useCallback( - (event: React.MouseEvent, id: number) => { - handleSelectProjects(id); - setSubMenuAnchorEl(event.currentTarget); - // Wait for 300ms to see if the mouse has moved to a menu item - setTimeout(() => { - mouseOnMenuItem.current = true; - }, 300); - }, - [handleSelectProjects], - ); - - const handleTriggerLeave = React.useCallback(() => { - mouseOnMenuItem.current = false; - // Wait for 320ms to see if the mouse has moved to the sub menu - // Timeout must be > 300ms to allow for `mouseOnMenuItem.current` to update - // inside `handleTriggerEnter` - setTimeout(() => { - if (mouseOnSubMenu.current || mouseOnMenuItem.current) { - return; - } - - setSubMenuAnchorEl(null); - }, 320); - }, []); - - const handleSubMenuEnter = React.useCallback(() => { - mouseOnSubMenu.current = true; - }, []); - - const handleSubMenuLeave = (event: React.MouseEvent) => { - mouseOnSubMenu.current = false; - if (subMenuAnchorEl?.contains(event.relatedTarget as Node)) { - return; - } - setSubMenuAnchorEl(null); - }; - - const handleSubMenuClose = React.useCallback(() => { - setSubMenuAnchorEl(null); - }, []); - return ( @@ -195,8 +50,6 @@ export default function CustomMenu() { width: '100%', columnGap: 2, }} - onMouseEnter={(event) => handleTriggerEnter(event, account.id)} - onMouseLeave={handleTriggerLeave} > ))} - + +
diff --git a/docs/data/toolpad/core/components/account/account.md b/docs/data/toolpad/core/components/account/account.md index b1117f6f9f9..a706c176a50 100644 --- a/docs/data/toolpad/core/components/account/account.md +++ b/docs/data/toolpad/core/components/account/account.md @@ -26,7 +26,7 @@ If a `session` object is present, the component is rendered as a dropdown contai When signed out, the component renders as an inline sign in button within the dashboard layout. -{{"demo": "AccountDemoSignedOut.js", "bg": "outlined" }} +{{"demo": "AccountDemoSignedOut.js", "bg": "outlined", "defaultCodeOpen": false }} ## Customization @@ -61,12 +61,6 @@ You can build advanced menus – such as a tenant switcher – by passing in a c {{"demo": "AccountSlotsAccountSwitcher.js", "bg": "outlined"}} -##### Crypto Wallet - -You can wrap the default `SignOutButton` with your own action buttons inside `AccountPopoverFooter` to customize the popover footer section: - -{{"demo": "AccountSlotsWallet.js", "bg": "outlined" }} - ### Labels You can pass in custom labels – including of different languages – using the `localeText` prop. diff --git a/packages/toolpad-core/src/Account/Account.tsx b/packages/toolpad-core/src/Account/Account.tsx index ceb81aa3527..d7c9aede327 100644 --- a/packages/toolpad-core/src/Account/Account.tsx +++ b/packages/toolpad-core/src/Account/Account.tsx @@ -101,7 +101,7 @@ function AccountContent(props: Omit) { /> )} {slots?.popover ? ( - + ) : ( ) { }} > {slots?.popoverContent ? ( - + ) : ( diff --git a/packages/toolpad-core/src/Account/AccountPreview.tsx b/packages/toolpad-core/src/Account/AccountPreview.tsx index 903bbe568f8..dc4455269c5 100644 --- a/packages/toolpad-core/src/Account/AccountPreview.tsx +++ b/packages/toolpad-core/src/Account/AccountPreview.tsx @@ -95,7 +95,7 @@ function AccountPreview(props: AccountPreviewProps) { return ( {avatarContent} - + {session.user?.name} diff --git a/playground/nextjs/src/app/(dashboard)/SidebarFooterAccount.tsx b/playground/nextjs/src/app/(dashboard)/SidebarFooterAccount.tsx new file mode 100644 index 00000000000..aceb55524f4 --- /dev/null +++ b/playground/nextjs/src/app/(dashboard)/SidebarFooterAccount.tsx @@ -0,0 +1,104 @@ +'use client'; + +import * as React from 'react'; + +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 { + AccountPreview, + AccountPopoverFooter, + SignOutButton, + AccountPreviewProps, +} from '@toolpad/core/Account'; + +export function AccountSidebarPreview(props: AccountPreviewProps) { + const { handleClick, open } = props; + return ( + + + + + ); +} + +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' }], + }, +]; + +export function SidebarFooterAccountPopover() { + return ( + + + Accounts + + + {accounts.map((account) => ( + + + + {account.name[0]} + + + + + ))} + + + + + + ); +} From ae9d39d0ecd36a3e2d44f8b4614562a010214633 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Sat, 19 Oct 2024 00:02:12 +0530 Subject: [PATCH 27/28] fix: simplify --- packages/toolpad-core/src/Account/Account.tsx | 75 +++---------------- 1 file changed, 11 insertions(+), 64 deletions(-) diff --git a/packages/toolpad-core/src/Account/Account.tsx b/packages/toolpad-core/src/Account/Account.tsx index d7c9aede327..bf80c7585d3 100644 --- a/packages/toolpad-core/src/Account/Account.tsx +++ b/packages/toolpad-core/src/Account/Account.tsx @@ -61,7 +61,8 @@ export interface AccountProps { localeText?: Partial>; } -function AccountContent(props: Omit) { +function Account(props: AccountProps) { + const { localeText } = props; const { slots, slotProps } = props; const [anchorEl, setAnchorEl] = React.useState(null); const session = React.useContext(SessionContext); @@ -81,15 +82,19 @@ function AccountContent(props: Omit) { } if (!session?.user) { - return slots?.signInButton ? ( - - ) : ( - + return ( + + {slots?.signInButton ? ( + + ) : ( + + )} + ); } return ( - + {slots?.preview ? ( ) : ( @@ -151,64 +156,6 @@ function AccountContent(props: Omit) { )} )} - - ); -} - -AccountContent.propTypes /* remove-proptypes */ = { - // ┌────────────────────────────── Warning ──────────────────────────────┐ - // │ These PropTypes are generated from the TypeScript type definitions. │ - // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ - // └─────────────────────────────────────────────────────────────────────┘ - /** - * The props used for each slot inside. - */ - slotProps: PropTypes.shape({ - popover: PropTypes.object, - preview: PropTypes.shape({ - handleClick: PropTypes.func, - open: PropTypes.bool, - slotProps: PropTypes.shape({ - avatar: PropTypes.object, - avatarIconButton: PropTypes.object, - moreIconButton: PropTypes.object, - }), - slots: PropTypes.shape({ - avatar: PropTypes.elementType, - }), - variant: PropTypes.oneOf(['condensed', 'expanded']), - }), - signInButton: PropTypes.object, - signOutButton: PropTypes.object, - }), - /** - * The components used for each slot inside. - */ - slots: PropTypes.shape({ - popoverContent: PropTypes.elementType, - preview: PropTypes.elementType, - signInButton: PropTypes.elementType, - signOutButton: PropTypes.elementType, - }), -} as any; -/** - * - * Demos: - * - * - [Account](https://mui.com/toolpad/core/react-account/) - * - [Dashboard Layout](https://mui.com/toolpad/core/react-dashboard-layout/) - * - [Sign-in Page](https://mui.com/toolpad/core/react-sign-in-page/) - * - * API: - * - * - [Account API](https://mui.com/toolpad/core/api/account) - */ -function Account(props: AccountProps) { - const { localeText, ...rest } = props; - - return ( - - ); } From 42c97d5fb0cbbc52a98d6acd35fa1f6d2b9c59a0 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Sat, 19 Oct 2024 00:10:28 +0530 Subject: [PATCH 28/28] fix: CI --- packages/toolpad-core/src/Account/Account.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/toolpad-core/src/Account/Account.tsx b/packages/toolpad-core/src/Account/Account.tsx index bf80c7585d3..b4aace2f797 100644 --- a/packages/toolpad-core/src/Account/Account.tsx +++ b/packages/toolpad-core/src/Account/Account.tsx @@ -60,7 +60,18 @@ export interface AccountProps { */ localeText?: Partial>; } - +/** + * + * Demos: + * + * - [Account](https://mui.com/toolpad/core/react-account/) + * - [Dashboard Layout](https://mui.com/toolpad/core/react-dashboard-layout/) + * - [Sign-in Page](https://mui.com/toolpad/core/react-sign-in-page/) + * + * API: + * + * - [Account API](https://mui.com/toolpad/core/api/account) + */ function Account(props: AccountProps) { const { localeText } = props; const { slots, slotProps } = props;