Created
September 29, 2025 13:26
-
-
Save mxsxs2/8de4e5b3f798b833fb6a59e07ea6e72b to your computer and use it in GitHub Desktop.
Plugin to always show tooltips for chart.js charts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { | |
| Chart, | |
| ChartType, | |
| Plugin, | |
| ChartConfiguration, | |
| VisualElement, | |
| } from 'chart.js' | |
| export interface AlwaysShowTooltipPluginOptions { | |
| color?: string | |
| } | |
| declare module 'chart.js' { | |
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | |
| interface PluginOptionsByType<TType extends ChartType> { | |
| alwaysShowTooltip?: AlwaysShowTooltipPluginOptions | |
| } | |
| } | |
| //TODO: implement tests once we change over from jest to vitest | |
| /** | |
| * Chart.js plugin to display always-visible tooltips (data values) on chart elements. | |
| * | |
| * Supports bar, line, pie, and doughnut charts. Skips values that are 0 or null. | |
| * Tooltip text is centered inside each chart element: | |
| * - Bars: vertically centered in the bar | |
| * - Lines: slightly above each point | |
| * - Pie/Doughnut: centered in each arc | |
| * | |
| * Plugin options can be set via `chartOptions.plugins.alwaysShowTooltip`, for example: | |
| * ```ts | |
| * plugins: { | |
| * alwaysShowTooltip: { | |
| * color: 'white', // sets the tooltip text color | |
| * } | |
| * } | |
| * ``` | |
| * | |
| * @type {Plugin<ChartType>} | |
| */ | |
| const AlwaysShowTooltipPlugin: Plugin<ChartType> = { | |
| id: 'alwaysShowTooltip', | |
| afterDatasetsDraw<TType extends ChartType>( | |
| chart: Chart<TType>, | |
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | |
| _: any, | |
| pluginOptions: AlwaysShowTooltipPluginOptions | |
| ) { | |
| const { ctx } = chart | |
| const chartType = (chart.config as ChartConfiguration<TType>).type | |
| const color = pluginOptions?.color ?? 'black' // default to black | |
| ctx.save() | |
| ctx.font = '12px sans-serif' | |
| ctx.textAlign = 'center' | |
| ctx.textBaseline = 'middle' | |
| chart.data.datasets.forEach((dataset, datasetIndex) => { | |
| const meta = chart.getDatasetMeta(datasetIndex) | |
| meta.data.forEach((element, index) => { | |
| const value = dataset.data[index] as number | |
| if (!value) return | |
| if (chartType === 'bar') { | |
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | |
| const x = (element as any).x | |
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | |
| const y = ((element as any).base + (element as any).y) / 2 | |
| ctx.fillStyle = color | |
| ctx.fillText(String(value), x, y) | |
| } | |
| if (chartType === 'line') { | |
| const { x, y } = element | |
| ctx.fillStyle = color | |
| ctx.fillText(String(value), x, y - 10) | |
| } | |
| if (chartType === 'pie' || chartType === 'doughnut') { | |
| const { x, y } = ( | |
| element as unknown as VisualElement | |
| ).getCenterPoint() | |
| ctx.fillStyle = color | |
| ctx.fillText(String(value), x, y) | |
| } | |
| }) | |
| }) | |
| ctx.restore() | |
| }, | |
| } | |
| export default AlwaysShowTooltipPlugin |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment