Skip to content

Commit 8ee2b2b

Browse files
committed
Track collapsible state in sessionStorage
1 parent 6b777f4 commit 8ee2b2b

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

code/core/src/components/components/Collapsible/Collapsible.tsx

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,20 @@ export const Collapsible = Object.assign(
3434
summary,
3535
collapsed,
3636
disabled,
37+
initialCollapsed,
38+
storageKey,
3739
state: providedState,
3840
...props
3941
}: {
4042
children: ReactNode | ((state: ReturnType<typeof useCollapsible>) => ReactNode);
4143
summary?: ReactNode | ((state: ReturnType<typeof useCollapsible>) => ReactNode);
4244
collapsed?: boolean;
4345
disabled?: boolean;
46+
initialCollapsed?: boolean;
47+
storageKey?: string;
4448
state?: ReturnType<typeof useCollapsible>;
4549
} & ComponentProps<typeof CollapsibleContent>) {
46-
const internalState = useCollapsible(collapsed, disabled);
50+
const internalState = useCollapsible({ collapsed, disabled, initialCollapsed, storageKey });
4751
const state = providedState || internalState;
4852
return (
4953
<>
@@ -64,14 +68,47 @@ export const Collapsible = Object.assign(
6468
}
6569
);
6670

67-
export const useCollapsible = (collapsed?: boolean, disabled?: boolean) => {
68-
const [isCollapsed, setCollapsed] = useState(!!collapsed);
71+
const useSessionState = <T,>(key: string | undefined, initialValue: T) => {
72+
const [value, setValue] = useState<T>(() => {
73+
try {
74+
return (JSON.parse(sessionStorage.getItem(key!)!) as T) ?? initialValue;
75+
} catch {
76+
return initialValue;
77+
}
78+
});
79+
80+
useEffect(() => {
81+
try {
82+
if (key) {
83+
sessionStorage.setItem(key, JSON.stringify(value));
84+
}
85+
} catch {}
86+
}, [key, value]);
87+
88+
return [value, setValue] as const;
89+
};
90+
91+
export const useCollapsible = ({
92+
collapsed,
93+
disabled,
94+
initialCollapsed = collapsed,
95+
storageKey,
96+
}: {
97+
collapsed?: boolean;
98+
disabled?: boolean;
99+
initialCollapsed?: boolean;
100+
storageKey?: string;
101+
}) => {
102+
const [isCollapsed, setCollapsed] = useSessionState(
103+
storageKey && `useCollapsible:${storageKey}`,
104+
!!initialCollapsed
105+
);
69106

70107
useEffect(() => {
71108
if (collapsed !== undefined) {
72109
setCollapsed(collapsed);
73110
}
74-
}, [collapsed]);
111+
}, [collapsed, setCollapsed]);
75112

76113
const toggleCollapsed = useCallback(
77114
(event?: SyntheticEvent<Element, Event>) => {
@@ -80,7 +117,7 @@ export const useCollapsible = (collapsed?: boolean, disabled?: boolean) => {
80117
setCollapsed((value) => !value);
81118
}
82119
},
83-
[disabled]
120+
[disabled, setCollapsed]
84121
);
85122

86123
const contentId = useId();

code/core/src/manager/components/sidebar/ChecklistWidget.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ export const ChecklistWidget = () => {
220220
<CollapsibleWithMargin collapsed={!hasItems || !loaded}>
221221
<HoverCard id="storybook-checklist-widget" outlineAnimation="rainbow">
222222
<Collapsible
223-
collapsed={!hasItems}
223+
storageKey="checklist-widget"
224+
initialCollapsed={!hasItems}
224225
disabled={!hasItems}
225226
summary={({ isCollapsed, toggleCollapsed, toggleProps }) => (
226227
<ActionList as="div" onClick={toggleCollapsed}>

0 commit comments

Comments
 (0)