From ab2c17985a9f3ba1daf494a77497f723ecafa9b0 Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Thu, 10 Oct 2024 14:27:09 +0300 Subject: [PATCH] fix: do not hide pdisk and vdisk popups if mouse on popup content --- src/components/PDiskPopup/PDiskPopup.tsx | 11 +++++++++++ src/components/VDisk/VDisk.tsx | 19 +++++++++++++------ src/components/VDiskPopup/VDiskPopup.tsx | 10 ++++++++++ src/containers/Storage/PDisk/PDisk.tsx | 19 +++++++++++++------ 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/components/PDiskPopup/PDiskPopup.tsx b/src/components/PDiskPopup/PDiskPopup.tsx index c73f4e5a9..65efe555b 100644 --- a/src/components/PDiskPopup/PDiskPopup.tsx +++ b/src/components/PDiskPopup/PDiskPopup.tsx @@ -70,6 +70,14 @@ export const PDiskPopup = ({data, ...props}: PDiskPopupProps) => { const nodeHost = valueIsDefined(data.NodeId) ? nodeHostsMap?.get(data.NodeId) : undefined; const info = React.useMemo(() => preparePDiskData(data, nodeHost), [data, nodeHost]); + const [isPopupOpen, setIsPopupOpen] = React.useState(props.open); + const onMouseLeave = React.useCallback(() => { + setIsPopupOpen(false); + }, []); + const onMouseEnter = React.useCallback(() => { + setIsPopupOpen(true); + }, []); + return ( { // bigger offset for easier switching to neighbour nodes // matches the default offset for popup with arrow out of a sense of beauty offset={[0, 12]} + onMouseLeave={onMouseLeave} + onMouseEnter={onMouseEnter} {...props} + open={isPopupOpen || props.open} > diff --git a/src/components/VDisk/VDisk.tsx b/src/components/VDisk/VDisk.tsx index cc59cffb8..c369719c6 100644 --- a/src/components/VDisk/VDisk.tsx +++ b/src/components/VDisk/VDisk.tsx @@ -1,5 +1,7 @@ import React from 'react'; +import {debounce} from 'lodash'; + import {cn} from '../../utils/cn'; import type {PreparedVDisk} from '../../utils/disks/types'; import {DiskStateProgressBar} from '../DiskStateProgressBar/DiskStateProgressBar'; @@ -12,6 +14,8 @@ import './VDisk.scss'; const b = cn('ydb-vdisk-component'); +const DEBOUNCE_TIMEOUT = 100; + export interface VDiskProps { data?: PreparedVDisk; compact?: boolean; @@ -35,15 +39,15 @@ export const VDisk = ({ const anchor = React.useRef(null); - const handleShowPopup = () => { + const debouncedHandleShowPopup = debounce(() => { setIsPopupVisible(true); onShowPopup?.(); - }; + }, DEBOUNCE_TIMEOUT); - const handleHidePopup = () => { + const debouncedHandleHidePopup = debounce(() => { setIsPopupVisible(false); onHidePopup?.(); - }; + }, DEBOUNCE_TIMEOUT); const vDiskPath = getVDiskLink(data); @@ -52,8 +56,11 @@ export const VDisk = ({
{ + debouncedHandleShowPopup.cancel(); + debouncedHandleHidePopup(); + }} > { const isFullData = isFullVDiskData(data); + const [isPopupOpen, setIsPopupOpen] = React.useState(props.open); + const onMouseLeave = React.useCallback(() => { + setIsPopupOpen(false); + }, []); + const onMouseEnter = React.useCallback(() => { + setIsPopupOpen(true); + }, []); const vdiskInfo = React.useMemo( () => (isFullData ? prepareVDiskData(data) : prepareUnavailableVDiskData(data)), @@ -181,7 +188,10 @@ export const VDiskPopup = ({data, ...props}: VDiskPopupProps) => { // bigger offset for easier switching to neighbour nodes // matches the default offset for popup with arrow out of a sense of beauty offset={[0, 12]} + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} {...props} + open={isPopupOpen || props.open} > {data.DonorMode && } diff --git a/src/containers/Storage/PDisk/PDisk.tsx b/src/containers/Storage/PDisk/PDisk.tsx index f0ff784ae..a48162925 100644 --- a/src/containers/Storage/PDisk/PDisk.tsx +++ b/src/containers/Storage/PDisk/PDisk.tsx @@ -1,5 +1,7 @@ import React from 'react'; +import {debounce} from 'lodash'; + import {DiskStateProgressBar} from '../../../components/DiskStateProgressBar/DiskStateProgressBar'; import {InternalLink} from '../../../components/InternalLink'; import {PDiskPopup} from '../../../components/PDiskPopup/PDiskPopup'; @@ -16,6 +18,8 @@ import './PDisk.scss'; const b = cn('pdisk-storage'); +const DEBOUNCE_TIMEOUT = 100; + interface PDiskProps { data?: PreparedPDisk; vDisks?: PreparedVDisk[]; @@ -44,15 +48,15 @@ export const PDisk = ({ const {NodeId, PDiskId} = data; const pDiskIdsDefined = valueIsDefined(NodeId) && valueIsDefined(PDiskId); - const handleShowPopup = () => { + const debouncedHandleShowPopup = debounce(() => { setIsPopupVisible(true); onShowPopup?.(); - }; + }, DEBOUNCE_TIMEOUT); - const handleHidePopup = () => { + const debouncedHandleHidePopup = debounce(() => { setIsPopupVisible(false); onHidePopup?.(); - }; + }, DEBOUNCE_TIMEOUT); const renderVDisks = () => { if (!vDisks?.length) { @@ -101,8 +105,11 @@ export const PDisk = ({ { + debouncedHandleShowPopup.cancel(); + debouncedHandleHidePopup(); + }} >