mirror of https://github.com/buster-so/buster.git
tooltip item move to taliwind
This commit is contained in:
parent
5144c1246d
commit
e460fa86f6
|
@ -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;
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
};
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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%;
|
||||
`
|
||||
}));
|
Loading…
Reference in New Issue