Skip to content

Commit 15b4683

Browse files
authored
chore(components): replace vendored drawer with lg dependency (#7289)
* chore(components): replace vendored drawer with leafygreen dependency * chore(compass-components): fix hacky selector
1 parent 9d76772 commit 15b4683

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+585
-2153
lines changed

package-lock.json

Lines changed: 507 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/compass-components/.depcheckrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@ ignores: [
22
'@mongodb-js/prettier-config-compass',
33
'@mongodb-js/tsconfig-compass',
44
'@types/chai-dom',
5+
# making sure all of the leafygreen is using the same version of these core
6+
# dependencies
57
'@emotion/css',
8+
"@leafygreen-ui/lib",
69
]

packages/compass-components/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"@leafygreen-ui/combobox": "^11.0.2",
4747
"@leafygreen-ui/confirmation-modal": "^6.0.2",
4848
"@leafygreen-ui/copyable": "^10.0.14",
49-
"@leafygreen-ui/descendants": "^2.1.0",
49+
"@leafygreen-ui/drawer": "^5.0.3",
5050
"@leafygreen-ui/emotion": "^4.0.9",
5151
"@leafygreen-ui/guide-cue": "^7.0.2",
5252
"@leafygreen-ui/hooks": "^8.3.4",
@@ -55,7 +55,6 @@
5555
"@leafygreen-ui/info-sprinkle": "^4.0.2",
5656
"@leafygreen-ui/input-option": "^3.0.12",
5757
"@leafygreen-ui/leafygreen-provider": "^4.0.2",
58-
"@leafygreen-ui/lib": "^15.3.0",
5958
"@leafygreen-ui/logo": "^10.0.2",
6059
"@leafygreen-ui/marketing-modal": "^5.0.2",
6160
"@leafygreen-ui/menu": "^29.0.5",
@@ -119,6 +118,7 @@
119118
},
120119
"devDependencies": {
121120
"@emotion/css": "^11.11.2",
121+
"@leafygreen-ui/lib": "^15.3.0",
122122
"@mongodb-js/eslint-config-compass": "^1.4.10",
123123
"@mongodb-js/mocha-config-compass": "^1.7.1",
124124
"@mongodb-js/prettier-config-compass": "^1.2.8",

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

Lines changed: 73 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,27 @@ import React, {
77
useRef,
88
useState,
99
} from 'react';
10-
1110
import {
1211
DrawerLayout,
1312
DisplayMode as DrawerDisplayMode,
1413
useDrawerToolbarContext,
1514
type DrawerLayoutProps,
16-
} from './drawer';
15+
} from '@leafygreen-ui/drawer';
1716
import { css, cx } from '@leafygreen-ui/emotion';
1817
import { isEqual } from 'lodash';
1918
import { rafraf } from '../utils/rafraf';
19+
import { BaseFontSize, fontWeights } from '@leafygreen-ui/tokens';
20+
21+
type ToolbarData = Required<DrawerLayoutProps>['toolbarData'];
2022

21-
type SectionData = Required<DrawerLayoutProps>['toolbarData'][number];
23+
type SectionData = ToolbarData[number];
2224

2325
type DrawerSectionProps = Omit<SectionData, 'content' | 'onClick'> & {
26+
// Title exists in DrawerLayoutProps, but is optional, whereas for us it needs
27+
// to be required (also due to merging of types inside leafygreen, we can't
28+
// convince typescript that our toolbarData is compatible with lg toolbarData
29+
// if that is not explicit)
30+
title: React.ReactNode;
2431
/**
2532
* If `true` will automatically open the section when first mounted. Default: `false`
2633
*/
@@ -163,22 +170,19 @@ const drawerLayoutFixesStyles = css({
163170
},
164171

165172
// drawer section
166-
'& > div:nth-child(2)': {
167-
marginTop: -1, // hiding the top border as we already have one in the place where the Anchor is currently rendered
173+
'& > div:nth-child(2) > div': {
174+
// hiding the border border as we already have one in the place where the
175+
// Anchor is currently rendered
176+
borderTop: 'none',
177+
borderBottom: 'none',
168178
},
169179

170-
// We're stretching the title container to all available width so that we can
171-
// layout the controls there better. Doing our best to target the section
172-
// title here, leafygreen really doesn't give us anything else to try.
173-
//
174-
// TODO(ticket): This is obviously a horrible selector and we should make sure
175-
// that LG team provides a better one for us to achieve this behavior when
176-
// we're removing the vendored version of the drawer
177-
'& > div:nth-child(2) > div:nth-child(2) > div:first-child > div:first-child > div:first-child > div:first-child':
180+
// drawer content > title content
181+
'& > div:nth-child(2) > div:nth-child(2) > div:nth-child(2) > div:first-child > div:first-child > div:first-child':
178182
{
179-
flex: 'none',
180-
width: 'calc(100% - 28px)', // disallow going over the title size (100 - close button width)
181-
overflow: 'hidden',
183+
// fix for the flex parent not allowing flex children to collapse if they
184+
// are overflowing the container
185+
minWidth: 0,
182186
},
183187
});
184188

@@ -210,13 +214,21 @@ const drawerSectionPortalStyles = css({
210214
height: '100%',
211215
});
212216

217+
// Leafygreen dynamically changes styles of the title group based on whether or
218+
// not title is a `string` or a `ReactNode`, we want it to consistently have
219+
// bold title styles no matter what title you provided, so we wrap it in our own
220+
// container
221+
const drawerTitleGroupStyles = css({
222+
width: '100%',
223+
fontSize: BaseFontSize.Body2,
224+
fontWeight: fontWeights.bold,
225+
});
226+
213227
/**
214228
* DrawerAnchor component will render the drawer in any place it is rendered.
215229
* This component has to wrap any content that Drawer will be shown near
216230
*/
217-
export const DrawerAnchor: React.FunctionComponent<{
218-
displayMode?: DrawerDisplayMode;
219-
}> = ({ displayMode, children }) => {
231+
export const DrawerAnchor: React.FunctionComponent = ({ children }) => {
220232
const actions = useContext(DrawerActionsContext);
221233
const drawerSectionItems = useContext(DrawerStateContext);
222234
const prevDrawerSectionItems = useRef<DrawerSectionProps[]>([]);
@@ -239,7 +251,13 @@ export const DrawerAnchor: React.FunctionComponent<{
239251
return drawerSectionItems
240252
.map((data) => {
241253
return {
254+
hasPadding: false,
242255
...data,
256+
title: (
257+
<div key={data.id} className={drawerTitleGroupStyles}>
258+
{data.title}
259+
</div>
260+
),
243261
content: (
244262
<div
245263
key={data.id}
@@ -255,7 +273,8 @@ export const DrawerAnchor: React.FunctionComponent<{
255273
}, [drawerSectionItems]);
256274
return (
257275
<DrawerLayout
258-
displayMode={displayMode ?? DrawerDisplayMode.Embedded}
276+
displayMode={DrawerDisplayMode.Embedded}
277+
resizable
259278
toolbarData={toolbarData}
260279
className={cx(
261280
drawerLayoutFixesStyles,
@@ -270,6 +289,15 @@ export const DrawerAnchor: React.FunctionComponent<{
270289
);
271290
};
272291

292+
function querySectionPortal(
293+
parent: Document | Element | null,
294+
id?: string
295+
): HTMLElement | null {
296+
return (
297+
parent?.querySelector(`[data-drawer-section${id ? `=${id}` : ''}]`) ?? null
298+
);
299+
}
300+
273301
/**
274302
* DrawerSection allows to declaratively render sections inside the drawer
275303
* independantly from the Drawer itself
@@ -278,7 +306,9 @@ export const DrawerSection: React.FunctionComponent<DrawerSectionProps> = ({
278306
children,
279307
...props
280308
}) => {
281-
const [portalNode, setPortalNode] = useState<Element | null>(null);
309+
const [portalNode, setPortalNode] = useState<Element | null>(() => {
310+
return querySectionPortal(document, props.id);
311+
});
282312
const actions = useContext(DrawerActionsContext);
283313
const prevProps = useRef<DrawerSectionProps>();
284314
useEffect(() => {
@@ -296,14 +326,24 @@ export const DrawerSection: React.FunctionComponent<DrawerSectionProps> = ({
296326
'Can not use DrawerSection without DrawerAnchor being mounted on the page'
297327
);
298328
}
299-
setPortalNode(
300-
document.querySelector(`[data-drawer-section="${props.id}"]`)
301-
);
329+
setPortalNode(querySectionPortal(drawerEl, props.id));
302330
const mutationObserver = new MutationObserver((mutations) => {
303331
for (const mutation of mutations) {
304-
for (const node of Array.from(mutation.addedNodes) as HTMLElement[]) {
305-
if (node.dataset && node.dataset.drawerSection === props.id) {
306-
setPortalNode(node);
332+
if (mutation.type === 'childList') {
333+
for (const node of Array.from(mutation.addedNodes)) {
334+
// Added node can be either the drawer section portal itself, a
335+
// parent node containing the section (in that case we won't get an
336+
// explicit mutation for the section itself), or something
337+
// completely unrelated, like a text node insert. By searching for
338+
// the section portal from added node parent element we cover all
339+
// these cases in one go
340+
const drawerSectionNode = querySectionPortal(
341+
node.parentElement,
342+
props.id
343+
);
344+
if (drawerSectionNode) {
345+
setPortalNode(drawerSectionNode);
346+
}
307347
}
308348
}
309349
}
@@ -315,7 +355,7 @@ export const DrawerSection: React.FunctionComponent<DrawerSectionProps> = ({
315355
return () => {
316356
mutationObserver.disconnect();
317357
};
318-
}, [actions, props.id]);
358+
}, [props.id]);
319359
useEffect(() => {
320360
return () => {
321361
actions.current.removeToolbarData(props.id);
@@ -333,7 +373,9 @@ export function useDrawerActions() {
333373
const actions = useContext(DrawerActionsContext);
334374
const stableActions = useRef({
335375
openDrawer: (id: string) => {
336-
actions.current.openDrawer(id);
376+
rafraf(() => {
377+
actions.current.openDrawer(id);
378+
});
337379
},
338380
closeDrawer: () => {
339381
actions.current.closeDrawer();
@@ -352,3 +394,5 @@ export const useDrawerState = () => {
352394
drawerState.length > 0,
353395
};
354396
};
397+
398+
export { getLgIds as getDrawerIds } from '@leafygreen-ui/drawer';

packages/compass-components/src/components/drawer/constants.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

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

Lines changed: 0 additions & 59 deletions
This file was deleted.

packages/compass-components/src/components/drawer/drawer-layout/drawer-layout.types.ts

Lines changed: 0 additions & 50 deletions
This file was deleted.

packages/compass-components/src/components/drawer/drawer-layout/index.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)