This is an automated email from the ASF dual-hosted git repository.
EnxDev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new e338c77dd73 fix(dashboard-tabs): disable drag on input fields during
tab reorder (#36889)
e338c77dd73 is described below
commit e338c77dd737a3247a499fe2c9b4f6cfbf650040
Author: Enzo Martellucci <[email protected]>
AuthorDate: Mon Jul 27 16:06:41 2026 +0200
fix(dashboard-tabs): disable drag on input fields during tab reorder
(#36889)
---
.../TabsRenderer/TabsRenderer.test.tsx | 65 ++++++++++++++++++++++
.../gridComponents/TabsRenderer/TabsRenderer.tsx | 8 ++-
2 files changed, 72 insertions(+), 1 deletion(-)
diff --git
a/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.test.tsx
b/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.test.tsx
index cd5605b9500..3f914f5546f 100644
---
a/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.test.tsx
+++
b/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.test.tsx
@@ -48,10 +48,50 @@ const mockProps: TabsRendererProps = {
tabBarPaddingLeft: 16,
};
+// Mirrors the tab label markup of Tab.tsx: the title lives in a
+// .dragdroppable-tab container and renders as a textarea via EditableTitle
+const draggableTabProps: TabsRendererProps = {
+ ...mockProps,
+ editMode: true,
+ tabItems: [
+ {
+ ...mockTabItems[0],
+ label: (
+ <div className="dragdroppable-tab">
+ <span className="editable-title">
+ <textarea defaultValue="Tab 1" />
+ </span>
+ </div>
+ ),
+ },
+ mockTabItems[1],
+ ],
+};
+
+// jsdom implements no PointerEvent, so @dnd-kit's PointerSensor never
activates
+class MockPointerEvent extends MouseEvent {
+ isPrimary: boolean;
+
+ pointerId: number;
+
+ constructor(type: string, init: PointerEventInit = {}) {
+ super(type, init);
+ this.isPrimary = init.isPrimary ?? true;
+ this.pointerId = init.pointerId ?? 1;
+ }
+}
+
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from
describe blocks
describe('TabsRenderer', () => {
+ const { PointerEvent: OriginalPointerEvent } = globalThis;
+
beforeEach(() => {
jest.clearAllMocks();
+ globalThis.PointerEvent = MockPointerEvent as typeof PointerEvent;
+ });
+
+ afterEach(() => {
+ globalThis.PointerEvent = OriginalPointerEvent;
});
test('renders tabs container with correct test attributes', () => {
@@ -199,4 +239,29 @@ describe('TabsRenderer', () => {
expect(screen.getByText('Tab 1 Content')).toBeInTheDocument();
expect(screen.queryByText('Tab 2 Content')).not.toBeInTheDocument(); //
Not active
});
+
+ test('drags from the tab title and shows the drag indicator only then', ()
=> {
+ render(<TabsRenderer {...draggableTabProps} />);
+ const container = screen.getByTestId('dashboard-component-tabs');
+ const title = container.querySelector('textarea') as HTMLTextAreaElement;
+
+ // At rest the title keeps the text cursor it sets on itself
+ expect(container).not.toHaveStyleRule('cursor', 'move', {
+ target: '.dragdroppable-tab *',
+ });
+
+ // Pressing on the title and moving past the sensor's distance constraint
+ // has to start a drag: the title covers most of the tab, so a tab that
+ // cannot be dragged from there cannot really be dragged at all
+ fireEvent.pointerDown(title, { button: 0, isPrimary: true, clientX: 0 });
+ fireEvent.pointerMove(document, {
+ button: 0,
+ isPrimary: true,
+ clientX: 50,
+ });
+
+ expect(container).toHaveStyleRule('cursor', 'move', {
+ target: '.dragdroppable-tab *',
+ });
+ });
});
diff --git
a/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx
b/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx
index d9e34e8ec23..9e6cf9c423e 100644
---
a/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx
+++
b/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx
@@ -72,10 +72,16 @@ const StyledTabsContainer = styled.div<{ isDragging?:
boolean }>`
}
}
- /* Hide ink-bar during drag */
${({ isDragging }) =>
isDragging &&
`
+ /* Show the drag indicator during drag, over the tab title textarea too.
+ The doubled parent outranks the title's own cursor; a single & loses. */
+ && .dragdroppable-tab * {
+ cursor: move;
+ }
+
+ /* Hide ink-bar during drag */
.ant-tabs-card > .ant-tabs-nav .ant-tabs-ink-bar,
.ant-tabs > .ant-tabs-nav .ant-tabs-ink-bar {
display: none !important;