From ab2c17985a9f3ba1daf494a77497f723ecafa9b0 Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Thu, 10 Oct 2024 14:27:09 +0300 Subject: [PATCH 1/3] 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(); + }} > Date: Thu, 10 Oct 2024 15:21:44 +0300 Subject: [PATCH 2/3] feat: add cell table delay --- src/components/CellWithPopover/CellWithPopover.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/CellWithPopover/CellWithPopover.tsx b/src/components/CellWithPopover/CellWithPopover.tsx index 272df0dd7..14529d8b4 100644 --- a/src/components/CellWithPopover/CellWithPopover.tsx +++ b/src/components/CellWithPopover/CellWithPopover.tsx @@ -11,6 +11,8 @@ interface CellWithPopoverProps extends PopoverProps { wrapperClassName?: string; } +const DELAY_TIMEOUT = 100; + export function CellWithPopover({ children, className, @@ -19,7 +21,12 @@ export function CellWithPopover({ }: CellWithPopoverProps) { return (
- + {children}
From 8a28fa9f4da728be4f5f0c6a1dd40c9505aae9c9 Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Thu, 10 Oct 2024 18:14:29 +0300 Subject: [PATCH 3/3] fix: review fixes --- src/components/PDiskPopup/PDiskPopup.tsx | 8 ++++---- src/components/VDiskPopup/VDiskPopup.tsx | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/PDiskPopup/PDiskPopup.tsx b/src/components/PDiskPopup/PDiskPopup.tsx index 65efe555b..0bca72c7f 100644 --- a/src/components/PDiskPopup/PDiskPopup.tsx +++ b/src/components/PDiskPopup/PDiskPopup.tsx @@ -70,12 +70,12 @@ 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 [isPopupContentHovered, setIsPopupContentHovered] = React.useState(false); const onMouseLeave = React.useCallback(() => { - setIsPopupOpen(false); + setIsPopupContentHovered(false); }, []); const onMouseEnter = React.useCallback(() => { - setIsPopupOpen(true); + setIsPopupContentHovered(true); }, []); return ( @@ -89,7 +89,7 @@ export const PDiskPopup = ({data, ...props}: PDiskPopupProps) => { onMouseLeave={onMouseLeave} onMouseEnter={onMouseEnter} {...props} - open={isPopupOpen || props.open} + open={isPopupContentHovered || props.open} > diff --git a/src/components/VDiskPopup/VDiskPopup.tsx b/src/components/VDiskPopup/VDiskPopup.tsx index e16dd3a7a..45b63c8ee 100644 --- a/src/components/VDiskPopup/VDiskPopup.tsx +++ b/src/components/VDiskPopup/VDiskPopup.tsx @@ -136,12 +136,13 @@ interface VDiskPopupProps extends PopupProps { export const VDiskPopup = ({data, ...props}: VDiskPopupProps) => { const isFullData = isFullVDiskData(data); - const [isPopupOpen, setIsPopupOpen] = React.useState(props.open); + + const [isPopupContentHovered, setIsPopupContentHovered] = React.useState(false); const onMouseLeave = React.useCallback(() => { - setIsPopupOpen(false); + setIsPopupContentHovered(false); }, []); const onMouseEnter = React.useCallback(() => { - setIsPopupOpen(true); + setIsPopupContentHovered(true); }, []); const vdiskInfo = React.useMemo( @@ -191,7 +192,7 @@ export const VDiskPopup = ({data, ...props}: VDiskPopupProps) => { onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} {...props} - open={isPopupOpen || props.open} + open={isPopupContentHovered || props.open} > {data.DonorMode && }