Skip to content

Commit

Permalink
fix: do not hide pdisk and vdisk popups if mouse on popup content (#1435
Browse files Browse the repository at this point in the history
)
  • Loading branch information
astandrik authored Oct 11, 2024
1 parent 78cd713 commit ac70e8d
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 13 deletions.
9 changes: 8 additions & 1 deletion src/components/CellWithPopover/CellWithPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ interface CellWithPopoverProps extends PopoverProps {
wrapperClassName?: string;
}

const DELAY_TIMEOUT = 100;

export function CellWithPopover({
children,
className,
Expand All @@ -19,7 +21,12 @@ export function CellWithPopover({
}: CellWithPopoverProps) {
return (
<div className={b(null, wrapperClassName)}>
<Popover className={b('popover', className)} {...props}>
<Popover
delayClosing={DELAY_TIMEOUT}
delayOpening={DELAY_TIMEOUT}
className={b('popover', className)}
{...props}
>
{children}
</Popover>
</div>
Expand Down
11 changes: 11 additions & 0 deletions src/components/PDiskPopup/PDiskPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 [isPopupContentHovered, setIsPopupContentHovered] = React.useState(false);
const onMouseLeave = React.useCallback(() => {
setIsPopupContentHovered(false);
}, []);
const onMouseEnter = React.useCallback(() => {
setIsPopupContentHovered(true);
}, []);

return (
<Popup
contentClassName={b()}
Expand All @@ -78,7 +86,10 @@ export const PDiskPopup = ({data, ...props}: PDiskPopupProps) => {
// 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={isPopupContentHovered || props.open}
>
<InfoViewer title="PDisk" info={info} size="s" />
</Popup>
Expand Down
19 changes: 13 additions & 6 deletions src/components/VDisk/VDisk.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -12,6 +14,8 @@ import './VDisk.scss';

const b = cn('ydb-vdisk-component');

const DEBOUNCE_TIMEOUT = 100;

export interface VDiskProps {
data?: PreparedVDisk;
compact?: boolean;
Expand All @@ -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);

Expand All @@ -52,8 +56,11 @@ export const VDisk = ({
<div
className={b()}
ref={anchor}
onMouseEnter={handleShowPopup}
onMouseLeave={handleHidePopup}
onMouseEnter={debouncedHandleShowPopup}
onMouseLeave={() => {
debouncedHandleShowPopup.cancel();
debouncedHandleHidePopup();
}}
>
<InternalLink to={vDiskPath} className={b('content')}>
<DiskStateProgressBar
Expand Down
11 changes: 11 additions & 0 deletions src/components/VDiskPopup/VDiskPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ interface VDiskPopupProps extends PopupProps {
export const VDiskPopup = ({data, ...props}: VDiskPopupProps) => {
const isFullData = isFullVDiskData(data);

const [isPopupContentHovered, setIsPopupContentHovered] = React.useState(false);
const onMouseLeave = React.useCallback(() => {
setIsPopupContentHovered(false);
}, []);
const onMouseEnter = React.useCallback(() => {
setIsPopupContentHovered(true);
}, []);

const vdiskInfo = React.useMemo(
() => (isFullData ? prepareVDiskData(data) : prepareUnavailableVDiskData(data)),
[data, isFullData],
Expand Down Expand Up @@ -181,7 +189,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={isPopupContentHovered || props.open}
>
{data.DonorMode && <Label className={b('donor-label')}>Donor</Label>}
<InfoViewer title="VDisk" info={vdiskInfo} size="s" />
Expand Down
19 changes: 13 additions & 6 deletions src/containers/Storage/PDisk/PDisk.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -16,6 +18,8 @@ import './PDisk.scss';

const b = cn('pdisk-storage');

const DEBOUNCE_TIMEOUT = 100;

interface PDiskProps {
data?: PreparedPDisk;
vDisks?: PreparedVDisk[];
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -101,8 +105,11 @@ export const PDisk = ({
<InternalLink
to={pDiskPath}
className={b('content')}
onMouseEnter={handleShowPopup}
onMouseLeave={handleHidePopup}
onMouseEnter={debouncedHandleShowPopup}
onMouseLeave={() => {
debouncedHandleShowPopup.cancel();
debouncedHandleHidePopup();
}}
>
<DiskStateProgressBar
diskAllocatedPercent={data.AllocatedPercent}
Expand Down

0 comments on commit ac70e8d

Please sign in to comment.