Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: do not hide pdisk and vdisk popups if mouse on popup content #1435

Merged
merged 4 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading