better bubble

This commit is contained in:
Vadim Ogievetsky 2024-11-25 14:32:25 -08:00
parent 93cd91bedf
commit 3a492d8b78
4 changed files with 32 additions and 11 deletions

View File

@ -43,6 +43,7 @@ export * from './menu-checkbox/menu-checkbox';
export * from './more-button/more-button'; export * from './more-button/more-button';
export * from './plural-pair-if-needed/plural-pair-if-needed'; export * from './plural-pair-if-needed/plural-pair-if-needed';
export * from './popover-text/popover-text'; export * from './popover-text/popover-text';
export * from './portal-bubble/portal-bubble';
export * from './query-error-pane/query-error-pane'; export * from './query-error-pane/query-error-pane';
export * from './record-table-pane/record-table-pane'; export * from './record-table-pane/record-table-pane';
export * from './refresh-button/refresh-button'; export * from './refresh-button/refresh-button';

View File

@ -18,7 +18,7 @@
@import '../../variables'; @import '../../variables';
$shpitz-size: 10px; $shpitz-size: 9px;
.portal-bubble { .portal-bubble {
position: absolute; position: absolute;
@ -44,11 +44,18 @@ $shpitz-size: 10px;
content: ''; content: '';
position: absolute; position: absolute;
transform: translate(-50%, 0); transform: translate(-50%, 0);
bottom: -$shpitz-size;
border-top: $shpitz-size solid $dark-gray1;
border-right: $shpitz-size solid transparent; border-right: $shpitz-size solid transparent;
border-left: $shpitz-size solid transparent; border-left: $shpitz-size solid transparent;
border-bottom: none; }
&.up > .shpitz {
bottom: -$shpitz-size;
border-top: $shpitz-size solid $dark-gray1;
}
&.down > .shpitz {
top: -$shpitz-size;
border-bottom: $shpitz-size solid $dark-gray1;
} }
& > .bubble-title-bar { & > .bubble-title-bar {

View File

@ -27,9 +27,18 @@ import { clamp } from '../../utils';
import './portal-bubble.scss'; import './portal-bubble.scss';
interface PortalBubbleProps { const SHPITZ_SIZE = 10;
export interface PortalBubbleOpenOn {
x: number;
y: number;
title?: string;
text: ReactNode;
}
export interface PortalBubbleProps {
className?: string; className?: string;
openOn: { x: number; y: number; title?: string; text: ReactNode } | undefined; openOn: PortalBubbleOpenOn | undefined;
direction?: 'up' | 'down'; direction?: 'up' | 'down';
onClose?(): void; onClose?(): void;
mute?: boolean; mute?: boolean;
@ -55,7 +64,10 @@ export const PortalBubble = function PortalBubble(props: PortalBubbleProps) {
if (!element) return; if (!element) return;
setMyWidth(element.offsetWidth); setMyWidth(element.offsetWidth);
}} }}
style={{ left: x, top: openOn.y }} style={{
left: x,
top: openOn.y + (minimal ? 0 : direction === 'up' ? -SHPITZ_SIZE : SHPITZ_SIZE),
}}
> >
{(openOn.title || onClose) && ( {(openOn.title || onClose) && (
<div className={classNames('bubble-title-bar', { 'with-close': Boolean(onClose) })}> <div className={classNames('bubble-title-bar', { 'with-close': Boolean(onClose) })}>

View File

@ -47,11 +47,12 @@ import {
uniq, uniq,
} from '../../utils'; } from '../../utils';
import type { Margin, Stage } from '../../utils/stage'; import type { Margin, Stage } from '../../utils/stage';
import type { PortalBubbleOpenOn } from '../portal-bubble/portal-bubble';
import { PortalBubble } from '../portal-bubble/portal-bubble';
import { ChartAxis } from './chart-axis'; import { ChartAxis } from './chart-axis';
import type { IntervalBar, IntervalRow, IntervalStat, TrimmedIntervalRow } from './common'; import type { IntervalBar, IntervalRow, IntervalStat, TrimmedIntervalRow } from './common';
import { aggregateSegmentStats, formatIntervalStat, formatIsoDateOnly } from './common'; import { aggregateSegmentStats, formatIntervalStat, formatIsoDateOnly } from './common';
import { PortalBubble } from './portal-bubble';
import './segment-bar-chart-render.scss'; import './segment-bar-chart-render.scss';
@ -543,7 +544,7 @@ export const SegmentBarChartRender = function SegmentBarChartRender(
}; };
} }
let hoveredOpenOn: { x: number; y: number; title?: string; text: ReactNode } | undefined; let hoveredOpenOn: PortalBubbleOpenOn | undefined;
if (svgRef.current) { if (svgRef.current) {
const rect = svgRef.current.getBoundingClientRect(); const rect = svgRef.current.getBoundingClientRect();
@ -594,7 +595,7 @@ export const SegmentBarChartRender = function SegmentBarChartRender(
rect.x + rect.x +
CHART_MARGIN.left + CHART_MARGIN.left +
timeScale(new Date((bubbleInfo.start.valueOf() + bubbleInfo.end.valueOf()) / 2)), timeScale(new Date((bubbleInfo.start.valueOf() + bubbleInfo.end.valueOf()) / 2)),
y: rect.y + CHART_MARGIN.top - 10, y: rect.y + CHART_MARGIN.top,
title, title,
text, text,
}; };
@ -611,7 +612,7 @@ export const SegmentBarChartRender = function SegmentBarChartRender(
rect.x + rect.x +
CHART_MARGIN.left + CHART_MARGIN.left +
timeScale(new Date((selection.start.valueOf() + selection.end.valueOf()) / 2)), timeScale(new Date((selection.start.valueOf() + selection.end.valueOf()) / 2)),
y: rect.y + CHART_MARGIN.top - 10, y: rect.y + CHART_MARGIN.top,
title: `${formatIsoDateOnly(selection.start)}${formatIsoDateOnly(selection.end)}`, title: `${formatIsoDateOnly(selection.start)}${formatIsoDateOnly(selection.end)}`,
text: ( text: (
<> <>