Tooltips
Chart tooltip examples: indicators, labels, formatters, icons and a total.
Each example is an iv-card with a bar chart and an iv-chart-tooltip. It opens on the second day (defaultIndex); hover to move it. Copy the code under it. See Chart for the tooltip API.
import { IV_CHART_IMPORTS } from '@inlaylab/ivorie/chart';Default
2024-07-16
Running
380Swimming
420import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_CARD_IMPORTS } from '@inlaylab/ivorie/card';
import { IV_CHART_IMPORTS, IvChartConfig } from '@inlaylab/ivorie/chart';
@Component({
selector: 'demo-chart-tooltip-default',
imports: [IV_CARD_IMPORTS, IV_CHART_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-card class="w-full max-w-md">
<iv-card-header>
<iv-card-title>Tooltip - Default</iv-card-title>
<iv-card-description>Default tooltip with ChartTooltipContent.</iv-card-description>
</iv-card-header>
<iv-card-content>
<iv-chart [config]="config">
<svg ivBarChart [data]="data">
<g
ivXAxis
dataKey="date"
[tickLine]="false"
[tickMargin]="10"
[axisLine]="false"
[tickFormatter]="weekday"
/>
<g ivBar dataKey="running" stackId="a" [radius]="[0, 0, 4, 4]" />
<g ivBar dataKey="swimming" stackId="a" [radius]="[4, 4, 0, 0]" />
</svg>
<iv-chart-tooltip [cursor]="false" [defaultIndex]="1" />
</iv-chart>
</iv-card-content>
</iv-card>
`,
})
export default class ChartTooltipDefault {
protected readonly data = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
protected readonly config: IvChartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
};
/** Dates are UTC days: format them in UTC, so server and browser agree. */
protected readonly weekday = (value: string) =>
new Date(value).toLocaleDateString('en-US', { weekday: 'short', timeZone: 'UTC' });
}
Line Indicator
2024-07-16
Running
380Swimming
420import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_CARD_IMPORTS } from '@inlaylab/ivorie/card';
import { IV_CHART_IMPORTS, IvChartConfig } from '@inlaylab/ivorie/chart';
@Component({
selector: 'demo-chart-tooltip-indicator-line',
imports: [IV_CARD_IMPORTS, IV_CHART_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-card class="w-full max-w-md">
<iv-card-header>
<iv-card-title>Tooltip - Line Indicator</iv-card-title>
<iv-card-description>Tooltip with line indicator.</iv-card-description>
</iv-card-header>
<iv-card-content>
<iv-chart [config]="config">
<svg ivBarChart [data]="data">
<g
ivXAxis
dataKey="date"
[tickLine]="false"
[tickMargin]="10"
[axisLine]="false"
[tickFormatter]="weekday"
/>
<g ivBar dataKey="running" stackId="a" [radius]="[0, 0, 4, 4]" />
<g ivBar dataKey="swimming" stackId="a" [radius]="[4, 4, 0, 0]" />
</svg>
<iv-chart-tooltip indicator="line" [cursor]="false" [defaultIndex]="1" />
</iv-chart>
</iv-card-content>
</iv-card>
`,
})
export default class ChartTooltipIndicatorLine {
protected readonly data = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
protected readonly config: IvChartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
};
/** Dates are UTC days: format them in UTC, so server and browser agree. */
protected readonly weekday = (value: string) =>
new Date(value).toLocaleDateString('en-US', { weekday: 'short', timeZone: 'UTC' });
}
No Indicator
2024-07-16
Running
380Swimming
420import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_CARD_IMPORTS } from '@inlaylab/ivorie/card';
import { IV_CHART_IMPORTS, IvChartConfig } from '@inlaylab/ivorie/chart';
@Component({
selector: 'demo-chart-tooltip-indicator-none',
imports: [IV_CARD_IMPORTS, IV_CHART_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-card class="w-full max-w-md">
<iv-card-header>
<iv-card-title>Tooltip - No Indicator</iv-card-title>
<iv-card-description>Tooltip with no indicator.</iv-card-description>
</iv-card-header>
<iv-card-content>
<iv-chart [config]="config">
<svg ivBarChart [data]="data">
<g
ivXAxis
dataKey="date"
[tickLine]="false"
[tickMargin]="10"
[axisLine]="false"
[tickFormatter]="weekday"
/>
<g ivBar dataKey="running" stackId="a" [radius]="[0, 0, 4, 4]" />
<g ivBar dataKey="swimming" stackId="a" [radius]="[4, 4, 0, 0]" />
</svg>
<iv-chart-tooltip hideIndicator [cursor]="false" [defaultIndex]="1" />
</iv-chart>
</iv-card-content>
</iv-card>
`,
})
export default class ChartTooltipIndicatorNone {
protected readonly data = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
protected readonly config: IvChartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
};
/** Dates are UTC days: format them in UTC, so server and browser agree. */
protected readonly weekday = (value: string) =>
new Date(value).toLocaleDateString('en-US', { weekday: 'short', timeZone: 'UTC' });
}
Custom label
Activities
Running
380Swimming
420import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_CARD_IMPORTS } from '@inlaylab/ivorie/card';
import { IV_CHART_IMPORTS, IvChartConfig } from '@inlaylab/ivorie/chart';
@Component({
selector: 'demo-chart-tooltip-label-custom',
imports: [IV_CARD_IMPORTS, IV_CHART_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-card class="w-full max-w-md">
<iv-card-header>
<iv-card-title>Tooltip - Custom label</iv-card-title>
<iv-card-description>Tooltip with custom label from chartConfig.</iv-card-description>
</iv-card-header>
<iv-card-content>
<iv-chart [config]="config">
<svg ivBarChart [data]="data">
<g
ivXAxis
dataKey="date"
[tickLine]="false"
[tickMargin]="10"
[axisLine]="false"
[tickFormatter]="weekday"
/>
<g ivBar dataKey="running" stackId="a" [radius]="[0, 0, 4, 4]" />
<g ivBar dataKey="swimming" stackId="a" [radius]="[4, 4, 0, 0]" />
</svg>
<iv-chart-tooltip
labelKey="activities"
indicator="line"
[cursor]="false"
[defaultIndex]="1"
/>
</iv-chart>
</iv-card-content>
</iv-card>
`,
})
export default class ChartTooltipLabelCustom {
protected readonly data = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
protected readonly config: IvChartConfig = {
activities: { label: 'Activities' },
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
};
/** Dates are UTC days: format them in UTC, so server and browser agree. */
protected readonly weekday = (value: string) =>
new Date(value).toLocaleDateString('en-US', { weekday: 'short', timeZone: 'UTC' });
}
Label Formatter
July 16, 2024
Running
380Swimming
420import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_CARD_IMPORTS } from '@inlaylab/ivorie/card';
import { IV_CHART_IMPORTS, IvChartConfig } from '@inlaylab/ivorie/chart';
@Component({
selector: 'demo-chart-tooltip-label-formatter',
imports: [IV_CARD_IMPORTS, IV_CHART_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-card class="w-full max-w-md">
<iv-card-header>
<iv-card-title>Tooltip - Label Formatter</iv-card-title>
<iv-card-description>Tooltip with label formatter.</iv-card-description>
</iv-card-header>
<iv-card-content>
<iv-chart [config]="config">
<svg ivBarChart [data]="data">
<g
ivXAxis
dataKey="date"
[tickLine]="false"
[tickMargin]="10"
[axisLine]="false"
[tickFormatter]="weekday"
/>
<g ivBar dataKey="running" stackId="a" [radius]="[0, 0, 4, 4]" />
<g ivBar dataKey="swimming" stackId="a" [radius]="[4, 4, 0, 0]" />
</svg>
<iv-chart-tooltip [labelFormatter]="longDate" [cursor]="false" [defaultIndex]="1" />
</iv-chart>
</iv-card-content>
</iv-card>
`,
})
export default class ChartTooltipLabelFormatter {
protected readonly data = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
protected readonly config: IvChartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
};
/** Dates are UTC days: format them in UTC, so server and browser agree. */
protected readonly weekday = (value: string) =>
new Date(value).toLocaleDateString('en-US', { weekday: 'short', timeZone: 'UTC' });
protected readonly longDate = (value: string) =>
new Date(value).toLocaleDateString('en-US', {
day: 'numeric',
month: 'long',
year: 'numeric',
timeZone: 'UTC',
});
}
No Label
Running
380Swimming
420import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_CARD_IMPORTS } from '@inlaylab/ivorie/card';
import { IV_CHART_IMPORTS, IvChartConfig } from '@inlaylab/ivorie/chart';
@Component({
selector: 'demo-chart-tooltip-label-none',
imports: [IV_CARD_IMPORTS, IV_CHART_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-card class="w-full max-w-md">
<iv-card-header>
<iv-card-title>Tooltip - No Label</iv-card-title>
<iv-card-description>Tooltip with no label.</iv-card-description>
</iv-card-header>
<iv-card-content>
<iv-chart [config]="config">
<svg ivBarChart [data]="data">
<g
ivXAxis
dataKey="date"
[tickLine]="false"
[tickMargin]="10"
[axisLine]="false"
[tickFormatter]="weekday"
/>
<g ivBar dataKey="running" stackId="a" [radius]="[0, 0, 4, 4]" />
<g ivBar dataKey="swimming" stackId="a" [radius]="[4, 4, 0, 0]" />
</svg>
<iv-chart-tooltip hideIndicator hideLabel [cursor]="false" [defaultIndex]="1" />
</iv-chart>
</iv-card-content>
</iv-card>
`,
})
export default class ChartTooltipLabelNone {
protected readonly data = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
protected readonly config: IvChartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
};
/** Dates are UTC days: format them in UTC, so server and browser agree. */
protected readonly weekday = (value: string) =>
new Date(value).toLocaleDateString('en-US', { weekday: 'short', timeZone: 'UTC' });
}
Formatter
Running
380 kcal
Swimming
420 kcal
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_CARD_IMPORTS } from '@inlaylab/ivorie/card';
import { IV_CHART_IMPORTS, IvChartConfig } from '@inlaylab/ivorie/chart';
@Component({
selector: 'demo-chart-tooltip-formatter',
imports: [IV_CARD_IMPORTS, IV_CHART_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-card class="w-full max-w-md">
<iv-card-header>
<iv-card-title>Tooltip - Formatter</iv-card-title>
<iv-card-description>Tooltip with custom formatter .</iv-card-description>
</iv-card-header>
<iv-card-content>
<iv-chart [config]="config">
<svg ivBarChart [data]="data">
<g
ivXAxis
dataKey="date"
[tickLine]="false"
[tickMargin]="10"
[axisLine]="false"
[tickFormatter]="weekday"
/>
<g ivBar dataKey="running" stackId="a" [radius]="[0, 0, 4, 4]" />
<g ivBar dataKey="swimming" stackId="a" [radius]="[4, 4, 0, 0]" />
</svg>
<iv-chart-tooltip hideLabel [cursor]="false" [defaultIndex]="1">
<ng-template ivChartTooltipItem let-item let-label="label">
<div class="flex min-w-[130px] items-center text-xs text-muted-foreground">
{{ label }}
<div
class="ml-auto flex items-baseline gap-0.5 font-mono font-medium text-foreground tabular-nums"
>
{{ item.value }}
<span class="font-normal text-muted-foreground">kcal</span>
</div>
</div>
</ng-template>
</iv-chart-tooltip>
</iv-chart>
</iv-card-content>
</iv-card>
`,
})
export default class ChartTooltipFormatter {
protected readonly data = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
protected readonly config: IvChartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
};
/** Dates are UTC days: format them in UTC, so server and browser agree. */
protected readonly weekday = (value: string) =>
new Date(value).toLocaleDateString('en-US', { weekday: 'short', timeZone: 'UTC' });
}
Icons
Running
380Swimming
420import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NgIcon } from '@ng-icons/core';
import { lucideFootprints, lucideWaves } from '@ng-icons/lucide';
import { IV_CARD_IMPORTS } from '@inlaylab/ivorie/card';
import { IV_CHART_IMPORTS, IvChartConfig } from '@inlaylab/ivorie/chart';
/** Config icons: any component. These wrap an ng-icon. */
@Component({
selector: 'demo-footprints-icon',
imports: [NgIcon],
changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'flex text-muted-foreground' },
template: `<ng-icon [svg]="icon" />`,
})
class FootprintsIcon {
protected readonly icon = lucideFootprints;
}
@Component({
selector: 'demo-waves-icon',
imports: [NgIcon],
changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'flex text-muted-foreground' },
template: `<ng-icon [svg]="icon" />`,
})
class WavesIcon {
protected readonly icon = lucideWaves;
}
@Component({
selector: 'demo-chart-tooltip-icons',
imports: [IV_CARD_IMPORTS, IV_CHART_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-card class="w-full max-w-md">
<iv-card-header>
<iv-card-title>Tooltip - Icons</iv-card-title>
<iv-card-description>Tooltip with icons.</iv-card-description>
</iv-card-header>
<iv-card-content>
<iv-chart [config]="config">
<svg ivBarChart [data]="data">
<g
ivXAxis
dataKey="date"
[tickLine]="false"
[tickMargin]="10"
[axisLine]="false"
[tickFormatter]="weekday"
/>
<g ivBar dataKey="running" stackId="a" [radius]="[0, 0, 4, 4]" />
<g ivBar dataKey="swimming" stackId="a" [radius]="[4, 4, 0, 0]" />
</svg>
<iv-chart-tooltip hideLabel [cursor]="false" [defaultIndex]="1" />
</iv-chart>
</iv-card-content>
</iv-card>
`,
})
export default class ChartTooltipIcons {
protected readonly data = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
protected readonly config: IvChartConfig = {
running: { label: 'Running', color: 'var(--chart-1)', icon: FootprintsIcon },
swimming: { label: 'Swimming', color: 'var(--chart-2)', icon: WavesIcon },
};
/** Dates are UTC days: format them in UTC, so server and browser agree. */
protected readonly weekday = (value: string) =>
new Date(value).toLocaleDateString('en-US', { weekday: 'short', timeZone: 'UTC' });
}
Advanced
Running
380 kcal
Swimming
420 kcal
Total
800 kcal
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_CARD_IMPORTS } from '@inlaylab/ivorie/card';
import { IV_CHART_IMPORTS, IvChartConfig, IvChartDatum } from '@inlaylab/ivorie/chart';
@Component({
selector: 'demo-chart-tooltip-advanced',
imports: [IV_CARD_IMPORTS, IV_CHART_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-card class="w-full max-w-md">
<iv-card-header>
<iv-card-title>Tooltip - Advanced</iv-card-title>
<iv-card-description>Tooltip with custom formatter and total.</iv-card-description>
</iv-card-header>
<iv-card-content>
<iv-chart [config]="config">
<svg ivBarChart [data]="data">
<g
ivXAxis
dataKey="date"
[tickLine]="false"
[tickMargin]="10"
[axisLine]="false"
[tickFormatter]="weekday"
/>
<g ivBar dataKey="running" stackId="a" [radius]="[0, 0, 4, 4]" />
<g ivBar dataKey="swimming" stackId="a" [radius]="[4, 4, 0, 0]" />
</svg>
<iv-chart-tooltip hideLabel class="w-[180px]" [cursor]="false" [defaultIndex]="1">
<ng-template
ivChartTooltipItem
let-item
let-label="label"
let-name="name"
let-index="index"
>
<div
class="h-2.5 w-2.5 shrink-0 rounded-[2px] bg-(--color-bg)"
[style.--color-bg]="'var(--color-' + name + ')'"
></div>
{{ label }}
<div
class="ml-auto flex items-baseline gap-0.5 font-mono font-medium text-foreground tabular-nums"
>
{{ item.value }}
<span class="font-normal text-muted-foreground">kcal</span>
</div>
<!-- After the last item -->
@if (index === 1) {
<div
class="mt-1.5 flex basis-full items-center border-t pt-1.5 text-xs font-medium text-foreground"
>
Total
<div
class="ml-auto flex items-baseline gap-0.5 font-mono font-medium text-foreground tabular-nums"
>
{{ total(item.row) }}
<span class="font-normal text-muted-foreground">kcal</span>
</div>
</div>
}
</ng-template>
</iv-chart-tooltip>
</iv-chart>
</iv-card-content>
</iv-card>
`,
})
export default class ChartTooltipAdvanced {
protected readonly data = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
protected readonly config: IvChartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
};
/** Dates are UTC days: format them in UTC, so server and browser agree. */
protected readonly weekday = (value: string) =>
new Date(value).toLocaleDateString('en-US', { weekday: 'short', timeZone: 'UTC' });
protected readonly total = (row: IvChartDatum) =>
Number(row['running']) + Number(row['swimming']);
}