+ ,
+ );
+
+ // Assert the callback was called with the new state
+ expect(mockToggleSidebar).toHaveBeenCalledWith(true);
+
+ // Trigger expand action
+ rerender(
+
+
Test Content
+ ,
+ );
+
+ // Assert the callback was called again with the updated state
+ expect(mockToggleSidebar).toHaveBeenCalledWith(false);
+ });
});
diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx
index da545108989..ae9b7c31388 100644
--- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx
+++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx
@@ -89,6 +89,14 @@ export interface DashboardLayoutProps {
* @default false
*/
hideNavigation?: boolean;
+ /** A prop that controls the collapsed state of the sidebar.
+ * @default false
+ */
+ sidebarCollapsed?: boolean;
+ /**
+ * Callback function to be executed on sidebarCollased state change
+ */
+ onToggleSidebar?: (sidebarCollapsed: boolean) => void;
/**
* Width of the sidebar when expanded.
* @default 320
@@ -131,6 +139,8 @@ function DashboardLayout(props: DashboardLayoutProps) {
slots,
slotProps,
sx,
+ sidebarCollapsed,
+ onToggleSidebar,
} = props;
const theme = useTheme();
@@ -174,6 +184,15 @@ function DashboardLayout(props: DashboardLayoutProps) {
const [isNavigationFullyExpanded, setIsNavigationFullyExpanded] =
React.useState(isNavigationExpanded);
+ React.useEffect(() => {
+ if (typeof sidebarCollapsed === 'boolean') {
+ setIsNavigationExpanded(!sidebarCollapsed);
+ if (onToggleSidebar) {
+ onToggleSidebar(sidebarCollapsed);
+ }
+ }
+ }, [sidebarCollapsed, setIsNavigationExpanded, onToggleSidebar]);
+
React.useEffect(() => {
if (isNavigationExpanded) {
const drawerWidthTransitionTimeout = setTimeout(() => {
@@ -483,6 +502,15 @@ DashboardLayout.propTypes /* remove-proptypes */ = {
* @default false
*/
hideNavigation: PropTypes.bool,
+ /**
+ * Callback function to be executed on sidebarCollased state change
+ */
+ onToggleSidebar: PropTypes.func,
+ /**
+ * A prop that controls the collapsed state of the sidebar.
+ * @default false
+ */
+ sidebarCollapsed: PropTypes.bool,
/**
* Width of the sidebar when expanded.
* @default 320
From 374dfbf9e4ec210d04fc1f89dca1c31f6ba56fc7 Mon Sep 17 00:00:00 2001
From: Vikas Gurjar <13435960+vikasgurjar@users.noreply.github.com>
Date: Fri, 6 Dec 2024 14:16:10 +0530
Subject: [PATCH 2/4] run pnpm docs:typescript:formatted
---
.../DashboardLayoutSidebarCollapsedProp.js | 14 +-------------
1 file changed, 1 insertion(+), 13 deletions(-)
diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.js
index 07f006e592f..cbd2357620d 100644
--- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.js
+++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.js
@@ -63,19 +63,7 @@ function DemoPageContent({ pathname, toggleSidebar }) {
DemoPageContent.propTypes = {
pathname: PropTypes.string.isRequired,
- toggleSidebar: PropTypes.shape({
- '__@hasInstance@2095': PropTypes.func.isRequired,
- '__@metadata@2097': PropTypes.any,
- apply: PropTypes.func.isRequired,
- arguments: PropTypes.any.isRequired,
- bind: PropTypes.func.isRequired,
- call: PropTypes.func.isRequired,
- caller: PropTypes.object.isRequired,
- length: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- prototype: PropTypes.any.isRequired,
- toString: PropTypes.func.isRequired,
- }).isRequired,
+ toggleSidebar: PropTypes.func.isRequired,
};
function DashboardLayoutSidebarCollapsedProp(props) {
From 9aaee1f6eb4a6d2d223d2edea26a83cb6a31a4c7 Mon Sep 17 00:00:00 2001
From: Vikas Gurjar <13435960+vikasgurjar@users.noreply.github.com>
Date: Fri, 6 Dec 2024 14:28:56 +0530
Subject: [PATCH 3/4] add demo for sidebarCollapsed
---
.../core/components/dashboard-layout/dashboard-layout.md | 6 ++++++
1 file changed, 6 insertions(+)
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 dc46918b677..11fba8c0bec 100644
--- a/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md
+++ b/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md
@@ -126,6 +126,12 @@ The layout sidebar can be hidden if needed with the `hideNavigation` prop.
{{"demo": "DashboardLayoutSidebarHidden.js", "height": 400, "iframe": true}}
+### Toggle sidebar
+
+The sidebar can be toggled if needed with the `sidebarCollapsed` prop.
+
+{{"demo": "DashboardLayoutSidebarCollapsedProp.js", "height": 400, "iframe": true}}
+
## Full-size content
The layout content can take up the full available area with styles such as `flex: 1` or `height: 100%`.
From f7f3397921bdcf1a48c0b37dbbf27c090334836c Mon Sep 17 00:00:00 2001
From: Vikas Gurjar <13435960+vikasgurjar@users.noreply.github.com>
Date: Sat, 7 Dec 2024 15:54:31 +0530
Subject: [PATCH 4/4] use navigationMenuOpen instead of sidebarCollapsed
---
.../DashboardLayoutSidebarCollapsedProp.js | 6 +--
.../DashboardLayoutSidebarCollapsedProp.tsx | 6 +--
...oardLayoutSidebarCollapsedProp.tsx.preview | 4 +-
.../dashboard-layout/dashboard-layout.md | 2 +-
.../toolpad/core/api/dashboard-layout.json | 5 ++-
.../dashboard-layout/dashboard-layout.json | 11 +++--
.../DashboardLayout/DashboardLayout.test.tsx | 35 +++++++++-------
.../src/DashboardLayout/DashboardLayout.tsx | 41 ++++++++++++-------
8 files changed, 66 insertions(+), 44 deletions(-)
diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.js b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.js
index cbd2357620d..6ef9969bee5 100644
--- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.js
+++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.js
@@ -70,7 +70,7 @@ function DashboardLayoutSidebarCollapsedProp(props) {
const { window } = props;
const [pathname, setPathname] = React.useState('/dashboard');
- const [sidebarCollapsed, toggleSidebar] = React.useState(true);
+ const [navigationMenuOpen, toggleSidebar] = React.useState(true);
const router = React.useMemo(() => {
return {
pathname,
@@ -89,10 +89,10 @@ function DashboardLayoutSidebarCollapsedProp(props) {
theme={demoTheme}
window={demoWindow}
>
-
+ toggleSidebar(!sidebarCollapsed)}
+ toggleSidebar={() => toggleSidebar(!navigationMenuOpen)}
/>
diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.tsx b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.tsx
index a693e39ecd1..f00eadeb905 100644
--- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.tsx
+++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.tsx
@@ -82,7 +82,7 @@ export default function DashboardLayoutSidebarCollapsedProp(props: DemoProps) {
const { window } = props;
const [pathname, setPathname] = React.useState('/dashboard');
- const [sidebarCollapsed, toggleSidebar] = React.useState(true);
+ const [navigationMenuOpen, toggleSidebar] = React.useState(true);
const router = React.useMemo(() => {
return {
pathname,
@@ -101,10 +101,10 @@ export default function DashboardLayoutSidebarCollapsedProp(props: DemoProps) {
theme={demoTheme}
window={demoWindow}
>
-
+ toggleSidebar(!sidebarCollapsed)}
+ toggleSidebar={() => toggleSidebar(!navigationMenuOpen)}
/>
diff --git a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.tsx.preview b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.tsx.preview
index 36d7e84465e..3e5869c9ede 100644
--- a/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.tsx.preview
+++ b/docs/data/toolpad/core/components/dashboard-layout/DashboardLayoutSidebarCollapsedProp.tsx.preview
@@ -1,6 +1,6 @@
-
+ toggleSidebar(!sidebarCollapsed)}
+ toggleSidebar={() => toggleSidebar(!navigationMenuOpen)}
/>
\ 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 11fba8c0bec..b27e92c67dd 100644
--- a/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md
+++ b/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md
@@ -128,7 +128,7 @@ The layout sidebar can be hidden if needed with the `hideNavigation` prop.
### Toggle sidebar
-The sidebar can be toggled if needed with the `sidebarCollapsed` prop.
+The sidebar can be toggled if needed with the `navigationMenuOpen` prop.
{{"demo": "DashboardLayoutSidebarCollapsedProp.js", "height": 400, "iframe": true}}
diff --git a/docs/pages/toolpad/core/api/dashboard-layout.json b/docs/pages/toolpad/core/api/dashboard-layout.json
index bc2ba69513a..217260c8f13 100644
--- a/docs/pages/toolpad/core/api/dashboard-layout.json
+++ b/docs/pages/toolpad/core/api/dashboard-layout.json
@@ -11,8 +11,9 @@
"defaultSidebarCollapsed": { "type": { "name": "bool" }, "default": "false" },
"disableCollapsibleSidebar": { "type": { "name": "bool" }, "default": "false" },
"hideNavigation": { "type": { "name": "bool" }, "default": "false" },
- "onToggleSidebar": { "type": { "name": "func" } },
- "sidebarCollapsed": { "type": { "name": "bool" }, "default": "false" },
+ "navigationMenuOpen": { "type": { "name": "bool" }, "default": "false" },
+ "onNavigationMenuClose": { "type": { "name": "func" } },
+ "onNavigationMenuOpen": { "type": { "name": "func" } },
"sidebarExpandedWidth": {
"type": { "name": "union", "description": "number | string" },
"default": "320"
diff --git a/docs/translations/api-docs/dashboard-layout/dashboard-layout.json b/docs/translations/api-docs/dashboard-layout/dashboard-layout.json
index bee0ce4246b..c95c460fb05 100644
--- a/docs/translations/api-docs/dashboard-layout/dashboard-layout.json
+++ b/docs/translations/api-docs/dashboard-layout/dashboard-layout.json
@@ -12,12 +12,15 @@
"hideNavigation": {
"description": "Whether the navigation bar and menu icon should be hidden"
},
- "onToggleSidebar": {
- "description": "Callback function to be executed on sidebarCollased state change"
- },
- "sidebarCollapsed": {
+ "navigationMenuOpen": {
"description": "A prop that controls the collapsed state of the sidebar."
},
+ "onNavigationMenuClose": {
+ "description": "Callback function to be executed on navigation menu state changes to closed"
+ },
+ "onNavigationMenuOpen": {
+ "description": "Callback function to be executed on navigation menu state changes to open"
+ },
"sidebarExpandedWidth": { "description": "Width of the sidebar when expanded." },
"slotProps": { "description": "The props used for each slot inside." },
"slots": { "description": "The components used for each slot inside." },
diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.test.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.test.tsx
index c6af2d57ffa..2d7b6f4f411 100644
--- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.test.tsx
+++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.test.tsx
@@ -411,9 +411,9 @@ describe('DashboardLayout', () => {
expect(screen.getByText('Hello world')).toBeTruthy();
});
- test('renders the sidebar in collapsed state when sidebarCollapsed is true', () => {
+ test('renders the sidebar in collapsed state when navigationMenuOpen is false', () => {
render(
-
+
Test Content
,
);
@@ -423,9 +423,9 @@ describe('DashboardLayout', () => {
expect(screen.queryByLabelText('Collapse menu')).toBeNull();
});
- test('renders the sidebar in expanded state when sidebarCollapsed is false', () => {
+ test('renders the sidebar in expanded state when navigationMenuOpen is true', () => {
render(
-
+
Test Content
,
);
@@ -433,32 +433,39 @@ describe('DashboardLayout', () => {
expect(screen.getAllByLabelText('Collapse menu')).toBeTruthy();
});
- test('calls onToggleSidebar callback when sidebarCollapsed state changes', () => {
+ test('calls onNavigationMenuOpen callback when navigationMenuOpen state changes to open', () => {
const mockToggleSidebar = vi.fn();
const { rerender } = render(
-
+
Test Content
,
);
- // Trigger sidebar toggle (simulate a collapse action)
+ // Trigger sidebar open action
rerender(
-
+
Test Content
,
);
- // Assert the callback was called with the new state
- expect(mockToggleSidebar).toHaveBeenCalledWith(true);
+ expect(mockToggleSidebar).toHaveBeenCalledOnce();
+ });
+
+ test('calls onNavigationMenuClose callback when navigationMenuOpen state changes to close', () => {
+ const mockToggleSidebar = vi.fn();
+ const { rerender } = render(
+
+
,
);
- // Assert the callback was called again with the updated state
- expect(mockToggleSidebar).toHaveBeenCalledWith(false);
+ expect(mockToggleSidebar).toHaveBeenCalledOnce();
});
});
diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx
index ae9b7c31388..14ef364bd8d 100644
--- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx
+++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx
@@ -92,11 +92,15 @@ export interface DashboardLayoutProps {
/** A prop that controls the collapsed state of the sidebar.
* @default false
*/
- sidebarCollapsed?: boolean;
+ navigationMenuOpen?: boolean;
/**
- * Callback function to be executed on sidebarCollased state change
+ * Callback function to be executed on navigation menu state changes to open
*/
- onToggleSidebar?: (sidebarCollapsed: boolean) => void;
+ onNavigationMenuOpen?: () => void;
+ /**
+ * Callback function to be executed on navigation menu state changes to closed
+ */
+ onNavigationMenuClose?: () => void;
/**
* Width of the sidebar when expanded.
* @default 320
@@ -139,8 +143,9 @@ function DashboardLayout(props: DashboardLayoutProps) {
slots,
slotProps,
sx,
- sidebarCollapsed,
- onToggleSidebar,
+ navigationMenuOpen,
+ onNavigationMenuOpen,
+ onNavigationMenuClose,
} = props;
const theme = useTheme();
@@ -185,13 +190,15 @@ function DashboardLayout(props: DashboardLayoutProps) {
React.useState(isNavigationExpanded);
React.useEffect(() => {
- if (typeof sidebarCollapsed === 'boolean') {
- setIsNavigationExpanded(!sidebarCollapsed);
- if (onToggleSidebar) {
- onToggleSidebar(sidebarCollapsed);
+ if (typeof navigationMenuOpen === 'boolean') {
+ setIsNavigationExpanded(navigationMenuOpen);
+ if (navigationMenuOpen) {
+ onNavigationMenuOpen?.();
+ } else {
+ onNavigationMenuClose?.();
}
}
- }, [sidebarCollapsed, setIsNavigationExpanded, onToggleSidebar]);
+ }, [navigationMenuOpen, setIsNavigationExpanded, onNavigationMenuOpen, onNavigationMenuClose]);
React.useEffect(() => {
if (isNavigationExpanded) {
@@ -502,15 +509,19 @@ DashboardLayout.propTypes /* remove-proptypes */ = {
* @default false
*/
hideNavigation: PropTypes.bool,
- /**
- * Callback function to be executed on sidebarCollased state change
- */
- onToggleSidebar: PropTypes.func,
/**
* A prop that controls the collapsed state of the sidebar.
* @default false
*/
- sidebarCollapsed: PropTypes.bool,
+ navigationMenuOpen: PropTypes.bool,
+ /**
+ * Callback function to be executed on navigation menu state changes to closed
+ */
+ onNavigationMenuClose: PropTypes.func,
+ /**
+ * Callback function to be executed on navigation menu state changes to open
+ */
+ onNavigationMenuOpen: PropTypes.func,
/**
* Width of the sidebar when expanded.
* @default 320