Skip to content

Commit fd1db23

Browse files
authored
fix: support resizing widgets in rtl (#7803)
1 parent af5c2b1 commit fd1db23

File tree

4 files changed

+95
-71
lines changed

4 files changed

+95
-71
lines changed

packages/dashboard/src/vaadin-dashboard-widget.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class DashboardWidget extends ControllerMixin(ElementMixin(PolylitMixin(LitEleme
5454
display: var(--_vaadin-dashboard-widget-actions-display, none);
5555
position: absolute;
5656
bottom: 0;
57-
right: 0;
57+
inset-inline-end: 0;
5858
font-size: 30px;
5959
cursor: grab;
6060
line-height: 1;
@@ -64,6 +64,10 @@ class DashboardWidget extends ControllerMixin(ElementMixin(PolylitMixin(LitEleme
6464
content: '\\2921';
6565
}
6666
67+
:host([dir='rtl']) #resize-handle::before {
68+
content: '\\2922';
69+
}
70+
6771
:host::after {
6872
content: '';
6973
z-index: 2;

packages/dashboard/src/widget-resize-controller.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class WidgetResizeController extends EventTarget {
6262
return;
6363
}
6464

65-
this.__resizeWidth = this.__resizeStartWidth + e.detail.dx;
65+
this.__resizeWidth = this.__resizeStartWidth + (document.dir === 'rtl' ? -e.detail.dx : e.detail.dx);
6666
this.__resizeHeight = this.__resizeStartHeight + e.detail.dy;
6767
this.__updateWidgetStyles();
6868

packages/dashboard/test/dashboard-widget-resizing.test.ts

Lines changed: 69 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import '../vaadin-dashboard.js';
55
import { isSafari } from '@vaadin/component-base/src/browser-utils.js';
66
import type { Dashboard, DashboardItem } from '../vaadin-dashboard.js';
77
import {
8+
describeBidirectional,
89
expectLayout,
910
fireResizeEnd,
1011
fireResizeOver,
@@ -51,89 +52,91 @@ describe('dashboard - widget resizing', () => {
5152
});
5253

5354
describe('mouse drag', () => {
54-
it('should resize a widget while dragging (start -> end)', async () => {
55-
// Start dragging the first widget resize handle
56-
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
57-
await nextFrame();
55+
describeBidirectional('horizontal', () => {
56+
it('should resize a widget while dragging (start -> end)', async () => {
57+
// Start dragging the first widget resize handle
58+
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
59+
await nextFrame();
5860

59-
// Drag over the end edge of the second one
60-
fireResizeOver(getElementFromCell(dashboard, 0, 1)!, 'end');
61-
await nextFrame();
61+
// Drag over the end edge of the second one
62+
fireResizeOver(getElementFromCell(dashboard, 0, 1)!, 'end');
63+
await nextFrame();
6264

63-
fireResizeEnd(dashboard);
64-
await nextFrame();
65+
fireResizeEnd(dashboard);
66+
await nextFrame();
6567

66-
// Expect the widgets to be reordered
67-
// prettier-ignore
68-
expectLayout(dashboard, [
69-
[0, 0],
70-
[1],
71-
]);
72-
});
68+
// Expect the widgets to be reordered
69+
// prettier-ignore
70+
expectLayout(dashboard, [
71+
[0, 0],
72+
[1],
73+
]);
74+
});
7375

74-
it('should not resize if dragged barely over another widget (start -> end)', async () => {
75-
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
76-
await nextFrame();
76+
it('should not resize if dragged barely over another widget (start -> end)', async () => {
77+
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
78+
await nextFrame();
7779

78-
fireResizeOver(getElementFromCell(dashboard, 0, 1)!, 'start');
79-
await nextFrame();
80+
fireResizeOver(getElementFromCell(dashboard, 0, 1)!, 'start');
81+
await nextFrame();
8082

81-
fireResizeEnd(dashboard);
82-
await nextFrame();
83+
fireResizeEnd(dashboard);
84+
await nextFrame();
8385

84-
// prettier-ignore
85-
expectLayout(dashboard, [
86-
[0, 1],
87-
]);
88-
});
86+
// prettier-ignore
87+
expectLayout(dashboard, [
88+
[0, 1],
89+
]);
90+
});
8991

90-
it('should resize a widget while dragging (end -> start)', async () => {
91-
dashboard.items = [{ id: 0, colspan: 2 }, { id: 1 }];
92-
await nextFrame();
93-
// prettier-ignore
94-
expectLayout(dashboard, [
95-
[0, 0],
96-
[1],
97-
]);
92+
it('should resize a widget while dragging (end -> start)', async () => {
93+
dashboard.items = [{ id: 0, colspan: 2 }, { id: 1 }];
94+
await nextFrame();
95+
// prettier-ignore
96+
expectLayout(dashboard, [
97+
[0, 0],
98+
[1],
99+
]);
98100

99-
fireResizeStart(getElementFromCell(dashboard, 0, 1)!);
100-
await nextFrame();
101+
fireResizeStart(getElementFromCell(dashboard, 0, 1)!);
102+
await nextFrame();
101103

102-
fireResizeOver(getElementFromCell(dashboard, 0, 0)!, 'start');
103-
await nextFrame();
104+
fireResizeOver(getElementFromCell(dashboard, 0, 0)!, 'start');
105+
await nextFrame();
104106

105-
fireResizeEnd(dashboard);
106-
await nextFrame();
107+
fireResizeEnd(dashboard);
108+
await nextFrame();
107109

108-
// prettier-ignore
109-
expectLayout(dashboard, [
110-
[0, 1],
111-
]);
112-
});
110+
// prettier-ignore
111+
expectLayout(dashboard, [
112+
[0, 1],
113+
]);
114+
});
113115

114-
it('should not resize if dragged barely over another widget (end -> start)', async () => {
115-
dashboard.items = [{ id: 0, colspan: 2 }, { id: 1 }];
116-
await nextFrame();
117-
// prettier-ignore
118-
expectLayout(dashboard, [
119-
[0, 0],
120-
[1],
121-
]);
116+
it('should not resize if dragged barely over another widget (end -> start)', async () => {
117+
dashboard.items = [{ id: 0, colspan: 2 }, { id: 1 }];
118+
await nextFrame();
119+
// prettier-ignore
120+
expectLayout(dashboard, [
121+
[0, 0],
122+
[1],
123+
]);
122124

123-
fireResizeStart(getElementFromCell(dashboard, 0, 1)!);
124-
await nextFrame();
125+
fireResizeStart(getElementFromCell(dashboard, 0, 1)!);
126+
await nextFrame();
125127

126-
fireResizeOver(getElementFromCell(dashboard, 0, 0)!, 'end');
127-
await nextFrame();
128+
fireResizeOver(getElementFromCell(dashboard, 0, 0)!, 'end');
129+
await nextFrame();
128130

129-
fireResizeEnd(dashboard);
130-
await nextFrame();
131+
fireResizeEnd(dashboard);
132+
await nextFrame();
131133

132-
// prettier-ignore
133-
expectLayout(dashboard, [
134-
[0, 0],
135-
[1],
136-
]);
134+
// prettier-ignore
135+
expectLayout(dashboard, [
136+
[0, 0],
137+
[1],
138+
]);
139+
});
137140
});
138141

139142
it('should resize a widget while dragging (top -> bottom)', async () => {

packages/dashboard/test/helpers.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,15 @@ function _getRowHeights(dashboard: Element): number[] {
3737
}
3838

3939
function _getElementFromCell(dashboard: HTMLElement, rowIndex: number, columnIndex: number, rowHeights: number[]) {
40-
const { top, left } = dashboard.getBoundingClientRect();
40+
const { top, left, right } = dashboard.getBoundingClientRect();
4141
const columnWidths = getColumnWidths(dashboard);
42-
const x = left + columnWidths.slice(0, columnIndex).reduce((sum, width) => sum + width, 0);
42+
const columnOffset = columnWidths.slice(0, columnIndex).reduce((sum, width) => sum + width, 0);
43+
const rtl = document.dir === 'rtl';
44+
const x = rtl ? right - columnOffset : left + columnOffset;
4345
const y = top + rowHeights.slice(0, rowIndex).reduce((sum, height) => sum + height, 0);
4446

4547
return document
46-
.elementsFromPoint(x + columnWidths[columnIndex] / 2, y + rowHeights[rowIndex] - 1)
48+
.elementsFromPoint(x + (columnWidths[columnIndex] / 2) * (rtl ? -1 : 1), y + rowHeights[rowIndex] - 1)
4749
.reverse()
4850
.find(
4951
(element) =>
@@ -279,3 +281,18 @@ export function fireResizeEnd(dragOverTarget: Element): void {
279281
export function getRemoveButton(section: DashboardWidget | DashboardSection): HTMLElement {
280282
return section.shadowRoot!.querySelector('#remove-button') as HTMLElement;
281283
}
284+
285+
export function describeBidirectional(name: string, tests: () => void): void {
286+
describe(name, tests);
287+
describe(`${name} (RTL)`, () => {
288+
before(() => {
289+
document.dir = 'rtl';
290+
});
291+
292+
after(() => {
293+
document.dir = 'ltr'; // Reset to default after tests
294+
});
295+
296+
tests();
297+
});
298+
}

0 commit comments

Comments
 (0)