tooltip item move to taliwind

This commit is contained in:
Nate Kelley 2025-02-26 15:18:57 -07:00
parent 5144c1246d
commit e460fa86f6
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
7 changed files with 139 additions and 61 deletions

View File

@ -16,7 +16,6 @@ export const BusterChartJSTooltip: React.FC<{
hasCategoryAxis: boolean;
hasMultipleMeasures: boolean;
keyToUsePercentage: string[];
columnSettings: NonNullable<BusterChartProps['columnSettings']>;
}> = ({
chart,
dataPoints: dataPointsProp,
@ -24,8 +23,7 @@ export const BusterChartJSTooltip: React.FC<{
selectedChartType,
hasCategoryAxis,
keyToUsePercentage,
hasMultipleMeasures,
columnSettings
hasMultipleMeasures
}) => {
const isPieChart = selectedChartType === ChartType.Pie;
const isScatter = selectedChartType === ChartType.Scatter;

View File

@ -194,7 +194,7 @@ const getOrCreateInitialTooltipContainer = (chart: ChartJSOrUndefined) => {
tooltipEl.innerHTML = `
<div class="tooltip-caret" ></div>
<div class="tooltip-content bg-white" style="position: relative; z-index: 2; border: 0.5px solid ${token.colorBorder}; border-radius: 4px"></div>
<div class="tooltip-content bg-background" style="position: relative; z-index: 2; border: 0.5px solid ${token.colorBorder}; border-radius: 4px"></div>
`;
const caretEl = tooltipEl.querySelector('.tooltip-caret')! as HTMLDivElement;
@ -245,7 +245,6 @@ const externalTooltip = (
columnLabelFormats={columnLabelFormats}
selectedChartType={selectedChartType}
keyToUsePercentage={keyToUsePercentage}
columnSettings={columnSettings}
chart={chart}
hasCategoryAxis={hasCategoryAxis}
hasMultipleMeasures={hasMultipleMeasures}

View File

@ -0,0 +1,113 @@
import type { Meta, StoryObj } from '@storybook/react';
import { BusterChartTooltip } from './BusterChartTooltip';
const meta: Meta<typeof BusterChartTooltip> = {
title: 'Base/Charts/BusterChartTooltip',
component: BusterChartTooltip,
parameters: {
layout: 'centered'
},
tags: ['autodocs'],
decorators: [
(Story) => (
<div className="rounded-sm border shadow-lg">
<Story />
</div>
)
]
};
export default meta;
type Story = StoryObj<typeof BusterChartTooltip>;
const baseTooltipItems = [
{
color: '#1677ff',
seriesType: 'line',
formattedLabel: 'Series 1',
values: [
{
formattedValue: 100,
formattedLabel: 'Value',
formattedPercentage: '50%'
}
],
usePercentage: true
},
{
color: '#52c41a',
seriesType: 'line',
formattedLabel: 'Series 2',
values: [
{
formattedValue: 200,
formattedLabel: 'Value',
formattedPercentage: '100%'
}
],
usePercentage: true
}
];
const scatterTooltipItems = [
{
color: '#1677ff',
seriesType: 'scatter',
formattedLabel: 'Point A',
values: [
{
formattedValue: '10 dollars',
formattedLabel: 'X',
formattedPercentage: undefined
},
{
formattedValue: '20 years',
formattedLabel: 'Y',
formattedPercentage: undefined
}
],
usePercentage: false
}
];
const manyTooltipItems = Array.from({ length: 15 }, (_, i) => ({
color: `hsl(${i * 20}, 70%, 50%)`,
seriesType: 'line',
formattedLabel: `Series ${i + 1}`,
values: [
{
formattedValue: (i + 1) * 100,
formattedLabel: 'Value',
formattedPercentage: `${(i + 1) * 10}%`
}
],
usePercentage: true
}));
export const Default: Story = {
args: {
tooltipItems: baseTooltipItems,
title: 'Chart Data'
}
};
export const WithScatterPlot: Story = {
args: {
tooltipItems: scatterTooltipItems,
title: '' //scatter typically does not have a title
}
};
export const WithManyItems: Story = {
args: {
tooltipItems: manyTooltipItems,
title: 'Many Series'
}
};
export const NoTitle: Story = {
args: {
tooltipItems: baseTooltipItems,
title: undefined
}
};

View File

@ -24,7 +24,9 @@ export const BusterChartTooltip: React.FC<{
<div className="flex flex-col py-1.5">
<div
className={`grid ${
isScatter ? 'grid-cols-1 gap-y-1.5' : 'grid-cols-[auto_auto] items-center gap-x-5'
isScatter
? 'grid-cols-1 gap-y-1.5'
: 'grid-cols-[auto_auto] items-center gap-x-5 gap-y-[3px]'
}`}>
{shownItems.map((param, index) => (
<TooltipItem key={index} {...param} />
@ -32,7 +34,7 @@ export const BusterChartTooltip: React.FC<{
</div>
{hasHiddenItems && (
<div className="text-text-secondary pl-3 text-sm">{`${hiddenItems.length} more...`}</div>
<div className="text-text-secondary mt-1 pl-3 text-sm">{`${hiddenItems.length} more...`}</div>
)}
</div>
</div>

View File

@ -1,8 +1,8 @@
import React from 'react';
import { useStyles } from './useStyles';
import type { ITooltipItem, TooltipItemValueProps } from './interfaces';
import { LegendItemDot } from '../BusterChartLegend';
import { LegendItemDot } from '../BusterChartLegend/LegendDot';
import { ChartType } from '../interfaces';
import { cn } from '@/lib/classMerge';
export const TooltipItem: React.FC<ITooltipItem> = ({
values,
@ -11,24 +11,23 @@ export const TooltipItem: React.FC<ITooltipItem> = ({
formattedLabel,
usePercentage
}) => {
const { styles, cx } = useStyles();
const isScatter = seriesType === 'scatter';
return (
<>
{formattedLabel && (
<>
<div className="flex items-center space-x-1.5 overflow-hidden pl-3 pr-3">
<div className="flex items-center space-x-1.5 overflow-hidden pr-3 pl-3">
<LegendItemDot color={color} type={seriesType as ChartType} inactive={false} />
<span
className={cx(styles.tooltipItemLabel, 'truncate', {
title: isScatter
className={cn('truncate text-base', {
'text-foreground font-medium': isScatter
})}>
{formattedLabel}
</span>
</div>
{isScatter && <div className={cx(styles.tooltipItemSeparator)} />}
{isScatter && <div className="bg-border h-[0.5px] w-full" />}
</>
)}
@ -42,8 +41,6 @@ const TooltipItemValue: React.FC<{
usePercentage: boolean;
isScatter: boolean;
}> = ({ values, usePercentage, isScatter }) => {
const { styles, cx } = useStyles();
const chooseValue = (
value: string | number | undefined,
percentage: string | number | undefined
@ -67,7 +64,10 @@ const TooltipItemValue: React.FC<{
const formattedValue = values[0]?.formattedValue;
return (
<div className={cx(styles.tooltipItemValue, 'tooltip-values px-3')}>
<div
className={cn(
'text-text-default tooltip-values overflow-hidden px-3 text-right text-xs font-medium text-ellipsis whitespace-nowrap'
)}>
{chooseValue(formattedValue, values[0]?.formattedPercentage)}
</div>
);
@ -77,12 +77,15 @@ const GroupTooltipValue: React.FC<{
label: string;
value: string | number | undefined;
}> = ({ label, value }) => {
const { styles, cx } = useStyles();
return (
<>
<div className={cx(styles.tooltipItemLabel, 'truncate')}>{label}</div>
<div className={cx(styles.tooltipItemValue)}>{value}</div>
<div className={cn('text-md text-text-secondary max-w-fit truncate')}>{label}</div>
<div
className={cn(
'text-text-default overflow-hidden text-right text-sm font-medium text-ellipsis whitespace-nowrap'
)}>
{value}
</div>
</>
);
};

View File

@ -1,11 +1,10 @@
import { useStyles } from './useStyles';
import { cn } from '@/lib/classMerge';
import React from 'react';
export const TooltipTitle: React.FC<{ title: string }> = ({ title }) => {
const { styles, cx } = useStyles();
return (
<div className={cx(styles.tooltipTitleContainer, 'px-3 py-1.5')}>
<span className="title">{title}</span>
<div className={cn('border-b', 'px-3 py-1.5')}>
<span className="text-foreground text-base font-medium">{title}</span>
</div>
);
};

View File

@ -1,36 +0,0 @@
import { createStyles } from 'antd-style';
export const useStyles = createStyles(({ token, css }) => ({
tooltipTitleContainer: css`
border-bottom: 0.5px solid ${token.colorBorder};
.title {
color: ${token.colorText};
font-size: 13px;
font-weight: 500;
}
`,
tooltipItemLabel: css`
font-size: 12px;
color: ${token.colorTextSecondary};
max-width: fit-content;
&.title {
color: ${token.colorText};
font-weight: 500;
}
`,
tooltipItemValue: css`
color: ${token.colorText};
font-size: 12px;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: right;
`,
tooltipItemSeparator: css`
background: ${token.colorBorder};
height: 0.5px;
width: 100%;
`
}));