Skip to content

feat(sidebar): context menu to control specific navigation items COMPASS-9393 #7070

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jul 11, 2025

Conversation

kraenhansen
Copy link
Contributor

@kraenhansen kraenhansen commented Jul 1, 2025

Description

Merging this PR will:

  • Refactor NavigationBaseItem to use forwardRef, in order for the parent component to attach the context menu (e962c88)
  • Pass a new getContextMenuGroups through sidebar navigation component tree, similar to how it's currently done for getItemActions (7ee2df8)
  • Refactor the "actions" abstraction of the components package (97465c9) as preparation for 👇
  • Add a new splitBySeparator utility function, to split actions into groups by their use of a separator item. Used to construct context menus, where each groups is an array of menu items. (23d4ad7)
  • Implement three levels of menus (connection, database and collection) which each include the menu items of the parent level (70bc8ad)
right-click-navigation-items.mov

Checklist

  • New tests and/or benchmarks are included
  • Documentation is changed or added
  • If this change updates the UI, screenshots/videos are added and a design review is requested
  • I have signed the MongoDB Contributor License Agreement (https://www.mongodb.com/legal/contributor-agreement)

Motivation and Context

  • Bugfix
  • New feature
  • Dependency update
  • Misc

Open Questions

I've decided to include all actions (not just those under "...") but also the actions "above the collapse", which is a deviation from the original design.

I've also followed the pattern of cascading actions, such that:

  • Right clicking a database shows actions for the connection too
  • Right clicking a collection shows actions for the database and connection too

☝️ this doesn't match the design but was discussed in comments on Figma.

Dependents

Types of changes

  • Backport Needed
  • Patch (non-breaking change which fixes an issue)
  • Minor (non-breaking change which adds functionality)
  • Major (fix or feature that would cause existing functionality to change)

@github-actions github-actions bot added the feat label Jul 1, 2025
Base automatically changed from gagik/context-menu-compass-ui to main July 1, 2025 14:23
@kraenhansen kraenhansen force-pushed the kh/sidebar-navigation-item-menus branch from 70bc8ad to 0fb7a1e Compare July 1, 2025 15:31
@kraenhansen kraenhansen force-pushed the kh/sidebar-navigation-item-menus branch from 0fb7a1e to 915e207 Compare July 2, 2025 06:44
@kraenhansen kraenhansen requested a review from gagik July 2, 2025 06:45
@kraenhansen kraenhansen marked this pull request as ready for review July 2, 2025 06:45
@Copilot Copilot AI review requested due to automatic review settings July 2, 2025 06:45
@kraenhansen kraenhansen requested a review from a team as a code owner July 2, 2025 06:45
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds context menu support to sidebar navigation items by refactoring base components, introducing a new context‐menu grouping helper, and wiring a cascading getContextMenuGroups prop through the navigation tree.

  • Refactor NavigationBaseItem to use forwardRef so it can receive a context‐menu trigger ref.
  • Propagate a new getContextMenuGroups callback through VirtualTree, TreeItem, and NavigationItem.
  • Introduce splitBySeparator and itemActionsToContextMenuGroups utilities (with tests) to layout context menu groups.

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/compass-connections-navigation/src/virtual-list/virtual-list.tsx Added getContextMenuGroups to virtual list props
packages/compass-connections-navigation/src/tree-data.ts Added connectionItem and databaseItem to tree items
packages/compass-connections-navigation/src/navigation-item.tsx Wired up useContextMenuGroups and passed getContextMenuGroups
packages/compass-connections-navigation/src/context-menus.ts Added itemActionsToContextMenuGroups helper
packages/compass-connections-navigation/src/connections-navigation-tree.tsx Implemented cascading getContextMenuGroups logic
packages/compass-connections-navigation/src/base-navigation-item.tsx Refactored to forwardRef and attached ref to root div
packages/compass-components/src/index.ts Exposed new context-menu types and splitBySeparator
packages/compass-components/src/components/context-menu.tsxx Exported ContextMenuItemGroup
packages/compass-components/src/components/actions/utils.ts Implemented splitBySeparator and isSeparatorMenuAction
packages/compass-components/src/components/actions/utils.spec.ts Added tests for splitBySeparator
packages/compass-components/src/components/actions/types.ts Introduced MenuAction and ItemSeparator types
packages/compass-components/src/components/actions/item-action-menu.tsx Refactored imports to use shared utils
packages/compass-components/src/components/actions/item-action-group.tsx Updated imports to use shared utils
packages/compass-components/src/components/actions/dropdown-menu-button.tsx Updated imports to use shared utils
Comments suppressed due to low confidence (4)

packages/compass-connections-navigation/src/context-menus.ts:1

  • [nitpick] Add unit tests for itemActionsToContextMenuGroups to verify that actions are correctly split into groups and mapped to menu items.
import {

packages/compass-connections-navigation/src/connections-navigation-tree.tsx:267

  • The function collectionItemActions is referenced here but not imported. Add import { collectionItemActions } from './item-actions'; to avoid a runtime/compile error.
              collectionItemActions({

packages/compass-connections-navigation/src/navigation-item.tsx:9

  • [nitpick] Remove the unused import ItemAction since it isn't used in this file to keep the imports clean.
  type ItemAction,

packages/compass-connections-navigation/src/connections-navigation-tree.tsx:18

  • [nitpick] Only ContextMenuItemGroup is actually used here. Consider removing the unused ItemAction and ItemSeparator imports.
} from '@mongodb-js/compass-components';

@kraenhansen kraenhansen self-assigned this Jul 2, 2025
Copy link
Collaborator

@gribnoysup gribnoysup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code part looks good, but I'm really unsure if stacking menus makes sense here, let's maybe ask design for feedback on that. In particular the list of actions for collection is so big it's somewhat disorienting (but maybe this will be better with a compact version of the menu?), I'm also not sure if showing "open shell" on db or coll will be confusing if it will not open shell with namespace preselected, as this is what the "open shell" buttons we have in other scoped parts of UI do

| SidebarNotConnectedConnectionTreeItem,
action: Actions
) => {
const onItemAction = useCallback(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This refactor was necessary to remove the explicit tie-in with the item type and the actions it can run. This would lead to actions silently being dropped when running i.e. 'open-shell' with a collection item that has a valid connectionId, even though it has all the information needed for the action to execute.

Now, the requirements are more explicitly based on the available fields and are tied to the action being run asserting for certain types / fields existing.

@@ -243,3 +245,192 @@ export const collectionItemActions = ({

return actions;
};

export const databaseContextMenuActions = ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

won't be able to reuse actions in this case since we decided to go a more custom route

{ separator: true },
isShellEnabled
? {
action: 'open-shell',
Copy link
Contributor

@mabaasit mabaasit Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right-clicking on db/collection, we should open shell for them, right? if you open shell from db screen, it automatically switches to that db usinguse dbName. And for collection, it switches and writes a find query.

Copy link
Contributor

@mabaasit mabaasit Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This behaviour is a bit different to what a user would expect

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great point, my solution is going to be to remove this from collection level and making a note of this as a descoped feature

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feel free to ignore if its more work: for this action, we already have an item and we can do exactly what we do at other places:

  1. For dbItem we can add {initialEvaluate: use ${namespace}} to the options
  2. For collItem we can add initialEvaluate and initialInput

This way we will have same exact behaviour and also have shell in the menu.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh that seems good!

@gagik gagik self-requested a review July 10, 2025 13:18
@gagik gagik self-assigned this Jul 10, 2025
@gagik gagik requested a review from mabaasit July 10, 2025 13:18
icon: 'Clone',
},
isAtlas
? null
: {
action: 'remove-connection',
label: 'Remove',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does change in both in sidebar and context menu but this creates better consistency in general. We have 'Edit connection' so one would expect the other actions to also have "connection" in their action name just like they do database, collection etc.

Copy link
Contributor

@mabaasit mabaasit Jul 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe we add it for favorite/unfavorite as well then?

@gagik gagik force-pushed the kh/sidebar-navigation-item-menus branch from 45a42df to c07aaa7 Compare July 11, 2025 09:32
@gagik gagik changed the base branch from main to wizard-experiments July 11, 2025 09:46
@gagik gagik changed the base branch from wizard-experiments to main July 11, 2025 09:46
Copy link

Semgrep found 4 run-shell-injection findings:

Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".

@gagik gagik merged commit f5b44b9 into main Jul 11, 2025
59 of 60 checks passed
@gagik gagik deleted the kh/sidebar-navigation-item-menus branch July 11, 2025 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants