Skip to content

Commit

Permalink
feat(hovercard): DP-119841 hovercard fixes for Fast Connect (#597)
Browse files Browse the repository at this point in the history
  • Loading branch information
ninamarina authored Dec 18, 2024
1 parent 64c4c77 commit e5c78a3
Show file tree
Hide file tree
Showing 14 changed files with 136 additions and 251 deletions.
2 changes: 0 additions & 2 deletions apps/dialtone-documentation/docs/components/hovercard.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ showHtmlWarning />

### Many hovercards

Initially, there is a 300ms delay when numerous hovercards are present. However, when transitioning from one anchor to another, the delay is determined by the mouse movement time. This implies that the closer the anchors are, the faster the hovercard appears. To achieve this, the component uses a global timer. Move the mouse over the avatars to reveal the hovercards in the example.

<code-well-header>
<dt-stack direction="row" gap="500">
<example-hovercard v-for="data in exampleData" :label="data.label" :content="data.content" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ export const argTypesData = {
},

// Props
open: {
control: {
type: 'boolean',
},
},
fallbackPlacements: {
description: `If the popover does not fit in the direction described by "placement",
it will attempt to change its direction to the "fallbackPlacements".
Expand Down
5 changes: 2 additions & 3 deletions packages/dialtone-vue2/components/hovercard/hovercard.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,8 @@ describe('DtHovercard Tests', () => {
await anchor.trigger('mouseleave');
await vi.runAllTimers();

content = getHovercardContent();

expect(content).toBeNull();
const dialog = document.querySelector('[data-qa="dt-hovercard__dialog"] > div');
expect(dialog.style.display).toBe('none');
});
});

Expand Down
42 changes: 33 additions & 9 deletions packages/dialtone-vue2/components/hovercard/hovercard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
:footer-class="footerClass"
:append-to="appendTo"
:hovercard="true"
:timer="timer"
data-qa="dt-hovercard"
:open="open"
:enter-delay="enterDelay"
:leave-delay="leaveDelay"
@opened="(e) => ($emit('opened', e))"
>
<template #anchor="{ attrs }">
Expand All @@ -39,9 +41,8 @@

<script>
import { POPOVER_APPEND_TO_VALUES, POPOVER_PADDING_CLASSES, DtPopover } from '@/components/popover/index.js';
import { TOOLTIP_DIRECTIONS } from '@/components/tooltip/index.js';
import { TOOLTIP_DIRECTIONS, TOOLTIP_DELAY_MS } from '@/components/tooltip/index.js';
import { getUniqueString } from '@/common/utils';
import useTimer from './timer';

export default {
name: 'DtHovercard',
Expand All @@ -52,6 +53,17 @@ export default {

props: {
/**
* Controls whether the hovercard is shown. Leaving this null will have the hovercard trigger on hover by default.
* If you set this value, the default trigger behavior will be disabled, and you can control it as you need.
* Supports .sync modifier
* @values null, true, false
*/
open: {
type: Boolean,
default: null,
},

/**
* Fade transition when the content display is toggled.
* @type boolean
* @values true, false
Expand Down Expand Up @@ -165,6 +177,24 @@ export default {
(appendTo instanceof HTMLElement);
},
},

/**
* The enter delay in milliseconds before the hovercard is shown.
* @type number
*/
enterDelay: {
type: Number,
default: TOOLTIP_DELAY_MS,
},

/**
* The leave delay in milliseconds before the hovercard is hidden.
* @type number
*/
leaveDelay: {
type: Number,
default: TOOLTIP_DELAY_MS,
},
},

emits: [
Expand All @@ -176,11 +206,5 @@ export default {
*/
'opened',
],

data () {
return {
timer: useTimer(),
};
},
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
:header-class="$attrs.headerClass"
:footer-class="$attrs.footerClass"
:append-to="$attrs.appendTo"
:open="$attrs.open"
:enter-delay="$attrs.enterDelay"
:leave-delay="$attrs.leaveDelay"
@opened="$attrs.onOpened"
>
<template #anchor="slotProps">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
:header-class="$attrs.headerClass"
:footer-class="$attrs.footerClass"
:append-to="$attrs.appendTo"
:enter-delay="$attrs.enterDelay"
:leave-delay="$attrs.leaveDelay"
@opened="$attrs.onOpened"
>
<template #anchor="slotProps">
Expand Down
67 changes: 0 additions & 67 deletions packages/dialtone-vue2/components/hovercard/timer.js

This file was deleted.

72 changes: 24 additions & 48 deletions packages/dialtone-vue2/components/popover/popover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
@keydown.up.prevent="onArrowKeyPress"
@keydown.down.prevent="onArrowKeyPress"
@keydown.escape.capture="closePopover"
@mouseenter="onEnterAnchor"
@mouseleave="onLeaveAnchor"
@mouseenter="openHovercard"
@mouseleave="closeHovercard"
>
<!-- @slot Anchor element that activates the popover. Usually a button. -->
<slot
Expand Down Expand Up @@ -58,8 +58,8 @@
:tabindex="contentTabindex"
appear
v-on="popoverListeners"
@mouseenter="onEnterContent"
@mouseleave="onLeaveContent"
@mouseenter="openHovercard"
@mouseleave="closeHovercard"
>
<popover-header-footer
v-if="$slots.headerContent || showCloseButton"
Expand Down Expand Up @@ -515,17 +515,21 @@ export default {
},

/**
* The timer is used only when the hovercard prop is true.
* It defines the delays when opening several hovercards.
* It must have the keys: enter, leave and current.
* If null, the default delay of 300ms will be used.
* The enter delay in milliseconds before the hovercard is shown.
* @type number
*/
timer: {
type: [Object, null],
default: null,
validator: timer => {
return timer === null || (timer.enter && timer.leave && Object.keys(timer).includes('current'));
},
enterDelay: {
type: Number,
default: TOOLTIP_DELAY_MS,
},

/**
* The leave delay in milliseconds before the hovercard is hidden.
* @type number
*/
leaveDelay: {
type: Number,
default: TOOLTIP_DELAY_MS,
},
},

Expand Down Expand Up @@ -593,10 +597,6 @@ export default {
// there is no aria-label and the labelledby should point to the anchor.
return this.ariaLabelledby || (!this.ariaLabel && getUniqueString('DtPopover__anchor'));
},

currentHovercard () {
return this.timer?.current.value;
},
},

watch: {
Expand Down Expand Up @@ -663,16 +663,6 @@ export default {
this.tip.hide();
}
},

currentHovercard () {
if (this.hovercard && this.timer) {
if (this.currentHovercard === this.id) {
this.isOpen = true;
} else {
this.isOpen = false;
}
}
},
},

mounted () {
Expand Down Expand Up @@ -1029,45 +1019,31 @@ export default {
setInTimer () {
this.inTimer = setTimeout(() => {
this.isOpen = true;
}, TOOLTIP_DELAY_MS);
}, this.enterDelay);
},

setOutTimer () {
this.outTimer = setTimeout(() => {
this.isOpen = false;
}, TOOLTIP_DELAY_MS);
}, this.leaveDelay);
},

onEnterAnchor () {
openHovercard () {
if (!this.hovercard) return;
if (this.timer) this.timer.enter(this.id);
else {
if (this.open === null || this.open === undefined) {
clearTimeout(this.outTimer);
this.setInTimer();
}
},

onLeaveAnchor () {
closeHovercard () {
if (!this.hovercard) return;
if (this.timer) this.timer.leave();
else {
if (this.open === null || this.open === undefined) {
clearTimeout(this.inTimer);
this.setOutTimer();
}
},

onEnterContent () {
if (!this.hovercard) return;
if (this.timer) this.timer.enter(this.id);
else clearTimeout(this.outTimer);
},

onLeaveContent () {
if (!this.hovercard) return;
if (this.timer) this.timer.leave();
else this.setOutTimer();
},

// ============================================================================
// $ HOVERCARD
// ----------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ export const argTypesData = {
},

// Props
open: {
control: {
type: 'boolean',
},
},
fallbackPlacements: {
description: `If the popover does not fit in the direction described by "placement",
it will attempt to change its direction to the "fallbackPlacements".
Expand Down
Loading

0 comments on commit e5c78a3

Please sign in to comment.