Skip to content

Commit 3908541

Browse files
authored
chore(combobox): remove combobox clone COMPASS-6465 (#6562)
* remove combobox clone * fix positioning * fix selector * clean up css * fix types * drive-by
1 parent 58e9f51 commit 3908541

File tree

28 files changed

+341
-3633
lines changed

28 files changed

+341
-3633
lines changed

package-lock.json

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

packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-builder-ui-workspace/sortable-list.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const SortableItem = ({ id, index, type }: SortableItemProps) => {
5858
const style = {
5959
transform: cssDndKit.Transform.toString(transform),
6060
transition,
61-
zIndex: isDragging ? 1 : 0,
61+
...(isDragging ? { zIndex: 1 } : {}),
6262
};
6363

6464
const sortableProps: SortableProps = {

packages/compass-aggregations/src/components/stage-toolbar/stage-operator-select.tsx

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,34 @@ import { filterStageOperators } from '../../utils/stage';
1717
import { isAtlasOnly } from '../../utils/stage';
1818
import type { ServerEnvironment } from '../../modules/env';
1919

20-
const inputWidth = spacing[7] * 2;
20+
const inputWidth = spacing[1400] * 3;
21+
const inputHeight = spacing[600] - 2; // match other xs controls
22+
// width of options popover
23+
const comboxboxOptionsWidth = spacing[1200] * 10;
24+
// left position of options popover wrt input. this aligns it with the start of input
25+
const comboboxOptionsLeft = (comboxboxOptionsWidth - inputWidth) / 2;
2126

22-
const inputHeight = spacing[4] - 2; // match other xs controls
2327
const comboboxStyles = css({
2428
width: inputWidth,
2529
'& [role="combobox"]': {
2630
padding: 0,
27-
paddingLeft: spacing[1],
31+
paddingLeft: spacing[100],
2832
height: inputHeight,
2933
'& > div': {
3034
minHeight: inputHeight,
3135
},
32-
'& input': {
33-
height: inputHeight - 2,
34-
},
36+
},
37+
});
38+
39+
const comboboxPortalStyles = css({
40+
position: 'fixed',
41+
top: 0,
42+
// -4px to count for the input focus outline.
43+
left: `${comboboxOptionsLeft - 4}px`,
44+
zIndex: 1,
45+
'> div': {
46+
width: comboxboxOptionsWidth,
47+
whiteSpace: 'normal',
3548
},
3649
});
3750

@@ -61,32 +74,35 @@ export const StageOperatorSelect = ({
6174
},
6275
[onChange, index]
6376
);
77+
const portalRef = React.useRef<HTMLDivElement | null>(null);
6478

6579
return (
66-
<Combobox
67-
value={selectedStage}
68-
disabled={isDisabled}
69-
aria-label="Select a stage operator"
70-
onChange={onStageOperatorSelected}
71-
size="default"
72-
clearable={false}
73-
data-testid="stage-operator-combobox"
74-
className={comboboxStyles}
75-
// Used for testing to access the popover for a stage
76-
popoverClassName={`mongodb-compass-stage-operator-combobox-${index}`}
77-
>
78-
{stages.map((stage, index) => (
79-
<ComboboxOption
80-
data-testid={`combobox-option-stage-${stage.name}`}
81-
key={`combobox-option-stage-${index}`}
82-
value={stage.name}
83-
displayName={stage.name}
84-
description={
85-
(isAtlasOnly(stage.env) ? 'Atlas only. ' : '') + stage.description
86-
}
87-
/>
88-
))}
89-
</Combobox>
80+
<React.Fragment>
81+
<div className={comboboxPortalStyles} ref={portalRef} />
82+
<Combobox
83+
value={selectedStage}
84+
disabled={isDisabled}
85+
aria-label="Select a stage operator"
86+
onChange={onStageOperatorSelected}
87+
size="default"
88+
clearable={false}
89+
data-testid="stage-operator-combobox"
90+
className={comboboxStyles}
91+
portalContainer={portalRef.current}
92+
usePortal
93+
>
94+
{stages.map((stage, index) => (
95+
<ComboboxOption
96+
data-testid={`combobox-option-stage-${stage.name}`}
97+
key={`combobox-option-stage-${index}`}
98+
value={stage.name}
99+
description={
100+
(isAtlasOnly(stage.env) ? 'Atlas only. ' : '') + stage.description
101+
}
102+
/>
103+
))}
104+
</Combobox>
105+
</React.Fragment>
90106
);
91107
};
92108

packages/compass-components/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,15 @@
4040
"@leafygreen-ui/card": "^10.0.6",
4141
"@leafygreen-ui/checkbox": "^12.1.1",
4242
"@leafygreen-ui/code": "^14.3.1",
43+
"@leafygreen-ui/combobox": "^9.1.6",
4344
"@leafygreen-ui/confirmation-modal": "^5.2.0",
4445
"@leafygreen-ui/emotion": "^4.0.7",
4546
"@leafygreen-ui/guide-cue": "^5.0.6",
4647
"@leafygreen-ui/hooks": "^8.1.2",
4748
"@leafygreen-ui/icon": "^12.0.0",
4849
"@leafygreen-ui/icon-button": "^15.0.20",
4950
"@leafygreen-ui/info-sprinkle": "^1.0.3",
50-
"@leafygreen-ui/inline-definition": "^6.0.14",
5151
"@leafygreen-ui/leafygreen-provider": "^3.1.12",
52-
"@leafygreen-ui/lib": "^13.2.1",
5352
"@leafygreen-ui/logo": "^9.1.1",
5453
"@leafygreen-ui/marketing-modal": "^4.2.1",
5554
"@leafygreen-ui/menu": "^23.0.2",
@@ -84,7 +83,6 @@
8483
"is-electron-renderer": "^2.0.1",
8584
"lodash": "^4.17.21",
8685
"polished": "^4.2.2",
87-
"prop-types": "^15.7.2",
8886
"react": "^17.0.2",
8987
"react-hotkeys-hook": "^4.3.7",
9088
"react-intersection-observer": "^8.34.0",

packages/compass-components/src/components/actions/item-action-group.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export function ItemActionGroup<Action extends string>({
7979

8080
const item = (
8181
<ItemComponent
82+
key={itemProps.action}
8283
{...itemProps}
8384
iconSize={iconSize}
8485
iconStyle={iconStyle}

packages/compass-components/src/components/combobox-with-custom-option.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import React, { useState, useMemo } from 'react';
2-
import { Combobox } from './combobox';
3-
import type {
4-
ComboboxProps,
5-
onChangeType,
6-
SelectValueType,
7-
} from './combobox/Combobox.types';
2+
import { Combobox } from './leafygreen';
3+
import type { ComboboxProps } from '@leafygreen-ui/combobox';
84

5+
type SelectValueType<T extends boolean> = Required<ComboboxProps<T>>['value'];
6+
type OnChangeType<T extends boolean> = Required<ComboboxProps<T>>['onChange'];
97
type ComboboxWithCustomOptionProps<T extends boolean, K> = ComboboxProps<T> & {
108
options: K[];
119
renderOption: (option: K, index: number, isCustom: boolean) => JSX.Element;
@@ -36,7 +34,7 @@ export const ComboboxWithCustomOption = <
3634
);
3735
}
3836
return _opts;
39-
}, [userOptions, customOptions, search]);
37+
}, [userOptions, customOptions, search, renderOption]);
4038

4139
const selectValueAndRunOnChange = (value: string[] | string | null) => {
4240
if (!onChange || !value) return;
@@ -47,13 +45,13 @@ export const ComboboxWithCustomOption = <
4745
.filter((value) => !userOptions.find((x) => x.value === value))
4846
.map((x) => ({ value: x })) as K[];
4947
setCustomOptions(customOptions);
50-
(onChange as onChangeType<true>)(multiSelectValues);
48+
(onChange as OnChangeType<true>)(multiSelectValues);
5149
} else {
5250
const selectValue = value as SelectValueType<false>;
5351
if (selectValue && !userOptions.find((x) => x.value === selectValue)) {
5452
setCustomOptions([{ value: selectValue } as K]);
5553
}
56-
(onChange as onChangeType<false>)(selectValue);
54+
(onChange as OnChangeType<false>)(selectValue);
5755
}
5856
};
5957

packages/compass-components/src/components/combobox-with-custom-options.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from '@mongodb-js/testing-library-compass';
1010

1111
import { ComboboxWithCustomOption } from './combobox-with-custom-option';
12-
import { ComboboxOption } from './combobox/ComboboxOption';
12+
import { ComboboxOption } from './leafygreen';
1313

1414
const renderCombobox = (
1515
props: Partial<ComponentProps<typeof ComboboxWithCustomOption>> = {}

0 commit comments

Comments
 (0)