Skip to content

Commit b3168de

Browse files
Nakshatra SharmaNakshatra Sharma
authored andcommitted
feat: persist sidebar state in local storage
1 parent 974ad0e commit b3168de

3 files changed

Lines changed: 84 additions & 6 deletions

File tree

cypress/components/DropdownMenu.cy.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,67 @@ describe('DropdownMenu Component', () => {
9898
cy.get('button').click();
9999
cy.get('[data-testid="test-content"]').should('be.visible');
100100
});
101+
102+
it('persists state to localStorage when id is provided', () => {
103+
const testId = 'test-dropdown-id';
104+
105+
// Clear storage before test
106+
window.localStorage.clear();
107+
108+
// Spy on localStorage
109+
cy.spy(window.localStorage, 'setItem').as('setItem');
110+
cy.spy(window.localStorage, 'getItem').as('getItem');
111+
112+
// 1. Mount and open
113+
cy.mount(
114+
<DropdownMenu
115+
label='Persist Test'
116+
icon={mockIcon}
117+
id={testId}
118+
testMode={true}
119+
>
120+
{mockChildren}
121+
</DropdownMenu>,
122+
);
123+
124+
// Initially closed
125+
cy.get('[data-testid="test-content"]').should('not.exist');
126+
127+
// Open it
128+
cy.get('button').click();
129+
cy.get('[data-testid="test-content"]').should('be.visible');
130+
131+
// Verify setItem was called
132+
cy.get('@setItem').should(
133+
'have.been.calledWith',
134+
`sidebar_open_${testId}`,
135+
'true',
136+
);
137+
138+
// 2. Remount (simulate page reload)
139+
cy.mount(
140+
<DropdownMenu
141+
label='Persist Test'
142+
icon={mockIcon}
143+
id={testId}
144+
testMode={true}
145+
>
146+
{mockChildren}
147+
</DropdownMenu>,
148+
);
149+
150+
// Verify getItem was called
151+
cy.get('@getItem').should('have.been.calledWith', `sidebar_open_${testId}`);
152+
153+
// Should be open immediately because of localStorage
154+
cy.get('[data-testid="test-content"]').should('be.visible');
155+
156+
// 3. Close it
157+
cy.get('button').click();
158+
cy.get('@setItem').should(
159+
'have.been.calledWith',
160+
`sidebar_open_${testId}`,
161+
'false',
162+
);
163+
});
101164
});

pages/tools/components/Sidebar.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ export default function Sidebar({
129129
label={label}
130130
icon={<IconComponent />}
131131
count={checkedValues.length}
132+
id={accessorKey}
132133
>
133134
{filterCriteria[accessorKey as FilterCriteriaFields]
134135
?.map(String)

pages/tools/components/ui/DropdownMenu.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/* eslint-disable linebreak-style */
22
/* eslint-disable react-hooks/rules-of-hooks */
33
/* eslint-disable linebreak-style */
4-
import { useRouter } from 'next/router';
54
import React, {
65
type ReactElement,
76
type ReactNode,
87
useEffect,
98
useState,
9+
useRef,
1010
} from 'react';
1111
import {
1212
Collapsible,
@@ -20,21 +20,35 @@ interface DropdownMenuProps {
2020
icon: ReactElement;
2121
count?: number;
2222
testMode?: boolean;
23+
id?: string;
2324
}
2425

2526
export default function DropdownMenu({
2627
children,
2728
label,
2829
icon,
2930
count = 0,
31+
id,
3032
}: DropdownMenuProps) {
3133
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
32-
const router = useRouter();
33-
34+
const isFirstRun = useRef(true);
3435
useEffect(() => {
35-
setIsDropdownOpen(false);
36-
}, [router]);
37-
36+
if (id) {
37+
const storedState = localStorage.getItem(`sidebar_open_${id}`);
38+
if (storedState) {
39+
setIsDropdownOpen(storedState === 'true');
40+
}
41+
}
42+
}, [id]);
43+
useEffect(() => {
44+
if (id) {
45+
if (isFirstRun.current) {
46+
isFirstRun.current = false;
47+
return;
48+
}
49+
localStorage.setItem(`sidebar_open_${id}`, String(isDropdownOpen));
50+
}
51+
}, [id, isDropdownOpen]);
3852
return (
3953
<div className='my-2 bg-slate-200 dark:bg-slate-900 p-2 rounded cursor-pointer transition-all duration-200 group'>
4054
<Collapsible open={isDropdownOpen} onOpenChange={setIsDropdownOpen}>

0 commit comments

Comments
 (0)