update chart tooltip designs (#15426)

closes
https://discord.com/channels/1130383047699738754/1430845815634657320

~~TODO: add truncation~~
This commit is contained in:
nitin
2025-10-30 19:07:59 +05:30
committed by GitHub
parent 2461296158
commit 28333815d5
7 changed files with 292 additions and 61 deletions
@@ -3,23 +3,36 @@ import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
import { IconArrowUpRight } from 'twenty-ui/display';
const StyledTooltipContent = styled.div`
const StyledTooltip = styled.div`
background: ${({ theme }) => theme.background.primary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: ${({ theme }) => theme.border.radius.md};
box-shadow: ${({ theme }) => theme.boxShadow.strong};
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(3)};
padding: ${({ theme }) => theme.spacing(3)};
gap: 2px;
max-width: min(300px, calc(100vw - 40px));
min-width: 160px;
pointer-events: none;
`;
const StyledTooltipContent = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(3)};
padding: ${({ theme }) => theme.spacing(2)};
`;
const StyledTooltipRow = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.extraLight};
display: flex;
font-size: ${({ theme }) => theme.font.size.xs};
gap: ${({ theme }) => theme.spacing(2)};
`;
const StyledTooltipRowContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
`;
@@ -31,22 +44,68 @@ const StyledDot = styled.div<{ $color: string }>`
flex-shrink: 0;
`;
const StyledTooltipValue = styled.span`
margin-left: auto;
white-space: nowrap;
`;
const StyledTooltipLink = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.light};
cursor: default;
display: flex;
justify-content: space-between;
height: ${({ theme }) => theme.spacing(6)};
font-weight: ${({ theme }) => theme.font.weight.regular};
padding-inline: ${({ theme }) => theme.spacing(2)};
line-height: 140%;
`;
const StyledTooltipSeparator = styled.div`
background-color: ${({ theme }) => theme.border.color.light};
min-height: 1px;
width: 100%;
`;
const StyledTooltipHeader = styled.div`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.sm};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.medium};
line-height: 140%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const StyledTooltipRowRightContent = styled.div`
align-items: center;
display: flex;
justify-content: space-between;
font-size: ${({ theme }) => theme.font.size.xs};
color: ${({ theme }) => theme.font.color.extraLight};
font-weight: ${({ theme }) => theme.font.weight.regular};
gap: ${({ theme }) => theme.spacing(2)};
min-width: 0;
width: 100%;
`;
const StyledTooltipLabel = styled.span`
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const StyledTooltipValue = styled.span`
flex-shrink: 0;
font-weight: ${({ theme }) => theme.font.weight.medium};
white-space: nowrap;
`;
const StyledHorizontalSectionPadding = styled.div<{
$addTop?: boolean;
$addBottom?: boolean;
}>`
padding-inline: ${({ theme }) => theme.spacing(1)};
margin-top: ${({ $addTop, theme }) => ($addTop ? theme.spacing(1) : 0)};
margin-bottom: ${({ $addBottom, theme }) =>
$addBottom ? theme.spacing(1) : 0};
`;
export type GraphWidgetTooltipItem = {
@@ -58,32 +117,47 @@ export type GraphWidgetTooltipItem = {
type GraphWidgetTooltipProps = {
items: GraphWidgetTooltipItem[];
showClickHint?: boolean;
title?: string;
indexLabel?: string;
};
export const GraphWidgetTooltip = ({
items,
showClickHint = false,
title,
indexLabel,
}: GraphWidgetTooltipProps) => {
const theme = useTheme();
return (
<StyledTooltipContent>
{title && <StyledTooltipHeader>{title}</StyledTooltipHeader>}
{items.map((item, index) => (
<StyledTooltipRow key={index}>
<StyledDot $color={item.dotColor} />
<span>{item.label}</span>
<StyledTooltipValue>{item.formattedValue}</StyledTooltipValue>
</StyledTooltipRow>
))}
<StyledTooltip>
<StyledHorizontalSectionPadding $addTop $addBottom={!showClickHint}>
<StyledTooltipContent>
{indexLabel && (
<StyledTooltipHeader>{indexLabel}</StyledTooltipHeader>
)}
<StyledTooltipRowContainer>
{items.map((item, index) => (
<StyledTooltipRow key={index}>
<StyledDot $color={item.dotColor} />
<StyledTooltipRowRightContent>
<StyledTooltipLabel>{item.label}</StyledTooltipLabel>
<StyledTooltipValue>{item.formattedValue}</StyledTooltipValue>
</StyledTooltipRowRightContent>
</StyledTooltipRow>
))}
</StyledTooltipRowContainer>
</StyledTooltipContent>
</StyledHorizontalSectionPadding>
{showClickHint && (
<StyledTooltipLink>
<span>{t`Click to see data`}</span>
<IconArrowUpRight size={theme.icon.size.sm} />
</StyledTooltipLink>
<>
<StyledTooltipSeparator />
<StyledHorizontalSectionPadding $addBottom>
<StyledTooltipLink>
<span>{t`Click to see data`}</span>
<IconArrowUpRight size={theme.icon.size.sm} />
</StyledTooltipLink>
</StyledHorizontalSectionPadding>
</>
)}
</StyledTooltipContent>
</StyledTooltip>
);
};
@@ -253,6 +253,8 @@ export const Stacked: Story = {
data={args.data}
indexBy={args.indexBy}
keys={args.keys}
groupMode={args.groupMode}
seriesLabels={args.seriesLabels}
showLegend={args.showLegend}
showGrid={args.showGrid}
xAxisLabel={args.xAxisLabel}
@@ -492,6 +494,124 @@ export const Currency: Story = {
),
};
export const GroupedWithAllBarsTooltip: Story = {
args: {
data: [
{
period: 'January',
lastYear: 18000,
thisYear: 19500,
to: '/comparison/january',
},
{
period: 'February',
lastYear: 20000,
thisYear: 20000,
to: '/comparison/february',
},
{
period: 'March',
lastYear: 22000,
thisYear: 24500,
to: '/comparison/march',
},
{
period: 'April',
lastYear: 21000,
thisYear: 23000,
to: '/comparison/april',
},
],
indexBy: 'period',
keys: ['lastYear', 'thisYear'],
seriesLabels: {
lastYear: 'Last year',
thisYear: 'This year',
},
displayType: 'shortNumber',
showLegend: true,
showGrid: true,
xAxisLabel: 'Period',
yAxisLabel: 'Revenue',
groupMode: 'grouped',
id: 'bar-chart-grouped-all-tooltip',
enableGroupTooltip: true,
},
render: (args) => (
<Container>
<GraphWidgetBarChart
data={args.data}
indexBy={args.indexBy}
keys={args.keys}
seriesLabels={args.seriesLabels}
displayType={args.displayType}
showLegend={args.showLegend}
showGrid={args.showGrid}
xAxisLabel={args.xAxisLabel}
yAxisLabel={args.yAxisLabel}
groupMode={args.groupMode}
id={args.id}
enableGroupTooltip={args.enableGroupTooltip}
/>
</Container>
),
};
export const GroupedDefaultTooltip: Story = {
args: {
data: [
{
period: 'January',
lastYear: 18000,
thisYear: 19500,
to: '/comparison/january',
},
{
period: 'February',
lastYear: 20000,
thisYear: 20000,
to: '/comparison/february',
},
{
period: 'March',
lastYear: 22000,
thisYear: 24500,
to: '/comparison/march',
},
],
indexBy: 'period',
keys: ['lastYear', 'thisYear'],
seriesLabels: {
lastYear: 'Last year',
thisYear: 'This year',
},
displayType: 'shortNumber',
showLegend: true,
showGrid: true,
xAxisLabel: 'Period',
yAxisLabel: 'Revenue',
groupMode: 'grouped',
id: 'bar-chart-grouped-default',
},
render: (args) => (
<Container>
<GraphWidgetBarChart
data={args.data}
indexBy={args.indexBy}
keys={args.keys}
seriesLabels={args.seriesLabels}
displayType={args.displayType}
showLegend={args.showLegend}
showGrid={args.showGrid}
xAxisLabel={args.xAxisLabel}
yAxisLabel={args.yAxisLabel}
groupMode={args.groupMode}
id={args.id}
/>
</Container>
),
};
export const Catalog: Story = {
decorators: [CatalogDecorator],
parameters: {
@@ -25,6 +25,7 @@ export const Default: Story = {
},
],
showClickHint: false,
indexLabel: 'March 09, 2024',
},
};
@@ -45,21 +46,38 @@ export const MultipleItems: Story = {
args: {
items: [
{
label: 'Q1',
formattedValue: '$12,345',
label: 'Last year',
formattedValue: '20k',
dotColor: 'blue',
},
{
label: 'Q2',
formattedValue: '$23,456',
dotColor: 'green',
},
{
label: 'Q3',
formattedValue: '$34,567',
dotColor: 'red',
label: 'This year',
formattedValue: '20k',
dotColor: 'purple',
},
],
showClickHint: false,
showClickHint: true,
indexLabel: 'February 2',
},
};
export const SuperLongText: Story = {
args: {
items: [
{
label:
'Total Annual Recurring Revenue (North America Region including Canada)',
formattedValue: '$2,450,000',
dotColor: 'blue',
},
{
label: 'Customer Acquisition Cost (Marketing & Sales Combined)',
formattedValue: '$125,500',
dotColor: 'purple',
},
],
showClickHint: true,
indexLabel:
'Q4 2024 Financial Year End (October - December) - North America Regional Performance Summary',
},
};