From d34cc79995d35af386aaa7103c9a93b7b8ff1e80 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Tue, 30 Jul 2024 22:23:20 +0100 Subject: [PATCH 1/4] Improve DashboardLayout docs --- .../app-provider/AppProviderBasic.js | 2 +- .../app-provider/AppProviderBasic.tsx | 2 +- .../app-provider/AppProviderTheme.js | 6 +- .../app-provider/AppProviderTheme.tsx | 6 +- .../dashboard-layout/DashboardLayoutBasic.js | 2 +- .../dashboard-layout/DashboardLayoutBasic.tsx | 2 +- .../DashboardLayoutBranding.js | 2 +- .../DashboardLayoutBranding.tsx | 2 +- .../DashboardLayoutNavigationActions.js | 86 +++---- .../DashboardLayoutNavigationActions.tsx | 87 +++---- ...shboardLayoutNavigationActions.tsx.preview | 46 +--- .../DashboardLayoutNavigationDividers.js | 94 ++++++++ .../DashboardLayoutNavigationDividers.tsx | 87 +++++++ ...hboardLayoutNavigationDividers.tsx.preview | 22 ++ .../DashboardLayoutNavigationHeadings.js | 101 ++++++++ .../DashboardLayoutNavigationHeadings.tsx | 94 ++++++++ ...hboardLayoutNavigationHeadings.tsx.preview | 29 +++ .../DashboardLayoutNavigationItems.js | 222 ------------------ .../DashboardLayoutNavigationItems.tsx | 215 ----------------- ...DashboardLayoutNavigationItems.tsx.preview | 149 ------------ .../DashboardLayoutNavigationLinks.js | 93 ++++++++ .../DashboardLayoutNavigationLinks.tsx | 86 +++++++ ...DashboardLayoutNavigationLinks.tsx.preview | 21 ++ .../DashboardLayoutNavigationNested.js | 101 ++++++++ .../DashboardLayoutNavigationNested.tsx | 94 ++++++++ ...ashboardLayoutNavigationNested.tsx.preview | 28 +++ .../dashboard-layout/dashboard-layout.md | 49 +++- .../toolpad/core/introduction/overview.md | 2 +- .../landing-core/ToolpadDashboardLayout.tsx | 4 +- examples/core-tutorial/app/layout.tsx | 2 +- .../DashboardLayout/DashboardLayout.test.tsx | 4 +- .../src/DashboardLayout/DashboardLayout.tsx | 2 +- .../src/nextjs/AppProvider.test.tsx | 2 +- playground/nextjs-pages/src/pages/_app.tsx | 3 +- 34 files changed, 1002 insertions(+), 745 deletions(-) create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.js create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.tsx create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.tsx.preview create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.js create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.tsx create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.tsx.preview delete mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.js delete mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.tsx delete mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.tsx.preview create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.js create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.tsx create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.tsx.preview create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.js create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.tsx create mode 100644 docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.tsx.preview diff --git a/docs/data/toolpad/core/components/app-provider/AppProviderBasic.js b/docs/data/toolpad/core/components/app-provider/AppProviderBasic.js index 35af75765dc..914bd2bed91 100644 --- a/docs/data/toolpad/core/components/app-provider/AppProviderBasic.js +++ b/docs/data/toolpad/core/components/app-provider/AppProviderBasic.js @@ -60,7 +60,7 @@ DemoPageContent.propTypes = { function AppProviderBasic(props) { const { window } = props; - const [pathname, setPathname] = React.useState('page'); + const [pathname, setPathname] = React.useState('/page'); const router = React.useMemo(() => { return { diff --git a/docs/data/toolpad/core/components/app-provider/AppProviderBasic.tsx b/docs/data/toolpad/core/components/app-provider/AppProviderBasic.tsx index d64b23039e4..224b603857a 100644 --- a/docs/data/toolpad/core/components/app-provider/AppProviderBasic.tsx +++ b/docs/data/toolpad/core/components/app-provider/AppProviderBasic.tsx @@ -64,7 +64,7 @@ interface DemoProps { export default function AppProviderBasic(props: DemoProps) { const { window } = props; - const [pathname, setPathname] = React.useState('page'); + const [pathname, setPathname] = React.useState('/page'); const router = React.useMemo(() => { return { diff --git a/docs/data/toolpad/core/components/app-provider/AppProviderTheme.js b/docs/data/toolpad/core/components/app-provider/AppProviderTheme.js index 2f6b4a86541..b7bc0013fe6 100644 --- a/docs/data/toolpad/core/components/app-provider/AppProviderTheme.js +++ b/docs/data/toolpad/core/components/app-provider/AppProviderTheme.js @@ -14,12 +14,12 @@ const NAVIGATION = [ title: 'Main items', }, { - segment: '/page', + segment: 'page', title: 'Page', icon: , }, { - segment: '/page-2', + segment: 'page-2', title: 'Page 2', icon: , }, @@ -78,7 +78,7 @@ DemoPageContent.propTypes = { function AppProviderTheme(props) { const { window } = props; - const [pathname, setPathname] = React.useState('page'); + const [pathname, setPathname] = React.useState('/page'); const router = React.useMemo(() => { return { diff --git a/docs/data/toolpad/core/components/app-provider/AppProviderTheme.tsx b/docs/data/toolpad/core/components/app-provider/AppProviderTheme.tsx index 51a6ecfda54..c94d09dcb90 100644 --- a/docs/data/toolpad/core/components/app-provider/AppProviderTheme.tsx +++ b/docs/data/toolpad/core/components/app-provider/AppProviderTheme.tsx @@ -14,12 +14,12 @@ const NAVIGATION: Navigation = [ title: 'Main items', }, { - segment: '/page', + segment: 'page', title: 'Page', icon: , }, { - segment: '/page-2', + segment: 'page-2', title: 'Page 2', icon: , }, @@ -82,7 +82,7 @@ interface DemoProps { export default function AppProviderTheme(props: DemoProps) { const { window } = props; - const [pathname, setPathname] = React.useState('page'); + const [pathname, setPathname] = React.useState('/page'); const router = React.useMemo(() => { return { diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBasic.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBasic.js index 8b5e7dc0466..a5daf4ad54f 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBasic.js +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBasic.js @@ -92,7 +92,7 @@ DemoPageContent.propTypes = { function DashboardLayoutBasic(props) { const { window } = props; - const [pathname, setPathname] = React.useState('dashboard'); + const [pathname, setPathname] = React.useState('/dashboard'); const router = React.useMemo(() => { return { diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBasic.tsx b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBasic.tsx index fd2b310d2cc..678b4b44122 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBasic.tsx +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBasic.tsx @@ -96,7 +96,7 @@ interface DemoProps { export default function DashboardLayoutBasic(props: DemoProps) { const { window } = props; - const [pathname, setPathname] = React.useState('dashboard'); + const [pathname, setPathname] = React.useState('/dashboard'); const router = React.useMemo(() => { return { diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBranding.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBranding.js index 605f383ea89..dd379a878d6 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBranding.js +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBranding.js @@ -56,7 +56,7 @@ DemoPageContent.propTypes = { function DashboardLayoutBranding(props) { const { window } = props; - const [pathname, setPathname] = React.useState('dashboard'); + const [pathname, setPathname] = React.useState('/dashboard'); const router = React.useMemo(() => { return { diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBranding.tsx b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBranding.tsx index d246ee44077..029946fbda3 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBranding.tsx +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutBranding.tsx @@ -60,7 +60,7 @@ interface DemoProps { export default function DashboardLayoutBranding(props: DemoProps) { const { window } = props; - const [pathname, setPathname] = React.useState('dashboard'); + const [pathname, setPathname] = React.useState('/dashboard'); const router = React.useMemo(() => { return { diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.js index eaf2dbbedea..5e3aad87442 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.js +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.js @@ -15,6 +15,21 @@ import CallReceivedIcon from '@mui/icons-material/CallReceived'; import { AppProvider } from '@toolpad/core/AppProvider'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; +const CALLS_NAVIGATION = [ + { + segment: '/made', + title: 'Made', + icon: , + action: , + }, + { + segment: '/received', + title: 'Received', + icon: , + action: , + }, +]; + const demoTheme = extendTheme({ breakpoints: { values: { @@ -50,7 +65,7 @@ DemoPageContent.propTypes = { function DashboardLayoutNavigationActions(props) { const { window } = props; - const [pathname, setPathname] = React.useState('contacts'); + const [pathname, setPathname] = React.useState('/contacts'); const router = React.useMemo(() => { return { @@ -78,60 +93,45 @@ function DashboardLayoutNavigationActions(props) { // Remove this const when copying and pasting into your project. const demoWindow = window !== undefined ? window() : undefined; + const popoverMenuAction = ( + + + + + + New call + Mark all as read + + + ); + return ( // preview-start , action: , }, { - segment: '/calls', + segment: 'calls', title: 'Calls', icon: , - action: ( - - - - - - New call - Mark all as read - - - ), - children: [ - { - segment: '/made', - title: 'Made', - icon: , - action: , - }, - { - segment: '/received', - title: 'Received', - icon: , - action: , - }, - ], + action: popoverMenuAction, + children: CALLS_NAVIGATION, }, ]} router={router} diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx index e5623b8c2fc..5be59d990a1 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx @@ -13,6 +13,22 @@ import CallMadeIcon from '@mui/icons-material/CallMade'; import CallReceivedIcon from '@mui/icons-material/CallReceived'; import { AppProvider, Router } from '@toolpad/core/AppProvider'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; +import type { Navigation } from '@toolpad/core'; + +const CALLS_NAVIGATION: Navigation = [ + { + segment: '/made', + title: 'Made', + icon: , + action: , + }, + { + segment: '/received', + title: 'Received', + icon: , + action: , + }, +]; const demoTheme = extendTheme({ breakpoints: { @@ -53,7 +69,7 @@ interface DemoProps { export default function DashboardLayoutNavigationActions(props: DemoProps) { const { window } = props; - const [pathname, setPathname] = React.useState('contacts'); + const [pathname, setPathname] = React.useState('/contacts'); const router = React.useMemo(() => { return { @@ -82,60 +98,45 @@ export default function DashboardLayoutNavigationActions(props: DemoProps) { // Remove this const when copying and pasting into your project. const demoWindow = window !== undefined ? window() : undefined; + const popoverMenuAction = ( + + + + + + New call + Mark all as read + + + ); + return ( // preview-start , action: , }, { - segment: '/calls', + segment: 'calls', title: 'Calls', icon: , - action: ( - - - - - - New call - Mark all as read - - - ), - children: [ - { - segment: '/made', - title: 'Made', - icon: , - action: , - }, - { - segment: '/received', - title: 'Received', - icon: , - action: , - }, - ], + action: popoverMenuAction, + children: CALLS_NAVIGATION, }, ]} router={router} diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx.preview b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx.preview index 6d82cfe85d1..5e09aae5dfb 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx.preview +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx.preview @@ -1,55 +1,17 @@ , action: , }, { - segment: '/calls', + segment: 'calls', title: 'Calls', icon: , - action: ( - - - - - - New call - Mark all as read - - - ), - children: [ - { - segment: '/made', - title: 'Made', - icon: , - action: , - }, - { - segment: '/received', - title: 'Received', - icon: , - action: , - }, - ], + action: popoverMenuAction, + children: CALLS_NAVIGATION, }, ]} router={router} diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.js new file mode 100644 index 00000000000..78b469b06a1 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.js @@ -0,0 +1,94 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { extendTheme } from '@mui/material/styles'; +import DescriptionIcon from '@mui/icons-material/Description'; +import { AppProvider } from '@toolpad/core/AppProvider'; +import { DashboardLayout } from '@toolpad/core/DashboardLayout'; + +const demoTheme = extendTheme({ + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +function DemoPageContent({ pathname }) { + return ( + + Dashboard content for {pathname} + + ); +} + +DemoPageContent.propTypes = { + pathname: PropTypes.string.isRequired, +}; + +function DashboardLayoutNavigationDividers(props) { + const { window } = props; + + const [pathname, setPathname] = React.useState('/star-wars'); + + const router = React.useMemo(() => { + return { + pathname, + searchParams: new URLSearchParams(), + navigate: (path) => setPathname(String(path)), + }; + }, [pathname]); + + // Remove this const when copying and pasting into your project. + const demoWindow = window !== undefined ? window() : undefined; + + return ( + // preview-start + , + }, + { kind: 'divider' }, + { + segment: 'eagle', + title: 'Eagle', + icon: , + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} + > + + + + + // preview-end + ); +} + +DashboardLayoutNavigationDividers.propTypes = { + /** + * Injected by the documentation to work in an iframe. + * Remove this when copying and pasting into your project. + */ + window: PropTypes.func, +}; + +export default DashboardLayoutNavigationDividers; diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.tsx b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.tsx new file mode 100644 index 00000000000..a19e4ea8ce7 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.tsx @@ -0,0 +1,87 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { extendTheme } from '@mui/material/styles'; +import DescriptionIcon from '@mui/icons-material/Description'; +import { AppProvider, Router } from '@toolpad/core/AppProvider'; +import { DashboardLayout } from '@toolpad/core/DashboardLayout'; + +const demoTheme = extendTheme({ + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +function DemoPageContent({ pathname }: { pathname: string }) { + return ( + + Dashboard content for {pathname} + + ); +} + +interface DemoProps { + /** + * Injected by the documentation to work in an iframe. + * Remove this when copying and pasting into your project. + */ + window?: () => Window; +} + +export default function DashboardLayoutNavigationDividers(props: DemoProps) { + const { window } = props; + + const [pathname, setPathname] = React.useState('/star-wars'); + + const router = React.useMemo(() => { + return { + pathname, + searchParams: new URLSearchParams(), + navigate: (path) => setPathname(String(path)), + }; + }, [pathname]); + + // Remove this const when copying and pasting into your project. + const demoWindow = window !== undefined ? window() : undefined; + + return ( + // preview-start + , + }, + { kind: 'divider' }, + { + segment: 'eagle', + title: 'Eagle', + icon: , + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} + > + + + + + // preview-end + ); +} diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.tsx.preview b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.tsx.preview new file mode 100644 index 00000000000..d6883665d81 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationDividers.tsx.preview @@ -0,0 +1,22 @@ +, + }, + { kind: 'divider' }, + { + segment: 'eagle', + title: 'Eagle', + icon: , + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} +> + + + + \ No newline at end of file diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.js new file mode 100644 index 00000000000..8555c6c14c4 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.js @@ -0,0 +1,101 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { extendTheme } from '@mui/material/styles'; +import DescriptionIcon from '@mui/icons-material/Description'; +import { AppProvider } from '@toolpad/core/AppProvider'; +import { DashboardLayout } from '@toolpad/core/DashboardLayout'; + +const demoTheme = extendTheme({ + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +function DemoPageContent({ pathname }) { + return ( + + Dashboard content for {pathname} + + ); +} + +DemoPageContent.propTypes = { + pathname: PropTypes.string.isRequired, +}; + +function DashboardLayoutNavigationHeadings(props) { + const { window } = props; + + const [pathname, setPathname] = React.useState('/lion'); + + const router = React.useMemo(() => { + return { + pathname, + searchParams: new URLSearchParams(), + navigate: (path) => setPathname(String(path)), + }; + }, [pathname]); + + // Remove this const when copying and pasting into your project. + const demoWindow = window !== undefined ? window() : undefined; + + return ( + // preview-start + , + }, + { + kind: 'header', + title: 'Movies', + }, + { + segment: 'lord-of-the-rings', + title: 'Lord of the Rings', + icon: , + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} + > + + + + + // preview-end + ); +} + +DashboardLayoutNavigationHeadings.propTypes = { + /** + * Injected by the documentation to work in an iframe. + * Remove this when copying and pasting into your project. + */ + window: PropTypes.func, +}; + +export default DashboardLayoutNavigationHeadings; diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.tsx b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.tsx new file mode 100644 index 00000000000..8ceb856a961 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.tsx @@ -0,0 +1,94 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { extendTheme } from '@mui/material/styles'; +import DescriptionIcon from '@mui/icons-material/Description'; +import { AppProvider, Router } from '@toolpad/core/AppProvider'; +import { DashboardLayout } from '@toolpad/core/DashboardLayout'; + +const demoTheme = extendTheme({ + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +function DemoPageContent({ pathname }: { pathname: string }) { + return ( + + Dashboard content for {pathname} + + ); +} + +interface DemoProps { + /** + * Injected by the documentation to work in an iframe. + * Remove this when copying and pasting into your project. + */ + window?: () => Window; +} + +export default function DashboardLayoutNavigationHeadings(props: DemoProps) { + const { window } = props; + + const [pathname, setPathname] = React.useState('/lion'); + + const router = React.useMemo(() => { + return { + pathname, + searchParams: new URLSearchParams(), + navigate: (path) => setPathname(String(path)), + }; + }, [pathname]); + + // Remove this const when copying and pasting into your project. + const demoWindow = window !== undefined ? window() : undefined; + + return ( + // preview-start + , + }, + { + kind: 'header', + title: 'Movies', + }, + { + segment: 'lord-of-the-rings', + title: 'Lord of the Rings', + icon: , + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} + > + + + + + // preview-end + ); +} diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.tsx.preview b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.tsx.preview new file mode 100644 index 00000000000..35a5f93e6e2 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationHeadings.tsx.preview @@ -0,0 +1,29 @@ +, + }, + { + kind: 'header', + title: 'Movies', + }, + { + segment: 'lord-of-the-rings', + title: 'Lord of the Rings', + icon: , + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} +> + + + + \ No newline at end of file diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.js deleted file mode 100644 index 8ca6ba156a7..00000000000 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.js +++ /dev/null @@ -1,222 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import Box from '@mui/material/Box'; -import Typography from '@mui/material/Typography'; -import { extendTheme } from '@mui/material/styles'; -import DescriptionIcon from '@mui/icons-material/Description'; -import FolderIcon from '@mui/icons-material/Folder'; -import { AppProvider } from '@toolpad/core/AppProvider'; -import { DashboardLayout } from '@toolpad/core/DashboardLayout'; - -const demoTheme = extendTheme({ - breakpoints: { - values: { - xs: 0, - sm: 600, - md: 600, - lg: 1200, - xl: 1536, - }, - }, -}); - -function DemoPageContent({ pathname }) { - return ( - - Dashboard content for {pathname} - - ); -} - -DemoPageContent.propTypes = { - pathname: PropTypes.string.isRequired, -}; - -function DashboardLayoutNavigationItems(props) { - const { window } = props; - - const [pathname, setPathname] = React.useState('home'); - - const router = React.useMemo(() => { - return { - pathname, - searchParams: new URLSearchParams(), - navigate: (path) => setPathname(String(path)), - }; - }, [pathname]); - - // Remove this const when copying and pasting into your project. - const demoWindow = window !== undefined ? window() : undefined; - - return ( - // preview-start - , - }, - { - segment: 'about', - title: 'About Us', - icon: , - }, - { - segment: 'movies', - title: 'Movies', - icon: , - children: [ - { - segment: 'fantasy', - title: 'Fantasy', - icon: , - children: [ - { - kind: 'header', - title: 'Epic Fantasy', - }, - { - segment: 'lord-of-the-rings', - title: 'Lord of the Rings', - icon: , - }, - { - segment: 'harry-potter', - title: 'Harry Potter', - icon: , - }, - { kind: 'divider' }, - { - kind: 'header', - title: 'Modern Fantasy', - }, - { - segment: 'chronicles-of-narnia', - title: 'Chronicles of Narnia', - icon: , - }, - ], - }, - { - segment: 'action', - title: 'Action', - icon: , - children: [ - { - segment: 'mad-max', - title: 'Mad Max', - icon: , - }, - { - segment: 'die-hard', - title: 'Die Hard', - icon: , - }, - ], - }, - { - segment: 'sci-fi', - title: 'Sci-Fi', - icon: , - children: [ - { - segment: 'star-wars', - title: 'Star Wars', - icon: , - }, - { - segment: 'matrix', - title: 'The Matrix', - icon: , - }, - ], - }, - ], - }, - { kind: 'divider' }, - { - kind: 'header', - title: 'Animals', - }, - { - segment: 'mammals', - title: 'Mammals', - icon: , - children: [ - { - segment: 'lion', - title: 'Lion', - icon: , - }, - { - segment: 'elephant', - title: 'Elephant', - icon: , - }, - ], - }, - { - segment: 'birds', - title: 'Birds', - icon: , - children: [ - { - segment: 'eagle', - title: 'Eagle', - icon: , - }, - { - segment: 'parrot', - title: 'Parrot', - icon: , - }, - ], - }, - { - segment: 'reptiles', - title: 'Reptiles', - icon: , - children: [ - { - segment: 'crocodile', - title: 'Crocodile', - icon: , - }, - { - segment: 'snake', - title: 'Snake', - icon: , - }, - ], - }, - ]} - router={router} - theme={demoTheme} - window={demoWindow} - > - - - - - // preview-end - ); -} - -DashboardLayoutNavigationItems.propTypes = { - /** - * Injected by the documentation to work in an iframe. - * Remove this when copying and pasting into your project. - */ - window: PropTypes.func, -}; - -export default DashboardLayoutNavigationItems; diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.tsx b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.tsx deleted file mode 100644 index 7597bb58ef0..00000000000 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.tsx +++ /dev/null @@ -1,215 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/material/Box'; -import Typography from '@mui/material/Typography'; -import { extendTheme } from '@mui/material/styles'; -import DescriptionIcon from '@mui/icons-material/Description'; -import FolderIcon from '@mui/icons-material/Folder'; -import { AppProvider, Router } from '@toolpad/core/AppProvider'; -import { DashboardLayout } from '@toolpad/core/DashboardLayout'; - -const demoTheme = extendTheme({ - breakpoints: { - values: { - xs: 0, - sm: 600, - md: 600, - lg: 1200, - xl: 1536, - }, - }, -}); - -function DemoPageContent({ pathname }: { pathname: string }) { - return ( - - Dashboard content for {pathname} - - ); -} - -interface DemoProps { - /** - * Injected by the documentation to work in an iframe. - * Remove this when copying and pasting into your project. - */ - window?: () => Window; -} - -export default function DashboardLayoutNavigationItems(props: DemoProps) { - const { window } = props; - - const [pathname, setPathname] = React.useState('home'); - - const router = React.useMemo(() => { - return { - pathname, - searchParams: new URLSearchParams(), - navigate: (path) => setPathname(String(path)), - }; - }, [pathname]); - - // Remove this const when copying and pasting into your project. - const demoWindow = window !== undefined ? window() : undefined; - - return ( - // preview-start - , - }, - { - segment: 'about', - title: 'About Us', - icon: , - }, - { - segment: 'movies', - title: 'Movies', - icon: , - children: [ - { - segment: 'fantasy', - title: 'Fantasy', - icon: , - children: [ - { - kind: 'header', - title: 'Epic Fantasy', - }, - { - segment: 'lord-of-the-rings', - title: 'Lord of the Rings', - icon: , - }, - { - segment: 'harry-potter', - title: 'Harry Potter', - icon: , - }, - { kind: 'divider' }, - { - kind: 'header', - title: 'Modern Fantasy', - }, - { - segment: 'chronicles-of-narnia', - title: 'Chronicles of Narnia', - icon: , - }, - ], - }, - { - segment: 'action', - title: 'Action', - icon: , - children: [ - { - segment: 'mad-max', - title: 'Mad Max', - icon: , - }, - { - segment: 'die-hard', - title: 'Die Hard', - icon: , - }, - ], - }, - { - segment: 'sci-fi', - title: 'Sci-Fi', - icon: , - children: [ - { - segment: 'star-wars', - title: 'Star Wars', - icon: , - }, - { - segment: 'matrix', - title: 'The Matrix', - icon: , - }, - ], - }, - ], - }, - { kind: 'divider' }, - { - kind: 'header', - title: 'Animals', - }, - { - segment: 'mammals', - title: 'Mammals', - icon: , - children: [ - { - segment: 'lion', - title: 'Lion', - icon: , - }, - { - segment: 'elephant', - title: 'Elephant', - icon: , - }, - ], - }, - { - segment: 'birds', - title: 'Birds', - icon: , - children: [ - { - segment: 'eagle', - title: 'Eagle', - icon: , - }, - { - segment: 'parrot', - title: 'Parrot', - icon: , - }, - ], - }, - { - segment: 'reptiles', - title: 'Reptiles', - icon: , - children: [ - { - segment: 'crocodile', - title: 'Crocodile', - icon: , - }, - { - segment: 'snake', - title: 'Snake', - icon: , - }, - ], - }, - ]} - router={router} - theme={demoTheme} - window={demoWindow} - > - - - - - // preview-end - ); -} diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.tsx.preview b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.tsx.preview deleted file mode 100644 index 33bfbb2304c..00000000000 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationItems.tsx.preview +++ /dev/null @@ -1,149 +0,0 @@ -, - }, - { - segment: 'about', - title: 'About Us', - icon: , - }, - { - segment: 'movies', - title: 'Movies', - icon: , - children: [ - { - segment: 'fantasy', - title: 'Fantasy', - icon: , - children: [ - { - kind: 'header', - title: 'Epic Fantasy', - }, - { - segment: 'lord-of-the-rings', - title: 'Lord of the Rings', - icon: , - }, - { - segment: 'harry-potter', - title: 'Harry Potter', - icon: , - }, - { kind: 'divider' }, - { - kind: 'header', - title: 'Modern Fantasy', - }, - { - segment: 'chronicles-of-narnia', - title: 'Chronicles of Narnia', - icon: , - }, - ], - }, - { - segment: 'action', - title: 'Action', - icon: , - children: [ - { - segment: 'mad-max', - title: 'Mad Max', - icon: , - }, - { - segment: 'die-hard', - title: 'Die Hard', - icon: , - }, - ], - }, - { - segment: 'sci-fi', - title: 'Sci-Fi', - icon: , - children: [ - { - segment: 'star-wars', - title: 'Star Wars', - icon: , - }, - { - segment: 'matrix', - title: 'The Matrix', - icon: , - }, - ], - }, - ], - }, - { kind: 'divider' }, - { - kind: 'header', - title: 'Animals', - }, - { - segment: 'mammals', - title: 'Mammals', - icon: , - children: [ - { - segment: 'lion', - title: 'Lion', - icon: , - }, - { - segment: 'elephant', - title: 'Elephant', - icon: , - }, - ], - }, - { - segment: 'birds', - title: 'Birds', - icon: , - children: [ - { - segment: 'eagle', - title: 'Eagle', - icon: , - }, - { - segment: 'parrot', - title: 'Parrot', - icon: , - }, - ], - }, - { - segment: 'reptiles', - title: 'Reptiles', - icon: , - children: [ - { - segment: 'crocodile', - title: 'Crocodile', - icon: , - }, - { - segment: 'snake', - title: 'Snake', - icon: , - }, - ], - }, - ]} - router={router} - theme={demoTheme} - window={demoWindow} -> - - - - \ No newline at end of file diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.js new file mode 100644 index 00000000000..086ca539564 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.js @@ -0,0 +1,93 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { extendTheme } from '@mui/material/styles'; +import DescriptionIcon from '@mui/icons-material/Description'; +import { AppProvider } from '@toolpad/core/AppProvider'; +import { DashboardLayout } from '@toolpad/core/DashboardLayout'; + +const demoTheme = extendTheme({ + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +function DemoPageContent({ pathname }) { + return ( + + Dashboard content for {pathname} + + ); +} + +DemoPageContent.propTypes = { + pathname: PropTypes.string.isRequired, +}; + +function DashboardLayoutNavigationLinks(props) { + const { window } = props; + + const [pathname, setPathname] = React.useState('/home'); + + const router = React.useMemo(() => { + return { + pathname, + searchParams: new URLSearchParams(), + navigate: (path) => setPathname(String(path)), + }; + }, [pathname]); + + // Remove this const when copying and pasting into your project. + const demoWindow = window !== undefined ? window() : undefined; + + return ( + // preview-start + , + }, + { + segment: 'about', + title: 'About Us', + icon: , + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} + > + + + + + // preview-end + ); +} + +DashboardLayoutNavigationLinks.propTypes = { + /** + * Injected by the documentation to work in an iframe. + * Remove this when copying and pasting into your project. + */ + window: PropTypes.func, +}; + +export default DashboardLayoutNavigationLinks; diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.tsx b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.tsx new file mode 100644 index 00000000000..e5a1e172df3 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.tsx @@ -0,0 +1,86 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { extendTheme } from '@mui/material/styles'; +import DescriptionIcon from '@mui/icons-material/Description'; +import { AppProvider, Router } from '@toolpad/core/AppProvider'; +import { DashboardLayout } from '@toolpad/core/DashboardLayout'; + +const demoTheme = extendTheme({ + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +function DemoPageContent({ pathname }: { pathname: string }) { + return ( + + Dashboard content for {pathname} + + ); +} + +interface DemoProps { + /** + * Injected by the documentation to work in an iframe. + * Remove this when copying and pasting into your project. + */ + window?: () => Window; +} + +export default function DashboardLayoutNavigationLinks(props: DemoProps) { + const { window } = props; + + const [pathname, setPathname] = React.useState('/home'); + + const router = React.useMemo(() => { + return { + pathname, + searchParams: new URLSearchParams(), + navigate: (path) => setPathname(String(path)), + }; + }, [pathname]); + + // Remove this const when copying and pasting into your project. + const demoWindow = window !== undefined ? window() : undefined; + + return ( + // preview-start + , + }, + { + segment: 'about', + title: 'About Us', + icon: , + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} + > + + + + + // preview-end + ); +} diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.tsx.preview b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.tsx.preview new file mode 100644 index 00000000000..3c159f307c4 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationLinks.tsx.preview @@ -0,0 +1,21 @@ +, + }, + { + segment: 'about', + title: 'About Us', + icon: , + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} +> + + + + \ No newline at end of file diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.js new file mode 100644 index 00000000000..eaccc97416c --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.js @@ -0,0 +1,101 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { extendTheme } from '@mui/material/styles'; +import DescriptionIcon from '@mui/icons-material/Description'; +import FolderIcon from '@mui/icons-material/Folder'; +import { AppProvider } from '@toolpad/core/AppProvider'; +import { DashboardLayout } from '@toolpad/core/DashboardLayout'; + +const demoTheme = extendTheme({ + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +function DemoPageContent({ pathname }) { + return ( + + Dashboard content for {pathname} + + ); +} + +DemoPageContent.propTypes = { + pathname: PropTypes.string.isRequired, +}; + +function DashboardLayoutNavigationNested(props) { + const { window } = props; + + const [pathname, setPathname] = React.useState('/movies/lord-of-the-rings'); + + const router = React.useMemo(() => { + return { + pathname, + searchParams: new URLSearchParams(), + navigate: (path) => setPathname(String(path)), + }; + }, [pathname]); + + // Remove this const when copying and pasting into your project. + const demoWindow = window !== undefined ? window() : undefined; + + return ( + // preview-start + , + children: [ + { + segment: 'lord-of-the-rings', + title: 'Lord of the Rings', + icon: , + }, + { + segment: 'harry-potter', + title: 'Harry Potter', + icon: , + }, + ], + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} + > + + + + + // preview-end + ); +} + +DashboardLayoutNavigationNested.propTypes = { + /** + * Injected by the documentation to work in an iframe. + * Remove this when copying and pasting into your project. + */ + window: PropTypes.func, +}; + +export default DashboardLayoutNavigationNested; diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.tsx b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.tsx new file mode 100644 index 00000000000..d7aa63cfea1 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.tsx @@ -0,0 +1,94 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { extendTheme } from '@mui/material/styles'; +import DescriptionIcon from '@mui/icons-material/Description'; +import FolderIcon from '@mui/icons-material/Folder'; +import { AppProvider, Router } from '@toolpad/core/AppProvider'; +import { DashboardLayout } from '@toolpad/core/DashboardLayout'; + +const demoTheme = extendTheme({ + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +function DemoPageContent({ pathname }: { pathname: string }) { + return ( + + Dashboard content for {pathname} + + ); +} + +interface DemoProps { + /** + * Injected by the documentation to work in an iframe. + * Remove this when copying and pasting into your project. + */ + window?: () => Window; +} + +export default function DashboardLayoutNavigationNested(props: DemoProps) { + const { window } = props; + + const [pathname, setPathname] = React.useState('/movies/lord-of-the-rings'); + + const router = React.useMemo(() => { + return { + pathname, + searchParams: new URLSearchParams(), + navigate: (path) => setPathname(String(path)), + }; + }, [pathname]); + + // Remove this const when copying and pasting into your project. + const demoWindow = window !== undefined ? window() : undefined; + + return ( + // preview-start + , + children: [ + { + segment: 'lord-of-the-rings', + title: 'Lord of the Rings', + icon: , + }, + { + segment: 'harry-potter', + title: 'Harry Potter', + icon: , + }, + ], + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} + > + + + + + // preview-end + ); +} diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.tsx.preview b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.tsx.preview new file mode 100644 index 00000000000..efc79cf2812 --- /dev/null +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationNested.tsx.preview @@ -0,0 +1,28 @@ +, + children: [ + { + segment: 'lord-of-the-rings', + title: 'Lord of the Rings', + icon: , + }, + { + segment: 'harry-potter', + title: 'Harry Potter', + icon: , + }, + ], + }, + ]} + router={router} + theme={demoTheme} + window={demoWindow} +> + + + + \ No newline at end of file diff --git a/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md b/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md index 44f31f12474..b0195c0f540 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md +++ b/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md @@ -26,7 +26,7 @@ Some elements of the `DashboardLayout` can be configured to match your personali This can be done via the `branding` prop in the [AppProvider](https://mui.com/toolpad/core/react-app-provider/), which allows for setting a custom `logo` image or `title` text in the page header. -{{"demo": "DashboardLayoutBranding.js", "height": 500, "iframe": true}} +{{"demo": "DashboardLayoutBranding.js", "height": 400, "iframe": true}} ## Navigation @@ -34,19 +34,50 @@ The `navigation` prop in the [AppProvider](https://mui.com/toolpad/core/react-ap The flexibility in composing and ordering these different elements allows for a great variety of navigation structures to fit your use case. -### Navigation Items +### Navigation Links -The main navigation items that can be used are: +Navigation links can be placed in the sidebar as items with the format: -- **Links:** `{ segment: '/home', title: 'Home', icon: }`; -- **Headings:** `{ kind: 'header', title: 'Epic Fantasy' }`; -- **Dividers:** `{ kind: 'divider' }`; -- **Collapsible nested navigation:** `{ title: 'Fantasy', icon: , children: [ ... ] }`. +```tsx +{ segment: 'home', title: 'Home', icon: } +``` -{{"demo": "DashboardLayoutNavigationItems.js", "height": 640, "iframe": true}} +{{"demo": "DashboardLayoutNavigationLinks.js", "height": 400, "iframe": true}} + +### Navigation Headings + +Navigation headings can be placed in the sidebar as items with the format: + +```tsx +{ kind: 'header', title: 'Epic Fantasy' } +``` + +{{"demo": "DashboardLayoutNavigationHeadings.js", "height": 400, "iframe": true}} + +### Navigation Dividers + +Dividers can can be placed between items in the sidebar as items with the format: + +```tsx +{ + kind: 'divider'; +} +``` + +{{"demo": "DashboardLayoutNavigationDividers.js", "height": 400, "iframe": true}} + +### Nested Navigation + +Nested navigation structures can be placed in the sidebar as items with the format: + +```tsx +{ title: 'Fantasy', icon: , children: [ ... ] } +``` + +{{"demo": "DashboardLayoutNavigationNested.js", "height": 400, "iframe": true}} ### Navigation Actions Navigation links have an optional `action` prop that can be used to render any content on the right-side of the respective list item, such as badges with numbers, or buttons to toggle a popover menu. -{{"demo": "DashboardLayoutNavigationActions.js", "height": 500, "iframe": true}} +{{"demo": "DashboardLayoutNavigationActions.js", "height": 400, "iframe": true}} diff --git a/docs/data/toolpad/core/introduction/overview.md b/docs/data/toolpad/core/introduction/overview.md index a2530965468..231582ecb49 100644 --- a/docs/data/toolpad/core/introduction/overview.md +++ b/docs/data/toolpad/core/introduction/overview.md @@ -8,7 +8,7 @@ title: Toolpad Overview This framework leverages the existing suite of components offered by MUI, and ties them together with the most commonly-used backend integrations to help you create dashboards fast. Imagine a React dashboard template but with backend features like authentication, role-based access control and data fetching already included. It comes with the guarantee of MUI's enterprise-tested components, and the Toolpad team's focus on using the latest stable libraries, and prioritising razor-sharp performance. -{{"demo": "../components/dashboard-layout/DashboardLayoutNavigationItems.js", "height": 640, "iframe": true}} +{{"demo": "../components/dashboard-layout/DashboardLayoutNavigationLinks.js", "height": 640, "iframe": true}} ## Overview diff --git a/docs/src/components/landing-core/ToolpadDashboardLayout.tsx b/docs/src/components/landing-core/ToolpadDashboardLayout.tsx index 59c9a9fce6a..20bb4eb3468 100644 --- a/docs/src/components/landing-core/ToolpadDashboardLayout.tsx +++ b/docs/src/components/landing-core/ToolpadDashboardLayout.tsx @@ -64,7 +64,7 @@ const NAVIGATION: Navigation = [ ]; function DashboardLayoutBasic() { - const [pathname, setPathname] = React.useState('dashboard'); + const [pathname, setPathname] = React.useState('/dashboard'); const router = React.useMemo(() => { return { @@ -153,7 +153,7 @@ const PlaceHolder = styled('div')<{ height: number }>(({ theme, height }) => ({ function DashboardLayoutBasic(props: DemoProps) { const { window } = props; - const [pathname, setPathname] = React.useState('page'); + const [pathname, setPathname] = React.useState('/page'); const router = React.useMemo(() => { return { diff --git a/examples/core-tutorial/app/layout.tsx b/examples/core-tutorial/app/layout.tsx index b1849cd8ebc..ae88025aa2e 100644 --- a/examples/core-tutorial/app/layout.tsx +++ b/examples/core-tutorial/app/layout.tsx @@ -9,7 +9,7 @@ const NAVIGATION: Navigation = [ title: 'Main items', }, { - segment: '/page', + segment: 'page', title: 'Page', icon: , }, diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.test.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.test.tsx index c6a4818dc7c..2cd92ff6f56 100644 --- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.test.tsx +++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.test.tsx @@ -158,13 +158,13 @@ describe('DashboardLayout', () => { const NAVIGATION: Navigation = [ { title: 'Item 1', - segment: '/item1', + segment: 'item1', icon: , action:
Action 1
, }, { title: 'Item', - segment: '/item 2', + segment: 'item2', icon: , action:
Action 2
, }, diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx index 61d1d032ead..5af3eecf7d9 100644 --- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx +++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx @@ -229,7 +229,7 @@ function DashboardSidebarSubNavigation({ ); } - const navigationItemFullPath = `${basePath}/${navigationItem.segment ?? ''}`; + const navigationItemFullPath = `${basePath}${basePath && !navigationItem.segment ? '' : '/'}${navigationItem.segment ?? ''}`; const navigationItemId = `${depth}-${navigationItemIndex}`; diff --git a/packages/toolpad-core/src/nextjs/AppProvider.test.tsx b/packages/toolpad-core/src/nextjs/AppProvider.test.tsx index bf271cbeceb..321038792b2 100644 --- a/packages/toolpad-core/src/nextjs/AppProvider.test.tsx +++ b/packages/toolpad-core/src/nextjs/AppProvider.test.tsx @@ -29,7 +29,7 @@ interface RouterTestProps { } function RouterTest({ children }: RouterTestProps) { - const [pathname, setPathname] = React.useState('page'); + const [pathname, setPathname] = React.useState('/page'); const router = React.useMemo(() => { return { diff --git a/playground/nextjs-pages/src/pages/_app.tsx b/playground/nextjs-pages/src/pages/_app.tsx index 4ddb2213303..854810bfda6 100644 --- a/playground/nextjs-pages/src/pages/_app.tsx +++ b/playground/nextjs-pages/src/pages/_app.tsx @@ -23,12 +23,11 @@ const NAVIGATION: Navigation = [ title: 'Main items', }, { - segment: '/', title: 'Dashboard', icon: , }, { - segment: '/orders', + segment: 'orders', title: 'Orders', icon: , }, From 8a9e976dbffdf57cd2f7a4f0f2a75e0eca19779a Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Tue, 30 Jul 2024 22:46:44 +0100 Subject: [PATCH 2/4] Adjustments --- .../core/components/dashboard-layout/dashboard-layout.md | 4 ++-- packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md b/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md index b0195c0f540..097f03b3fef 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md +++ b/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md @@ -49,7 +49,7 @@ Navigation links can be placed in the sidebar as items with the format: Navigation headings can be placed in the sidebar as items with the format: ```tsx -{ kind: 'header', title: 'Epic Fantasy' } +{ kind: 'header', title: 'Animals' } ``` {{"demo": "DashboardLayoutNavigationHeadings.js", "height": 400, "iframe": true}} @@ -71,7 +71,7 @@ Dividers can can be placed between items in the sidebar as items with the format Nested navigation structures can be placed in the sidebar as items with the format: ```tsx -{ title: 'Fantasy', icon: , children: [ ... ] } +{ title: 'Movies', icon: , children: [ ... ] } ``` {{"demo": "DashboardLayoutNavigationNested.js", "height": 400, "iframe": true}} diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx index 5af3eecf7d9..e7feddf5a99 100644 --- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx +++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx @@ -169,7 +169,7 @@ function DashboardSidebarSubNavigation({ if (!isPageItem(nestedNavigationItem)) { return false; } - const navigationItemFullPath = `${basePath}/${nestedNavigationItem.segment ?? ''}`; + const navigationItemFullPath = `${basePath}${basePath && !navigationItem.segment ? '' : '/'}${navigationItem.segment ?? ''}`; return navigationItemFullPath === pathname; }), From 7f0956221a3a7556232bf3b81a4b4a806955b7b0 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Wed, 31 Jul 2024 19:52:15 +0100 Subject: [PATCH 3/4] Fix initially expanded navigation items --- .../src/DashboardLayout/DashboardLayout.tsx | 16 ++-------- .../toolpad-core/src/shared/navigation.tsx | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx index e7feddf5a99..194b8431468 100644 --- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx +++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx @@ -36,7 +36,7 @@ import { } from '../shared/context'; import type { Navigation, NavigationPageItem } from '../AppProvider'; import { ToolpadLogo } from './ToolpadLogo'; -import { getItemTitle, isPageItem } from '../shared/navigation'; +import { getItemTitle, hasSelectedNavigationChildren } from '../shared/navigation'; import { useApplicationTitle } from '../shared/branding'; const DRAWER_WIDTH = 320; // px @@ -161,18 +161,8 @@ function DashboardSidebarSubNavigation({ navigationItem, originalIndex: navigationItemIndex, })) - .filter( - ({ navigationItem }) => - isPageItem(navigationItem) && - navigationItem.children && - navigationItem.children.some((nestedNavigationItem) => { - if (!isPageItem(nestedNavigationItem)) { - return false; - } - const navigationItemFullPath = `${basePath}${basePath && !navigationItem.segment ? '' : '/'}${navigationItem.segment ?? ''}`; - - return navigationItemFullPath === pathname; - }), + .filter(({ navigationItem }) => + hasSelectedNavigationChildren(navigationItem, basePath, pathname), ) .map(({ originalIndex }) => `${depth}-${originalIndex}`), [basePath, depth, pathname, subNavigation], diff --git a/packages/toolpad-core/src/shared/navigation.tsx b/packages/toolpad-core/src/shared/navigation.tsx index 6345c9b6994..5ba20be5df0 100644 --- a/packages/toolpad-core/src/shared/navigation.tsx +++ b/packages/toolpad-core/src/shared/navigation.tsx @@ -8,3 +8,33 @@ export const isPageItem = (item: NavigationItem): item is NavigationPageItem => export const getItemTitle = (item: NavigationPageItem | NavigationSubheaderItem) => { return isPageItem(item) ? item.title ?? item.segment : item.title; }; + +export function hasSelectedNavigationChildren( + navigationItem: NavigationItem, + basePath: string, + pathname: string, +): boolean { + if (isPageItem(navigationItem) && navigationItem.children) { + const navigationItemFullPath = `${basePath}${basePath && !navigationItem.segment ? '' : '/'}${navigationItem.segment ?? ''}`; + + return navigationItem.children.some((nestedNavigationItem) => { + if (!isPageItem(nestedNavigationItem)) { + return false; + } + + if (nestedNavigationItem.children) { + return hasSelectedNavigationChildren( + nestedNavigationItem, + navigationItemFullPath, + pathname, + ); + } + + const nestedNavigationItemFullPath = `${navigationItemFullPath}${navigationItemFullPath && !nestedNavigationItem.segment ? '' : '/'}${nestedNavigationItem.segment ?? ''}`; + + return nestedNavigationItemFullPath === pathname; + }); + } + + return false; +} From 268f3d203729b3c7c56b3a283bda67d804599a28 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 1 Aug 2024 22:37:26 +0100 Subject: [PATCH 4/4] Switch things a bit in one demo --- .../DashboardLayoutNavigationActions.js | 30 +++++++++---------- .../DashboardLayoutNavigationActions.tsx | 30 +++++++++---------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.js index 5e3aad87442..5d0899abd4b 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.js +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.js @@ -15,21 +15,6 @@ import CallReceivedIcon from '@mui/icons-material/CallReceived'; import { AppProvider } from '@toolpad/core/AppProvider'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; -const CALLS_NAVIGATION = [ - { - segment: '/made', - title: 'Made', - icon: , - action: , - }, - { - segment: '/received', - title: 'Received', - icon: , - action: , - }, -]; - const demoTheme = extendTheme({ breakpoints: { values: { @@ -62,6 +47,21 @@ DemoPageContent.propTypes = { pathname: PropTypes.string.isRequired, }; +const CALLS_NAVIGATION = [ + { + segment: '/made', + title: 'Made', + icon: , + action: , + }, + { + segment: '/received', + title: 'Received', + icon: , + action: , + }, +]; + function DashboardLayoutNavigationActions(props) { const { window } = props; diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx index 5be59d990a1..dbbda585475 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx +++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutNavigationActions.tsx @@ -15,21 +15,6 @@ import { AppProvider, Router } from '@toolpad/core/AppProvider'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import type { Navigation } from '@toolpad/core'; -const CALLS_NAVIGATION: Navigation = [ - { - segment: '/made', - title: 'Made', - icon: , - action: , - }, - { - segment: '/received', - title: 'Received', - icon: , - action: , - }, -]; - const demoTheme = extendTheme({ breakpoints: { values: { @@ -58,6 +43,21 @@ function DemoPageContent({ pathname }: { pathname: string }) { ); } +const CALLS_NAVIGATION: Navigation = [ + { + segment: '/made', + title: 'Made', + icon: , + action: , + }, + { + segment: '/received', + title: 'Received', + icon: , + action: , + }, +]; + interface DemoProps { /** * Injected by the documentation to work in an iframe.