Conversation
…ab position correctly since our reordering logic is duplicating in two components and, moreover, I found a bug in one of the implementations, I decided to put all the common logic to a dedicated helper with test coverage to be sure we use the right logic everywhere.
|
SqlResultsTabs Screen.Recording.2025-11-05.at.18.01.56.mov |
…ring in useHeaderDnD
|
Changed reorderArray implementation for useHeaderDnD (see implementation and tests). I believe this is the right implementation and we don't use this header dnd yet so it's safe to change it now. |
| manual, | ||
| }); | ||
|
|
||
| const tabOrderKey = container ? `tabs-order-${container.areaLabel}` : 'tabs-no-persist'; |
There was a problem hiding this comment.
areaLabel can't be used as a stable storage key, please introduce new prop for TabsState
|
|
||
| const onReorder = | ||
| onReorderProp || | ||
| ((draggedTabId: string, targetTabId: string, position: 'before' | 'after') => { |
…tracting some logic to helpers
- moved the tab order persistence logic into a new useTabOrderPersistence hook to make the flow is more obvious (we use this default persistence only with tabs container) - introduced new reorderStateKey tab state to have an identifier for a tab panel, use it in canDrop check to prevent cross-panel DnD -replaced reorderable prop with reorderStateKey, because without a key you can't use reordering
… for improved drag-and-drop UI
There was a problem hiding this comment.
Pull Request Overview
This PR adds drag-and-drop reordering functionality to various tab components in the application, including Panels, Navigator Tabs, and SQL Result Tabs. The implementation introduces a new reusable hook system for tab reordering with persistent state storage.
Key changes:
- Implemented a generic
reorderArrayutility function with comprehensive test coverage - Added
useTabDragAndDropanduseTabOrderPersistencehooks for managing tab reordering - Integrated reordering capabilities into multiple tab components (ToolsPanel, NavigationTabs, SqlResultTabs, SideBarPanel)
Reviewed Changes
Copilot reviewed 28 out of 29 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| webapp/yarn.lock | Added new dependencies for testing and drag-and-drop functionality |
| webapp/packages/plugin-tools-panel/src/ToolsPanel/ToolsPanel.tsx | Integrated tab reordering with persistence for tools panel |
| webapp/packages/plugin-sql-editor/src/SqlResultTabs/SqlResultTabs.tsx | Added reorder handler for SQL result tabs |
| webapp/packages/plugin-navigation-tabs/tsconfig.json | Added js-helpers package reference |
| webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsService.ts | Refactored tabIdList getter to use persisted tab order and added reorderTab method |
| webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/NavigationTabsBar.tsx | Implemented reorder callback for navigation tabs |
| webapp/packages/plugin-navigation-tabs/package.json | Added js-helpers dependency |
| webapp/packages/core-ui/tsconfig.json | Added references to react-dnd, react-tests, and cli packages |
| webapp/packages/core-ui/src/index.ts | Exported new tab drag-and-drop utilities |
| webapp/packages/core-ui/src/Tabs/useTabOrderPersistence.ts | New hook for persisting tab order across sessions |
| webapp/packages/core-ui/src/Tabs/useTabDragAndDrop.ts | New hook providing drag-and-drop functionality for tabs |
| webapp/packages/core-ui/src/Tabs/TabsState.tsx | Added reorder state key and callback support |
| webapp/packages/core-ui/src/Tabs/TabsContext.ts | Extended context interface with reorder functionality |
| webapp/packages/core-ui/src/Tabs/TabsContainer/TabsContainer.ts | Implemented applyOrder method for tab ordering |
| webapp/packages/core-ui/src/Tabs/TabsContainer/ITabsContainer.ts | Added applyOrder to interface |
| webapp/packages/core-ui/src/Tabs/TabsBox/TabsBox.tsx | Added reorder props support |
| webapp/packages/core-ui/src/Tabs/Tab/useTab.ts | Added reorderStateKey getter |
| webapp/packages/core-ui/src/Tabs/Tab/Tab.tsx | Integrated drag-and-drop functionality with visual feedback |
| webapp/packages/core-ui/src/Tabs/Tab/Tab.module.css | Added CSS styles for drag-and-drop visual states |
| webapp/packages/core-ui/src/SideBarPanel/SideBarPanel.tsx | Enabled tab reordering for sidebar panels |
| webapp/packages/core-ui/package.json | Added test dependencies and react-dnd package |
| webapp/common-typescript/@dbeaver/js-helpers/src/reorderArray.ts | New utility function for reordering array elements with multiple signature overloads |
| webapp/common-typescript/@dbeaver/js-helpers/src/reorderArray.test.ts | Comprehensive test suite for reorderArray function |
| webapp/common-typescript/@dbeaver/js-helpers/src/index.ts | Exported reorderArray utility |
| webapp/common-react/@dbeaver/react-data-grid/tsconfig.json | Added js-helpers package reference |
| webapp/common-react/@dbeaver/react-data-grid/src/useHeaderDnD.ts | Updated to use shared reorderArray utility |
| webapp/common-react/@dbeaver/react-data-grid/src/reorderArray.ts | Removed local implementation in favor of shared utility |
| webapp/common-react/@dbeaver/react-data-grid/src/index.ts | Removed reorderArray export |
| webapp/common-react/@dbeaver/react-data-grid/package.json | Added js-helpers dependency |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…or improved performance
…' of github.com:dbeaver/cloudbeaver into 4583-cb-3739-add-reorder-option-to-tabs-scripts-objects
| dropProps, | ||
| } = useTabDragAndDrop({ | ||
| tabId, | ||
| stateKey: tab.reorderStateKey || undefined, |
There was a problem hiding this comment.
Seems like tab.reorderStateKey has type of reorderStateKey?: string so there is no need for fallback?
| export interface ITabDragAndDropOptions { | ||
| tabId: string; | ||
| stateKey: string | undefined; | ||
| onReorder: ((draggedTabId: string, targetTabId: string, position: 'before' | 'after') => void) | null; |
There was a problem hiding this comment.
we duplicate position: 'before' | 'after', probably we want to move it to separate type like TabReorderPosition
There was a problem hiding this comment.
We fixed it in one place but the type declaration repeats across entire pr)
| draggable: !!stateKey, | ||
| onDragStart: (event, store) => { | ||
| event.stopPropagation(); | ||
| store.setData('dbeaver-tab-id', tabId); |
There was a problem hiding this comment.
We repeat this variables across the hook, should we move them to const and use like this?
DBEAVER_TAB_ID = dbeaver-tab-id
store?.getData(DBEAVER_TAB_ID);
…er and update useTabOrderPersistence to not have dependencies on container
…olsPanel Since we are not mutating a container state anymore, we have to update sorting separately in TabList level because it reads directly from the container.
… useTabDragAndDrop
…lResultTabs to use it
Panels
Screen.Recording.2025-11-05.at.15.43.18.mov
Navigator Tabs
Screen.Recording.2025-11-05.at.15.45.16.mov
ObjectView tabs remain not reorderable. Do we want to move them also?
