Skip to content

Commit 4bb603c

Browse files
author
Welly Shen
committed
Hovercards: Add hideOnTargetClick option & Remove hovercards after calling the detach()
1 parent d665839 commit 4bb603c

File tree

6 files changed

+52
-6
lines changed

6 files changed

+52
-6
lines changed

web/packages/hovercards/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ Determines whether the hovercard's placement should automatically flip when ther
187187

188188
Determines whether the hovercard's placement should automatically shift when there is not enough display space.
189189

190+
##### `hideOnTargetClick: boolean = false`
191+
192+
Hides the hovercard when its trigger element is clicked.
193+
190194
##### `offset: number = 10`
191195

192196
The offset of the hovercard relative to the target element, in pixels.

web/packages/hovercards/playground/core.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ addEventListener( 'DOMContentLoaded', () => {
99
placement: 'top',
1010
// To test the empty about me case
1111
myHash: '99c3338797c95c418d9996bd39931506',
12+
hideOnTargetClick: true,
1213
onCanShowHovercard: ( hash ) => {
1314
if ( hash === 'a2bb8d897bb538896708195dd9eb162f585654611c50a3a1c9a16a7b64f33270' ) {
1415
return false;
@@ -179,6 +180,11 @@ addEventListener( 'DOMContentLoaded', () => {
179180
)
180181
);
181182

183+
// To test detach
184+
document.getElementById( 'detach' )?.addEventListener( 'click', () => {
185+
hovercards.detach();
186+
} );
187+
182188
// To test hovercard skeleton
183189
document.getElementById( 'hovercard-skeleton' )?.appendChild( Hovercards.createHovercardSkeleton() );
184190

web/packages/hovercards/playground/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
height="60"
7777
/>
7878
<div id="attr" data-gravatar-hash="c3bb8d897bb538896708195dd9eb162f585654611c50a3a1c9a16a7b64f33270?s=60&d=retro&r=g">@WellyTest</div>
79+
<button id="detach">Detach</button>
7980
</div>
8081
<div id="react-app"></div>
8182
<div id="inline">

web/packages/hovercards/playground/react.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable import/no-unresolved */
22

33
import { createRoot } from 'react-dom/client';
4-
import React, { useRef, useEffect, useState } from 'react';
4+
import { useRef, useEffect, useState } from 'react';
55

66
import type { HovercardsProps } from '../dist/index.react.d';
77
import { useHovercards, Hovercards } from '../dist/index.react';
@@ -11,13 +11,15 @@ const props: HovercardsProps = {
1111
// attach: document.body,
1212
// placement: 'top',
1313
// ignoreSelector: '#grav-img-1',
14+
hideOnTargetClick: true,
1415
i18n: {
1516
'View profile →': 'Voir le profil →',
1617
},
1718
};
1819

1920
function App() {
2021
const { attach } = useHovercards( {
22+
hideOnTargetClick: true,
2123
// eslint-disable-next-line no-console
2224
onFetchProfileSuccess: ( hash ) => console.log( hash ),
2325
onCanShowHovercard: ( hash ) => {

web/packages/hovercards/src/core.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export type Options = Partial< {
112112
offset: number;
113113
autoFlip: boolean;
114114
autoShift: boolean;
115+
hideOnTargetClick: boolean;
115116
delayToShow: number;
116117
delayToHide: number;
117118
additionalClass: string;
@@ -133,6 +134,7 @@ interface HovercardRef {
133134
ref: HTMLElement;
134135
onEnter: ( e: MouseEvent ) => void;
135136
onLeave: ( e: MouseEvent ) => void;
137+
onClick: ( e: MouseEvent ) => void;
136138
}
137139

138140
const BASE_API_URL = 'https://api.gravatar.com/v3/profiles';
@@ -145,6 +147,7 @@ export default class Hovercards {
145147
_offset: number;
146148
_autoFlip: boolean;
147149
_autoShift: boolean;
150+
_hideOnTargetClick: boolean;
148151
_delayToShow: number;
149152
_delayToHide: number;
150153
_additionalClass: string;
@@ -166,9 +169,10 @@ export default class Hovercards {
166169

167170
constructor( {
168171
placement = 'right-start',
172+
offset = 10,
169173
autoFlip = true,
170174
autoShift = true,
171-
offset = 10,
175+
hideOnTargetClick = false,
172176
delayToShow = 500,
173177
delayToHide = 300,
174178
additionalClass = '',
@@ -183,9 +187,10 @@ export default class Hovercards {
183187
i18n = {},
184188
}: Options = {} ) {
185189
this._placement = placement;
190+
this._offset = offset;
186191
this._autoFlip = autoFlip;
187192
this._autoShift = autoShift;
188-
this._offset = offset;
193+
this._hideOnTargetClick = hideOnTargetClick;
189194
this._delayToShow = delayToShow;
190195
this._delayToHide = delayToHide;
191196
this._additionalClass = additionalClass;
@@ -291,6 +296,7 @@ export default class Hovercards {
291296
...hovercardRef,
292297
onEnter: ( e: MouseEvent ) => this._handleMouseEnter( e, hovercardRef ),
293298
onLeave: ( e: MouseEvent ) => this._handleMouseLeave( e, hovercardRef ),
299+
onClick: () => this._handleMouseClick( hovercardRef ),
294300
} ) );
295301

296302
return this._hovercardRefs;
@@ -881,19 +887,20 @@ export default class Hovercards {
881887
/**
882888
* Waits for a specified delay and hides the hovercard.
883889
*
884-
* @param {string} id - The ID associated with the hovercard.
890+
* @param {string} id - The ID associated with the hovercard.
891+
* @param {number} [delay] - The delay in milliseconds before hiding the hovercard.
885892
* @return {void}
886893
* @private
887894
*/
888-
_hideHovercard( id: string ): void {
895+
_hideHovercard( id: string, delay = this._delayToHide ): void {
889896
const timeoutId = setTimeout( () => {
890897
const hovercard = dc.getElementById( id );
891898

892899
if ( hovercard ) {
893900
hovercard.remove();
894901
this._onHovercardHidden( id, hovercard as HTMLDivElement );
895902
}
896-
}, this._delayToHide );
903+
}, delay );
897904

898905
this._hideHovercardTimeoutIds.set( id, timeoutId );
899906
}
@@ -938,6 +945,23 @@ export default class Hovercards {
938945
this._hideHovercard( id );
939946
}
940947

948+
/**
949+
* Handles the click event for hovercard refs.
950+
*
951+
* @param {HovercardRef} hovercardRef - The hovercard ref object.
952+
* @param {string} hovercardRef.id - The ID associated with the hovercard.
953+
* @return {void}
954+
* @private
955+
*/
956+
_handleMouseClick( { id }: HovercardRef ): void {
957+
if ( 'ontouchstart' in dc || ! this._hideOnTargetClick ) {
958+
return;
959+
}
960+
961+
clearInterval( this._showHovercardTimeoutIds.get( id ) );
962+
this._hideHovercard( id, 0 );
963+
}
964+
941965
/**
942966
* Attaches event listeners on or within the target element.
943967
*
@@ -957,6 +981,7 @@ export default class Hovercards {
957981
this._queryHovercardRefs( target, dataAttributeName, ignoreSelector ).forEach( ( hovercardRef ) => {
958982
hovercardRef.ref.addEventListener( 'mouseenter', hovercardRef.onEnter );
959983
hovercardRef.ref.addEventListener( 'mouseleave', hovercardRef.onLeave );
984+
hovercardRef.ref.addEventListener( 'click', hovercardRef.onClick );
960985
} );
961986
};
962987

@@ -973,6 +998,11 @@ export default class Hovercards {
973998
this._hovercardRefs.forEach( ( hovercardRef ) => {
974999
hovercardRef.ref.removeEventListener( 'mouseenter', hovercardRef.onEnter );
9751000
hovercardRef.ref.removeEventListener( 'mouseleave', hovercardRef.onLeave );
1001+
hovercardRef.ref.removeEventListener( 'click', hovercardRef.onClick );
1002+
1003+
// Clear the hovercard show timeout and remove the hovercard element.
1004+
clearInterval( this._showHovercardTimeoutIds.get( hovercardRef.id ) );
1005+
dc.getElementById( hovercardRef.id )?.remove();
9761006
} );
9771007

9781008
this._hovercardRefs = [];

web/packages/hovercards/src/use-hovercards.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export default function useHovercards( {
1717
offset,
1818
autoFlip,
1919
autoShift,
20+
hideOnTargetClick,
2021
delayToShow,
2122
delayToHide,
2223
additionalClass,
@@ -47,6 +48,7 @@ export default function useHovercards( {
4748
offset,
4849
autoFlip,
4950
autoShift,
51+
hideOnTargetClick,
5052
delayToShow,
5153
delayToHide,
5254
additionalClass,
@@ -65,6 +67,7 @@ export default function useHovercards( {
6567
offset,
6668
autoFlip,
6769
autoShift,
70+
hideOnTargetClick,
6871
delayToShow,
6972
delayToHide,
7073
additionalClass,

0 commit comments

Comments
 (0)