Skip to content

Commit f5b44b9

Browse files
kraenhansengagik
andauthored
feat(sidebar): context menu to control specific navigation items COMPASS-9393 (#7070)
--------- Co-authored-by: gagik <[email protected]>
1 parent f8dc1a3 commit f5b44b9

22 files changed

+926
-155
lines changed

package-lock.json

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

packages/compass-components/src/components/actions/dropdown-menu-button.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import { Button, Icon, Menu, MenuItem, MenuSeparator } from '../leafygreen';
77
import { WorkspaceContainer } from '../workspace-container';
88

99
import { ItemActionButtonSize } from './constants';
10-
import { actionTestId } from './utils';
1110
import { ActionGlyph } from './action-glyph';
12-
import { isSeparatorMenuAction, type MenuAction } from './item-action-menu';
11+
import { actionTestId, isSeparatorMenuAction } from './utils';
12+
import type { MenuAction } from './types';
1313

1414
const getHiddenOnNarrowStyles = (narrowBreakpoint: string) =>
1515
css({

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import { MenuSeparator, Tooltip } from '../leafygreen';
66

77
import { ItemActionButtonSize } from './constants';
88
import type { ItemAction, ItemSeparator } from './types';
9-
import { isSeparatorMenuAction } from './item-action-menu';
109
import { ItemActionButton } from './item-action-button';
11-
import { actionTestId } from './utils';
10+
import { actionTestId, isSeparatorMenuAction } from './utils';
1211

1312
export type GroupedItemAction<Action extends string> = ItemAction<Action> & {
1413
tooltipProps?: Parameters<typeof Tooltip>;

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

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,9 @@ import { Menu, MenuItem, MenuSeparator } from '../leafygreen';
66

77
import { ItemActionButtonSize } from './constants';
88
import { ActionGlyph } from './action-glyph';
9-
import type { ItemBase, ItemSeparator } from './types';
9+
import type { MenuAction } from './types';
1010
import { SmallIconButton } from './small-icon-button';
11-
import { actionTestId } from './utils';
12-
13-
export type MenuAction<Action extends string> =
14-
| ItemBase<Action>
15-
| ItemSeparator;
16-
17-
export function isSeparatorMenuAction(value: unknown): value is ItemSeparator {
18-
return (
19-
typeof value === 'object' &&
20-
value !== null &&
21-
'separator' in value &&
22-
value.separator === true
23-
);
24-
}
11+
import { actionTestId, isSeparatorMenuAction } from './utils';
2512

2613
const containerStyle = css({
2714
flex: 'none',

packages/compass-components/src/components/actions/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,7 @@ export type ItemAction<Action extends string> = {
3636
} & ItemBase<Action>;
3737

3838
export type ItemSeparator = { separator: true };
39+
40+
export type MenuAction<Action extends string> =
41+
| ItemBase<Action>
42+
| ItemSeparator;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { expect } from 'chai';
2+
import { splitBySeparator } from './utils';
3+
4+
describe('item action utils', function () {
5+
describe('splitBySeparator', function () {
6+
it('returns an empty array for an empty input', function () {
7+
const result = splitBySeparator([]);
8+
expect(result).is.empty;
9+
});
10+
11+
it('returns a single item for a single input', function () {
12+
const result = splitBySeparator([{ label: 'Foo', action: 'foo' }]);
13+
expect(result).deep.equal([[{ label: 'Foo', action: 'foo' }]]);
14+
});
15+
16+
it('splits four items separated by a separator', function () {
17+
const result = splitBySeparator([
18+
{ label: 'Foo', action: 'foo' },
19+
{ label: 'Bar', action: 'bar' },
20+
{ separator: true },
21+
{ label: 'Baz', action: 'baz' },
22+
{ label: 'Qux', action: 'qux' },
23+
]);
24+
expect(result).deep.equal([
25+
[
26+
{ label: 'Foo', action: 'foo' },
27+
{ label: 'Bar', action: 'bar' },
28+
],
29+
[
30+
{ label: 'Baz', action: 'baz' },
31+
{ label: 'Qux', action: 'qux' },
32+
],
33+
]);
34+
});
35+
36+
it('disregards leading separators', function () {
37+
const result = splitBySeparator([
38+
{ separator: true },
39+
{ label: 'Foo', action: 'foo' },
40+
]);
41+
expect(result).deep.equal([[{ label: 'Foo', action: 'foo' }]]);
42+
});
43+
44+
it('disregards trailing separators', function () {
45+
const result = splitBySeparator([
46+
{ label: 'Foo', action: 'foo' },
47+
{ separator: true },
48+
]);
49+
expect(result).deep.equal([[{ label: 'Foo', action: 'foo' }]]);
50+
});
51+
});
52+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,35 @@
1+
import type { ItemBase, ItemSeparator, MenuAction } from './types';
2+
3+
export function isSeparatorMenuAction(value: unknown): value is ItemSeparator {
4+
return (
5+
typeof value === 'object' &&
6+
value !== null &&
7+
'separator' in value &&
8+
value.separator === true
9+
);
10+
}
11+
112
export function actionTestId(dataTestId: string | undefined, action: string) {
213
return dataTestId ? `${dataTestId}-${action}-action` : undefined;
314
}
15+
16+
export function splitBySeparator<Action extends string>(
17+
actions: MenuAction<Action>[]
18+
) {
19+
const result: ItemBase<Action>[][] = [];
20+
let currentGroup: ItemBase<Action>[] = [];
21+
for (const action of actions) {
22+
if (isSeparatorMenuAction(action)) {
23+
if (currentGroup.length > 0) {
24+
result.push(currentGroup);
25+
currentGroup = [];
26+
}
27+
} else {
28+
currentGroup.push(action);
29+
}
30+
}
31+
if (currentGroup.length > 0) {
32+
result.push(currentGroup);
33+
}
34+
return result;
35+
}

packages/compass-components/src/components/context-menu.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import {
1111
type ContextMenuWrapperProps,
1212
} from '@mongodb-js/compass-context-menu';
1313

14-
export type { ContextMenuItem } from '@mongodb-js/compass-context-menu';
14+
export type {
15+
ContextMenuItem,
16+
ContextMenuItemGroup,
17+
} from '@mongodb-js/compass-context-menu';
1518

1619
// TODO: Remove these once https://jira.mongodb.org/browse/LG-5013 is resolved
1720

packages/compass-components/src/index.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,19 @@ import ResizableSidebar, {
5151
defaultSidebarWidth,
5252
} from './components/resizeable-sidebar';
5353

54-
import type {
54+
export type {
5555
ItemAction,
5656
ItemComponentProps,
5757
ItemSeparator,
58+
MenuAction,
5859
} from './components/actions/types';
59-
import type { GroupedItemAction } from './components/actions/item-action-group';
60-
import type { MenuAction } from './components/actions/item-action-menu';
60+
export { splitBySeparator } from './components/actions/utils';
61+
export type { GroupedItemAction } from './components/actions/item-action-group';
6162

62-
import { ItemActionControls } from './components/actions/item-action-controls';
63-
import { ItemActionGroup } from './components/actions/item-action-group';
64-
import { ItemActionMenu } from './components/actions/item-action-menu';
65-
import { DropdownMenuButton } from './components/actions/dropdown-menu-button';
63+
export { ItemActionControls } from './components/actions/item-action-controls';
64+
export { ItemActionGroup } from './components/actions/item-action-group';
65+
export { ItemActionMenu } from './components/actions/item-action-menu';
66+
export { DropdownMenuButton } from './components/actions/dropdown-menu-button';
6667

6768
export { DocumentIcon } from './components/icons/document-icon';
6869
export { FavoriteIcon } from './components/icons/favorite-icon';
@@ -104,15 +105,11 @@ export {
104105
useContextMenuItems,
105106
useContextMenuGroups,
106107
type ContextMenuItem,
108+
type ContextMenuItemGroup,
107109
} from './components/context-menu';
108110

109111
export type {
110112
FileInputBackend,
111-
ItemAction,
112-
ItemComponentProps,
113-
GroupedItemAction,
114-
MenuAction,
115-
ItemSeparator,
116113
ElectronFileDialogOptions,
117114
ElectronShowFileDialogProvider,
118115
};
@@ -131,10 +128,6 @@ export {
131128
ResizableSidebar,
132129
WarningSummary,
133130
WorkspaceTabs,
134-
ItemActionControls,
135-
ItemActionGroup,
136-
ItemActionMenu,
137-
DropdownMenuButton,
138131
defaultSidebarWidth,
139132
createElectronFileInputBackend,
140133
createJSDomFileInputDummyBackend,

packages/compass-connections-navigation/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@
4949
"reformat": "npm run eslint . -- --fix && npm run prettier -- --write ."
5050
},
5151
"dependencies": {
52-
"@mongodb-js/compass-connections": "^1.64.0",
5352
"@mongodb-js/compass-components": "^1.42.0",
54-
"@mongodb-js/connection-info": "^0.15.5",
55-
"@mongodb-js/connection-form": "^1.56.0",
53+
"@mongodb-js/compass-connections": "^1.64.0",
54+
"@mongodb-js/compass-context-menu": "^0.2.0",
5655
"@mongodb-js/compass-workspaces": "^0.45.0",
56+
"@mongodb-js/connection-form": "^1.56.0",
57+
"@mongodb-js/connection-info": "^0.15.5",
5758
"compass-preferences-model": "^2.44.0",
5859
"mongodb-build-info": "^1.7.2",
5960
"react": "^17.0.2",

0 commit comments

Comments
 (0)