Skip to content

Commit df15c46

Browse files
committed
finish the open context
1 parent 4a20b0e commit df15c46

File tree

2 files changed

+95
-19
lines changed

2 files changed

+95
-19
lines changed

packages/compass-components/src/components/drawer-portal.spec.tsx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
DrawerContentProvider,
1010
DrawerSection,
1111
DrawerAnchor,
12+
useDrawerState,
13+
useDrawerActions,
1214
} from './drawer-portal';
1315
import { expect } from 'chai';
1416

@@ -162,4 +164,68 @@ describe('DrawerSection', function () {
162164
screen.getByTestId('lg-drawer')
163165
).to.have.attribute('aria-hidden', 'true');
164166
});
167+
168+
it('can control drawer state via the hooks', async function () {
169+
const ControlElement = () => {
170+
const { isDrawerOpen } = useDrawerState();
171+
const { openDrawer, closeDrawer } = useDrawerActions();
172+
return (
173+
<div>
174+
<span data-testid="drawer-state">
175+
{isDrawerOpen ? 'open' : 'closed'}
176+
</span>
177+
<button
178+
data-testid="toggle-drawer"
179+
onClick={
180+
isDrawerOpen
181+
? () => closeDrawer()
182+
: () => openDrawer('controlled-section')
183+
}
184+
>
185+
{isDrawerOpen ? 'Close drawer' : 'Open drawer'}
186+
</button>
187+
</div>
188+
);
189+
};
190+
render(
191+
<DrawerContentProvider>
192+
<ControlElement />
193+
<DrawerAnchor>
194+
<DrawerSection
195+
id="unrelated-section"
196+
label="Test section 1"
197+
title="Test section 1"
198+
glyph="Trash"
199+
>
200+
This is an unrelated section
201+
</DrawerSection>
202+
<DrawerSection
203+
id="controlled-section"
204+
label="Test section 2"
205+
title="Test section 2"
206+
glyph="Bell"
207+
>
208+
This is the controlled section
209+
</DrawerSection>
210+
</DrawerAnchor>
211+
</DrawerContentProvider>
212+
);
213+
214+
// Drawer is closed by default
215+
expect(screen.getByTestId('drawer-state')).to.have.text('closed');
216+
217+
// Open the drawer
218+
userEvent.click(screen.getByTestId('toggle-drawer'));
219+
await waitFor(() => {
220+
expect(screen.getByTestId('drawer-state')).to.have.text('open');
221+
expect(screen.getByText('This is the controlled section')).to.be.visible;
222+
});
223+
224+
// Close the drawer
225+
userEvent.click(screen.getByTestId('toggle-drawer'));
226+
await waitFor(() => {
227+
expect(screen.getByTestId('drawer-state')).to.have.text('closed');
228+
expect(screen.queryByText('This is the controlled section')).not.to.exist;
229+
});
230+
});
165231
});

packages/compass-components/src/components/drawer-portal.tsx

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ type DrawerSectionProps = Omit<SectionData, 'content' | 'onClick'> & {
3232
order?: number;
3333
};
3434

35-
type DrawerOpenStateContextValue = {
36-
current: {
37-
isDrawerOpen: boolean;
38-
};
35+
type DrawerOpenStateContextValue = boolean;
36+
37+
type DrawerSetOpenStateContextValue = {
38+
setIsDrawerOpen: (isOpen: boolean) => void;
3939
};
4040

4141
type DrawerActionsContextValue = {
@@ -49,13 +49,13 @@ type DrawerActionsContextValue = {
4949

5050
const DrawerStateContext = React.createContext<DrawerSectionProps[]>([]);
5151

52-
const DrawerOpenStateContext = React.createContext<DrawerOpenStateContextValue>(
53-
{
54-
current: {
55-
isDrawerOpen: false,
56-
},
57-
}
58-
);
52+
const DrawerOpenStateContext =
53+
React.createContext<DrawerOpenStateContextValue>(false);
54+
55+
const DrawerSetOpenStateContext =
56+
React.createContext<DrawerSetOpenStateContextValue>({
57+
setIsDrawerOpen: () => {},
58+
});
5959

6060
const DrawerActionsContext = React.createContext<DrawerActionsContextValue>({
6161
current: {
@@ -103,6 +103,8 @@ export const DrawerContentProvider: React.FunctionComponent = ({
103103
children,
104104
}) => {
105105
const [drawerState, setDrawerState] = useState<DrawerSectionProps[]>([]);
106+
const [drawerOpenState, setDrawerOpenState] =
107+
useState<DrawerOpenStateContextValue>(false);
106108
const drawerActions = useRef({
107109
openDrawer: () => undefined,
108110
closeDrawer: () => undefined,
@@ -130,20 +132,28 @@ export const DrawerContentProvider: React.FunctionComponent = ({
130132

131133
return (
132134
<DrawerStateContext.Provider value={drawerState}>
133-
<DrawerActionsContext.Provider value={drawerActions}>
134-
{children}
135-
</DrawerActionsContext.Provider>
135+
<DrawerOpenStateContext.Provider value={drawerOpenState}>
136+
<DrawerSetOpenStateContext.Provider
137+
value={{ setIsDrawerOpen: setDrawerOpenState }}
138+
>
139+
<DrawerActionsContext.Provider value={drawerActions}>
140+
{children}
141+
</DrawerActionsContext.Provider>
142+
</DrawerSetOpenStateContext.Provider>
143+
</DrawerOpenStateContext.Provider>
136144
</DrawerStateContext.Provider>
137145
);
138146
};
139147

140148
const DrawerContextGrabber: React.FunctionComponent = ({ children }) => {
141149
const drawerToolbarContext = useDrawerToolbarContext();
142150
const actions = useContext(DrawerActionsContext);
143-
const state = useContext(DrawerOpenStateContext);
151+
const openStateSetter = useContext(DrawerSetOpenStateContext);
144152
actions.current.openDrawer = drawerToolbarContext.openDrawer;
145153
actions.current.closeDrawer = drawerToolbarContext.closeDrawer;
146-
state.current.isDrawerOpen = drawerToolbarContext.isDrawerOpen;
154+
useEffect(() => {
155+
openStateSetter.setIsDrawerOpen(drawerToolbarContext.isDrawerOpen);
156+
}, [drawerToolbarContext.isDrawerOpen, openStateSetter]);
147157
return <>{children}</>;
148158
};
149159

@@ -339,11 +349,11 @@ export function useDrawerActions() {
339349
}
340350

341351
export const useDrawerState = () => {
342-
const drawerToolbarContext = useContext(DrawerOpenStateContext);
352+
const drawerOpenStateContext = useContext(DrawerOpenStateContext);
343353
const drawerState = useContext(DrawerStateContext);
344354
return {
345-
isOpen:
346-
drawerToolbarContext.current.isDrawerOpen &&
355+
isDrawerOpen:
356+
drawerOpenStateContext &&
347357
// the second check is a workaround, because LG doesn't set isDrawerOpen to false when it's empty
348358
drawerState.length > 0,
349359
};

0 commit comments

Comments
 (0)