Skip to content

Commit 05eef7f

Browse files
committed
Fix InteractionWrapper for touch devices.
1 parent 9f35509 commit 05eef7f

15 files changed

Lines changed: 152 additions & 132 deletions

components/Atoms/InteractionWrapper.spec.ts

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@ describe('InteractionWrapper', () => {
5050
let wrapper: VueWrapper;
5151

5252
beforeEach(() => {
53+
isAnyOpenMock.value = false;
5354
containsClassMock.mockReset();
5455
containsClassMock.mockReturnValueOnce(false);
56+
5557
wrapper = factory();
5658
});
5759

@@ -221,30 +223,39 @@ describe('InteractionWrapper', () => {
221223
});
222224
});
223225

224-
describe('when the isAnyOpen value is true', () => {
225-
beforeEach(() => {
226-
isAnyOpenMock.value = true;
226+
describe('when the mouseenter event is triggered', () => {
227+
beforeEach(async () => {
228+
onDragStartMock = vi.fn();
229+
wrapper = factory();
230+
await wrapper.trigger('mouseenter');
227231
});
228232

229233
it('matches the snapshot', () => {
230234
expect(wrapper.html()).toMatchSnapshot();
231235
});
232236

233-
it('sets the draggable attribute to false', () => {
234-
expect(wrapper.attributes('draggable')).toBe('false');
237+
it('sets the draggable attribute to true', () => {
238+
expect(wrapper.attributes('draggable')).toBe('true');
235239
});
236-
});
237240

238-
describe('when the isAnyOpen value is false', () => {
239-
beforeEach(() => {
240-
isAnyOpenMock.value = false;
241+
describe('when the isAnyOpen value is true', () => {
242+
beforeEach(() => {
243+
isAnyOpenMock.value = true;
244+
});
245+
246+
it('matches the snapshot', () => {
247+
expect(wrapper.html()).toMatchSnapshot();
248+
});
249+
250+
it('sets the draggable attribute to false', () => {
251+
expect(wrapper.attributes('draggable')).toBe('false');
252+
});
241253
});
242254

243255
describe('when the draggable prop is set to false', () => {
244-
beforeEach(() => {
245-
wrapper = factory({
246-
draggable: false,
247-
});
256+
beforeEach(async () => {
257+
wrapper = factory({ draggable: false });
258+
await wrapper.trigger('mouseenter');
248259
});
249260

250261
it('matches the snapshot', () => {
@@ -257,8 +268,10 @@ describe('InteractionWrapper', () => {
257268
});
258269

259270
describe('when the onDragStart event is not attached', () => {
260-
beforeEach(() => {
271+
beforeEach(async () => {
261272
onDragStartMock = undefined;
273+
wrapper = factory();
274+
await wrapper.trigger('mouseenter');
262275
});
263276

264277
it('matches the snapshot', () => {
@@ -270,18 +283,17 @@ describe('InteractionWrapper', () => {
270283
});
271284
});
272285

273-
describe('when the isAnyOpen value and the draggable prop are set to true and the onDragStart event is attached', () => {
274-
beforeEach(() => {
275-
onDragStartMock = vi.fn();
276-
wrapper = factory();
286+
describe('when the mouseleave event is triggered', () => {
287+
beforeEach(async () => {
288+
await wrapper.trigger('mouseleave');
277289
});
278290

279291
it('matches the snapshot', () => {
280292
expect(wrapper.html()).toMatchSnapshot();
281293
});
282294

283-
it('sets the draggable attribute to true', () => {
284-
expect(wrapper.attributes('draggable')).toBe('true');
295+
it('sets the draggable attribute to false', () => {
296+
expect(wrapper.attributes('draggable')).toBe('false');
285297
});
286298
});
287299
});
@@ -293,39 +305,37 @@ describe('InteractionWrapper', () => {
293305
await wrapper.trigger('touchstart');
294306
});
295307

296-
it('sets the draggable attribute to false', () => {
297-
expect(wrapper.attributes('draggable')).toBe('false');
298-
});
299-
300-
it('matches the snapshot', () => {
301-
expect(wrapper.html()).toMatchSnapshot();
302-
});
303-
304-
describe('when the touchend event is triggered', () => {
308+
describe('when the mouseenter event is triggered', () => {
305309
beforeEach(async () => {
306-
await wrapper.trigger('touchend');
307-
});
308-
309-
it('sets the draggable attribute to true', () => {
310-
expect(wrapper.attributes('draggable')).toBe('true');
310+
await wrapper.trigger('mouseenter');
311311
});
312312

313313
it('matches the snapshot', () => {
314314
expect(wrapper.html()).toMatchSnapshot();
315315
});
316+
317+
it('sets the draggable attribute to false', () => {
318+
expect(wrapper.attributes('draggable')).toBe('false');
319+
});
316320
});
317321

318-
describe('when the touchcancel event is triggered', () => {
322+
describe('when the mouseleave event is triggered', () => {
319323
beforeEach(async () => {
320-
await wrapper.trigger('touchcancel');
324+
await wrapper.trigger('mouseleave');
321325
});
322326

323-
it('sets the draggable attribute to true', () => {
324-
expect(wrapper.attributes('draggable')).toBe('true');
325-
});
327+
describe('when the mouseenter event is triggered', () => {
328+
beforeEach(async () => {
329+
await wrapper.trigger('mouseenter');
330+
});
326331

327-
it('matches the snapshot', () => {
328-
expect(wrapper.html()).toMatchSnapshot();
332+
it('matches the snapshot', () => {
333+
expect(wrapper.html()).toMatchSnapshot();
334+
});
335+
336+
it('sets the draggable attribute to true', () => {
337+
expect(wrapper.attributes('draggable')).toBe('true');
338+
});
329339
});
330340
});
331341
});

components/Atoms/InteractionWrapper.vue

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,8 @@ const instance = getCurrentInstance();
2020
2121
const { isAnyOpen } = useDropdownMenuState();
2222
23-
const isTouching = ref(false);
24-
25-
function cancelTouch() {
26-
isTouching.value = false;
27-
}
23+
const isMouseOver = ref(false);
24+
const isTouched = ref(false);
2825
2926
// Only allow the event if the following is true.
3027
function isInteractiveTarget(event: Event) {
@@ -43,31 +40,44 @@ function onClick(event: MouseEvent) {
4340
}
4441
4542
function onContextMenu(event: MouseEvent) {
43+
event.preventDefault();
44+
event.stopPropagation();
45+
4646
if (isInteractiveTarget(event)) {
4747
return;
4848
}
4949
50-
event.preventDefault();
51-
event.stopPropagation();
52-
5350
emit('contextMenu', event);
5451
}
5552
5653
function onDragStart(event: DragEvent) {
5754
if (isInteractiveTarget(event)) {
55+
event.preventDefault();
56+
event.stopPropagation();
5857
return;
5958
}
6059
6160
emit('dragStart', event);
6261
}
6362
63+
function onMouseEnter() {
64+
if (!isTouched.value) {
65+
isMouseOver.value = true;
66+
}
67+
}
68+
69+
function onMouseLeave() {
70+
isMouseOver.value = false;
71+
isTouched.value = false;
72+
}
73+
6474
function onTouchStart() {
65-
isTouching.value = true;
75+
isTouched.value = true;
6676
}
6777
6878
const isDraggable = computed(
6979
() =>
70-
!isTouching.value &&
80+
isMouseOver.value &&
7181
!isAnyOpen.value &&
7282
props.draggable &&
7383
!!instance?.vnode.props?.onDragStart,
@@ -82,8 +92,8 @@ const isDraggable = computed(
8292
@click="onClick"
8393
@contextmenu="onContextMenu"
8494
@dragstart="onDragStart"
85-
@touchcancel="cancelTouch"
86-
@touchend="cancelTouch"
95+
@mouseenter="onMouseEnter"
96+
@mouseleave="onMouseLeave"
8797
@touchstart="onTouchStart"
8898
>
8999
<slot />

components/Atoms/__snapshots__/InteractionWrapper.spec.ts.snap

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
exports[`InteractionWrapper > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="false">Default slot content.</div>"`;
44

5-
exports[`InteractionWrapper > when the isAnyOpen value is false > when the draggable prop is set to false > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="false">Default slot content.</div>"`;
5+
exports[`InteractionWrapper > when the mouseenter event is triggered > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="true">Default slot content.</div>"`;
66

7-
exports[`InteractionWrapper > when the isAnyOpen value is false > when the isAnyOpen value and the draggable prop are set to true and the onDragStart event is attached > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="true">Default slot content.</div>"`;
7+
exports[`InteractionWrapper > when the mouseenter event is triggered > when the draggable prop is set to false > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="false">Default slot content.</div>"`;
88

9-
exports[`InteractionWrapper > when the isAnyOpen value is false > when the onDragStart event is not attached > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="false">Default slot content.</div>"`;
9+
exports[`InteractionWrapper > when the mouseenter event is triggered > when the isAnyOpen value is true > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="false">Default slot content.</div>"`;
1010

11-
exports[`InteractionWrapper > when the isAnyOpen value is true > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="false">Default slot content.</div>"`;
11+
exports[`InteractionWrapper > when the mouseenter event is triggered > when the mouseleave event is triggered > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="false">Default slot content.</div>"`;
1212

13-
exports[`InteractionWrapper > when the touchstart event is triggered > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="false">Default slot content.</div>"`;
13+
exports[`InteractionWrapper > when the mouseenter event is triggered > when the onDragStart event is not attached > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="false">Default slot content.</div>"`;
1414

15-
exports[`InteractionWrapper > when the touchstart event is triggered > when the touchcancel event is triggered > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="true">Default slot content.</div>"`;
15+
exports[`InteractionWrapper > when the touchstart event is triggered > when the mouseenter event is triggered > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="false">Default slot content.</div>"`;
1616

17-
exports[`InteractionWrapper > when the touchstart event is triggered > when the touchend event is triggered > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="true">Default slot content.</div>"`;
17+
exports[`InteractionWrapper > when the touchstart event is triggered > when the mouseleave event is triggered > when the mouseenter event is triggered > matches the snapshot 1`] = `"<div class="interactionWrapper" draggable="true">Default slot content.</div>"`;

components/Organisms/TrackLists/__snapshots__/AlbumTracksList.spec.ts.snap

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ exports[`AlbumTracksList > when the tracks prop is not an empty array > matches
1616
<div class="trackCell trackOptions"></div>
1717
</div>
1818
<div class="lazyLoadContent trackRow">
19-
<div class="interactionWrapper" draggable="true">
19+
<div class="interactionWrapper" draggable="false">
2020
<div class="trackCell">
2121
<div>
2222
<div class="overlapWrapper trackPlayPause">
@@ -79,7 +79,7 @@ exports[`AlbumTracksList > when the tracks prop is not an empty array > matches
7979
</div>
8080
</div>
8181
<div class="lazyLoadContent trackRow">
82-
<div class="interactionWrapper" draggable="true">
82+
<div class="interactionWrapper" draggable="false">
8383
<div class="trackCell">
8484
<div>
8585
<div class="overlapWrapper trackPlayPause">
@@ -142,7 +142,7 @@ exports[`AlbumTracksList > when the tracks prop is not an empty array > matches
142142
</div>
143143
</div>
144144
<div class="lazyLoadContent trackRow">
145-
<div class="interactionWrapper" draggable="true">
145+
<div class="interactionWrapper" draggable="false">
146146
<div class="trackCell">
147147
<div>
148148
<div class="overlapWrapper trackPlayPause">
@@ -205,7 +205,7 @@ exports[`AlbumTracksList > when the tracks prop is not an empty array > matches
205205
</div>
206206
</div>
207207
<div class="lazyLoadContent trackRow">
208-
<div class="interactionWrapper" draggable="true">
208+
<div class="interactionWrapper" draggable="false">
209209
<div class="trackCell">
210210
<div>
211211
<div class="overlapWrapper trackPlayPause">
@@ -268,7 +268,7 @@ exports[`AlbumTracksList > when the tracks prop is not an empty array > matches
268268
</div>
269269
</div>
270270
<div class="lazyLoadContent trackRow">
271-
<div class="interactionWrapper" draggable="true">
271+
<div class="interactionWrapper" draggable="false">
272272
<div class="trackCell">
273273
<div>
274274
<div class="overlapWrapper trackPlayPause">

components/Organisms/TrackLists/__snapshots__/AlbumTracksListItem.spec.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
exports[`AlbumTracksListItem > matches the snapshot 1`] = `
44
"<div class="lazyLoadContent trackRow">
5-
<div class="interactionWrapper" draggable="true">
5+
<div class="interactionWrapper" draggable="false">
66
<div class="trackCell">
77
<div>
88
<track-play-pause-stub image="image-0" trackid="track-0" tracknumber="1" hideimage="true" large="false"></track-play-pause-stub>
@@ -77,7 +77,7 @@ exports[`AlbumTracksListItem > matches the snapshot 1`] = `
7777

7878
exports[`AlbumTracksListItem > when track.artists is an empty array > matches the snapshot 1`] = `
7979
"<div class="lazyLoadContent trackRow">
80-
<div class="interactionWrapper" draggable="true">
80+
<div class="interactionWrapper" draggable="false">
8181
<div class="trackCell">
8282
<div>
8383
<track-play-pause-stub image="image-0" trackid="track-0" tracknumber="1" hideimage="true" large="false"></track-play-pause-stub>

components/Organisms/TrackLists/__snapshots__/MixedTracksList.spec.ts.snap

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ exports[`MixedTracksList > when the tracks prop is not an empty array > when the
11351135
<div class="trackCell trackOptions"></div>
11361136
</div>
11371137
<div class="lazyLoadContent trackRow">
1138-
<div class="interactionWrapper" draggable="true">
1138+
<div class="interactionWrapper" draggable="false">
11391139
<div class="trackCell">
11401140
<div>
11411141
<div class="overlapWrapper trackPlayPause withImage">
@@ -1208,7 +1208,7 @@ exports[`MixedTracksList > when the tracks prop is not an empty array > when the
12081208
</div>
12091209
</div>
12101210
<div class="lazyLoadContent trackRow">
1211-
<div class="interactionWrapper" draggable="true">
1211+
<div class="interactionWrapper" draggable="false">
12121212
<div class="trackCell">
12131213
<div>
12141214
<div class="overlapWrapper trackPlayPause withImage">
@@ -1281,7 +1281,7 @@ exports[`MixedTracksList > when the tracks prop is not an empty array > when the
12811281
</div>
12821282
</div>
12831283
<div class="lazyLoadContent trackRow">
1284-
<div class="interactionWrapper" draggable="true">
1284+
<div class="interactionWrapper" draggable="false">
12851285
<div class="trackCell">
12861286
<div>
12871287
<div class="overlapWrapper trackPlayPause withImage">
@@ -1354,7 +1354,7 @@ exports[`MixedTracksList > when the tracks prop is not an empty array > when the
13541354
</div>
13551355
</div>
13561356
<div class="lazyLoadContent trackRow">
1357-
<div class="interactionWrapper" draggable="true">
1357+
<div class="interactionWrapper" draggable="false">
13581358
<div class="trackCell">
13591359
<div>
13601360
<div class="overlapWrapper trackPlayPause withImage">
@@ -1427,7 +1427,7 @@ exports[`MixedTracksList > when the tracks prop is not an empty array > when the
14271427
</div>
14281428
</div>
14291429
<div class="lazyLoadContent trackRow">
1430-
<div class="interactionWrapper" draggable="true">
1430+
<div class="interactionWrapper" draggable="false">
14311431
<div class="trackCell">
14321432
<div>
14331433
<div class="overlapWrapper trackPlayPause withImage">

0 commit comments

Comments
 (0)