From a18c69336dc086caa8fc554a9b9e1178b8add85c Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 26 Jun 2026 16:44:48 -0700 Subject: [PATCH 1/4] feat(types): add data_visualization Block Kit block Add the DataVisualizationBlock type and its nested chart objects (pie/bar/area/line) to @slack/types, including a tsd type test mirroring the existing block tests. Ref: https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Co-Authored-By: Claude --- .changeset/data-visualization-block.md | 5 + packages/types/src/block-kit/blocks.ts | 126 +++++++++++++++++++++++++ packages/types/test/blocks.test-d.ts | 68 ++++++++++++- 3 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 .changeset/data-visualization-block.md diff --git a/.changeset/data-visualization-block.md b/.changeset/data-visualization-block.md new file mode 100644 index 000000000..7dd4ba447 --- /dev/null +++ b/.changeset/data-visualization-block.md @@ -0,0 +1,5 @@ +--- +"@slack/types": minor +--- + +feat: add `DataVisualizationBlock` type for the `data_visualization` Block Kit block diff --git a/packages/types/src/block-kit/blocks.ts b/packages/types/src/block-kit/blocks.ts index 60ab5166c..fcd23101d 100644 --- a/packages/types/src/block-kit/blocks.ts +++ b/packages/types/src/block-kit/blocks.ts @@ -61,6 +61,7 @@ export type KnownBlock = | ContainerBlock | ContextBlock | ContextActionsBlock + | DataVisualizationBlock | DividerBlock | FileBlock | HeaderBlock @@ -289,6 +290,131 @@ export interface ContextActionsBlock extends Block { elements: ContextActionsBlockElement[]; } +/** + * @description A single slice of a {@link DataVisualizationPieChart}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationPieSegment { + /** + * @description The label for the segment. Maximum length is 20 characters. + */ + label: string; + /** + * @description The value for the segment. Must be greater than 0. + */ + value: number; +} + +/** + * @description A single data point within a {@link DataVisualizationSeries}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationDataPoint { + /** + * @description The label for the data point. Maximum length is 20 characters. Must match a category defined in + * the chart's {@link DataVisualizationAxisConfig}. + */ + label: string; + /** + * @description The value for the data point. Negative values are permitted. + */ + value: number; +} + +/** + * @description A series of data points displayed in a bar, area, or line {@link DataVisualizationBlock} chart. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationSeries { + /** + * @description The name of the series. Maximum length is 20 characters. Must be unique within the chart. + */ + name: string; + /** + * @description An array of {@link DataVisualizationDataPoint} objects. Minimum 1, maximum 20 data points. + */ + data: DataVisualizationDataPoint[]; +} + +/** + * @description Axis configuration for a bar, area, or line {@link DataVisualizationBlock} chart. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationAxisConfig { + /** + * @description The x-axis category labels. The order of categories determines the x-axis display sequence. Maximum + * length for each category is 20 characters. + */ + categories: string[]; + /** + * @description An optional label for the x-axis. Maximum length is 50 characters. + */ + x_label?: string; + /** + * @description An optional label for the y-axis. Maximum length is 50 characters. + */ + y_label?: string; +} + +/** + * @description A pie chart for a {@link DataVisualizationBlock}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationPieChart { + /** + * @description The type of chart. For a pie chart, `type` is always `pie`. + */ + type: 'pie'; + /** + * @description An array of {@link DataVisualizationPieSegment} objects. Minimum 1, maximum 6 segments. + */ + segments: DataVisualizationPieSegment[]; +} + +/** + * @description A bar, area, or line chart for a {@link DataVisualizationBlock}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationSeriesChart { + /** + * @description The type of chart. One of `bar`, `area`, or `line`. + */ + type: 'bar' | 'area' | 'line'; + /** + * @description An array of {@link DataVisualizationSeries} objects. Minimum 1, maximum 6 series. + */ + series: DataVisualizationSeries[]; + /** + * @description The {@link DataVisualizationAxisConfig} describing the chart axes. + */ + axis_config: DataVisualizationAxisConfig; +} + +/** + * @description A helper union type of all chart shapes supported by a {@link DataVisualizationBlock}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export type DataVisualizationChart = DataVisualizationPieChart | DataVisualizationSeriesChart; + +/** + * @description Displays a chart visualizing a dataset, such as a pie, bar, area, or line chart. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationBlock extends Block { + /** + * @description The type of block. For a data visualization block, `type` is always `data_visualization`. + */ + type: 'data_visualization'; + /** + * @description The title of the chart. Maximum length is 50 characters. + */ + title: string; + /** + * @description The {@link DataVisualizationChart} to render. One of a pie, bar, area, or line chart. + */ + chart: DataVisualizationChart; +} + /** * @description Visually separates pieces of info inside of a message. A content divider, like an `
`, to split up * different blocks inside of a message. The divider block is nice and neat, requiring only a `type`. diff --git a/packages/types/test/blocks.test-d.ts b/packages/types/test/blocks.test-d.ts index 3169703e5..98f1068b4 100644 --- a/packages/types/test/blocks.test-d.ts +++ b/packages/types/test/blocks.test-d.ts @@ -1,5 +1,5 @@ import { expectAssignable, expectError } from 'tsd'; -import type { AlertBlock, CardBlock, CarouselBlock, ContainerBlock, KnownBlock } from '../src/index'; +import type { AlertBlock, CardBlock, CarouselBlock, ContainerBlock, DataVisualizationBlock, KnownBlock } from '../src/index'; // CardBlock // -- sad path @@ -102,3 +102,69 @@ expectAssignable({ title: { type: 'plain_text', text: 'Known' }, child_blocks: [{ type: 'divider' }], }); + +// DataVisualizationBlock +// -- sad path +expectError({}); // missing type, title and chart +expectError({ type: 'data_visualization', title: 'Sales' }); // missing required chart +expectError({ + type: 'data_visualization', + title: 'Sales', + chart: { type: 'pie' }, // pie chart missing required segments +}); +expectError({ + type: 'data_visualization', + title: 'Sales', + chart: { type: 'bar', series: [{ name: 'Q1', data: [{ label: 'Jan', value: 1 }] }] }, // series chart missing axis_config +}); +expectError({ + type: 'data_visualization', + title: 'Sales', + chart: { type: 'scatter', segments: [{ label: 'A', value: 1 }] }, // unknown chart type +}); +// -- happy path +expectAssignable({ + type: 'data_visualization', + title: 'Revenue by region', + chart: { + type: 'pie', + segments: [ + { label: 'North', value: 40 }, + { label: 'South', value: 60 }, + ], + }, +}); +expectAssignable({ + type: 'data_visualization', + title: 'Quarterly revenue', + block_id: 'viz_1', + chart: { + type: 'bar', + series: [ + { + name: 'Product A', + data: [ + { label: 'Q1', value: 10 }, + { label: 'Q2', value: 20 }, + ], + }, + { + name: 'Product B', + data: [ + { label: 'Q1', value: 5 }, + { label: 'Q2', value: -3 }, + ], + }, + ], + axis_config: { categories: ['Q1', 'Q2'], x_label: 'Quarter', y_label: 'Revenue' }, + }, +}); +expectAssignable({ + type: 'data_visualization', + title: 'Trend', + chart: { + type: 'line', + series: [{ name: 'Users', data: [{ label: 'Mon', value: 1 }] }], + axis_config: { categories: ['Mon'] }, + }, +}); From 9587cd24ab7b8fc857f0f47935829942892f0960 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Tue, 8 Sep 2026 14:41:43 -0700 Subject: [PATCH 2/4] style(types): wrap blocks.test-d.ts import to satisfy biome formatter The rebase conflict resolution left the import on a single line that exceeds biome's line-length threshold, failing `biome check packages` in CI. Apply biome's own suggested multi-line format. Co-Authored-By: Claude --- packages/types/test/blocks.test-d.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/types/test/blocks.test-d.ts b/packages/types/test/blocks.test-d.ts index 98f1068b4..deb00e7e5 100644 --- a/packages/types/test/blocks.test-d.ts +++ b/packages/types/test/blocks.test-d.ts @@ -1,5 +1,12 @@ import { expectAssignable, expectError } from 'tsd'; -import type { AlertBlock, CardBlock, CarouselBlock, ContainerBlock, DataVisualizationBlock, KnownBlock } from '../src/index'; +import type { + AlertBlock, + CardBlock, + CarouselBlock, + ContainerBlock, + DataVisualizationBlock, + KnownBlock, +} from '../src/index'; // CardBlock // -- sad path From 8679ad91371916006ed98c6499dccf9f98ba9794 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 9 Sep 2026 16:27:16 -0700 Subject: [PATCH 3/4] refactor(types): keep only DataVisualizationBlock exported, inline the chart union The data_visualization block introduced seven exported companion types. Match the TableBlock precedent (TableBlockColumnSettings is a non-exported interface): export only DataVisualizationBlock and drop `export` from the six helper interfaces (still named for readability, referenced via {@link}). Inline the single-use DataVisualizationChart union directly on `chart` and remove the alias. No behavior change; narrows the public API. Co-Authored-By: Claude --- packages/types/src/block-kit/blocks.ts | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/types/src/block-kit/blocks.ts b/packages/types/src/block-kit/blocks.ts index 403e8cbef..200148afb 100644 --- a/packages/types/src/block-kit/blocks.ts +++ b/packages/types/src/block-kit/blocks.ts @@ -296,7 +296,7 @@ export interface ContextActionsBlock extends Block { * @description A single slice of a {@link DataVisualizationPieChart}. * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. */ -export interface DataVisualizationPieSegment { +interface DataVisualizationPieSegment { /** * @description The label for the segment. Maximum length is 20 characters. */ @@ -311,7 +311,7 @@ export interface DataVisualizationPieSegment { * @description A single data point within a {@link DataVisualizationSeries}. * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. */ -export interface DataVisualizationDataPoint { +interface DataVisualizationDataPoint { /** * @description The label for the data point. Maximum length is 20 characters. Must match a category defined in * the chart's {@link DataVisualizationAxisConfig}. @@ -327,7 +327,7 @@ export interface DataVisualizationDataPoint { * @description A series of data points displayed in a bar, area, or line {@link DataVisualizationBlock} chart. * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. */ -export interface DataVisualizationSeries { +interface DataVisualizationSeries { /** * @description The name of the series. Maximum length is 20 characters. Must be unique within the chart. */ @@ -342,7 +342,7 @@ export interface DataVisualizationSeries { * @description Axis configuration for a bar, area, or line {@link DataVisualizationBlock} chart. * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. */ -export interface DataVisualizationAxisConfig { +interface DataVisualizationAxisConfig { /** * @description The x-axis category labels. The order of categories determines the x-axis display sequence. Maximum * length for each category is 20 characters. @@ -362,7 +362,7 @@ export interface DataVisualizationAxisConfig { * @description A pie chart for a {@link DataVisualizationBlock}. * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. */ -export interface DataVisualizationPieChart { +interface DataVisualizationPieChart { /** * @description The type of chart. For a pie chart, `type` is always `pie`. */ @@ -377,7 +377,7 @@ export interface DataVisualizationPieChart { * @description A bar, area, or line chart for a {@link DataVisualizationBlock}. * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. */ -export interface DataVisualizationSeriesChart { +interface DataVisualizationSeriesChart { /** * @description The type of chart. One of `bar`, `area`, or `line`. */ @@ -392,12 +392,6 @@ export interface DataVisualizationSeriesChart { axis_config: DataVisualizationAxisConfig; } -/** - * @description A helper union type of all chart shapes supported by a {@link DataVisualizationBlock}. - * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. - */ -export type DataVisualizationChart = DataVisualizationPieChart | DataVisualizationSeriesChart; - /** * @description Displays a chart visualizing a dataset, such as a pie, bar, area, or line chart. * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. @@ -412,9 +406,10 @@ export interface DataVisualizationBlock extends Block { */ title: string; /** - * @description The {@link DataVisualizationChart} to render. One of a pie, bar, area, or line chart. + * @description The chart to render. One of a pie ({@link DataVisualizationPieChart}) or bar/area/line + * ({@link DataVisualizationSeriesChart}) chart. */ - chart: DataVisualizationChart; + chart: DataVisualizationPieChart | DataVisualizationSeriesChart; } /** From 786019e6f60b625617242a405e51f0a006e0002f Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 9 Sep 2026 16:37:54 -0700 Subject: [PATCH 4/4] refactor(types): split data_visualization series charts, align JSDoc to docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the single DataVisualizationSeriesChart (type: 'bar' | 'area' | 'line') into three discriminated interfaces — DataVisualizationBarChart, DataVisualizationAreaChart, DataVisualizationLineChart — each carrying a literal type and the per-type prose the docs give (bar groups; filled areas layered in array order; lines). All three stay unexported and union into DataVisualizationBlock.chart alongside the pie chart. Rewrite every field @description to mirror the data-visualization block reference verbatim, which also corrects the segment/series caps from "maximum 6" to the documented "Min 1, max 12". Add an area-chart happy-path type test (bar and line were already covered). Co-Authored-By: Claude --- packages/types/src/block-kit/blocks.ts | 92 +++++++++++++++++++------- packages/types/test/blocks.test-d.ts | 12 ++++ 2 files changed, 81 insertions(+), 23 deletions(-) diff --git a/packages/types/src/block-kit/blocks.ts b/packages/types/src/block-kit/blocks.ts index 200148afb..5ae0d6882 100644 --- a/packages/types/src/block-kit/blocks.ts +++ b/packages/types/src/block-kit/blocks.ts @@ -298,11 +298,12 @@ export interface ContextActionsBlock extends Block { */ interface DataVisualizationPieSegment { /** - * @description The label for the segment. Maximum length is 20 characters. + * @description Display name for this slice, shown in the legend and on hover. Maximum of 20 characters. */ label: string; /** - * @description The value for the segment. Must be greater than 0. + * @description Numeric weight of this slice. Must be greater than 0. Rendered percentage is the value divided by + * the sum of all segment values. */ value: number; } @@ -313,12 +314,12 @@ interface DataVisualizationPieSegment { */ interface DataVisualizationDataPoint { /** - * @description The label for the data point. Maximum length is 20 characters. Must match a category defined in - * the chart's {@link DataVisualizationAxisConfig}. + * @description The x-axis category this point belongs to. Must match one of the values in `axis_config.categories`. + * Maximum of 20 characters. */ label: string; /** - * @description The value for the data point. Negative values are permitted. + * @description Numeric y-axis value. Negative values are permitted. */ value: number; } @@ -329,11 +330,13 @@ interface DataVisualizationDataPoint { */ interface DataVisualizationSeries { /** - * @description The name of the series. Maximum length is 20 characters. Must be unique within the chart. + * @description Human-readable identifier displayed in the chart legend. Must be unique across all series in the + * same chart. Maximum 20 characters. */ name: string; /** - * @description An array of {@link DataVisualizationDataPoint} objects. Minimum 1, maximum 20 data points. + * @description Ordered data points. Min 1, max 20. Must contain exactly one entry for every label in + * `axis_config.categories`. */ data: DataVisualizationDataPoint[]; } @@ -344,16 +347,16 @@ interface DataVisualizationSeries { */ interface DataVisualizationAxisConfig { /** - * @description The x-axis category labels. The order of categories determines the x-axis display sequence. Maximum - * length for each category is 20 characters. + * @description Category labels for the x-axis. Defines valid labels and their left-to-right display order. Each + * category label has a maximum of 20 characters. */ categories: string[]; /** - * @description An optional label for the x-axis. Maximum length is 50 characters. + * @description Descriptive title displayed below the x-axis (e.g., "Time of Day"). Maximum of 50 characters. */ x_label?: string; /** - * @description An optional label for the y-axis. Maximum length is 50 characters. + * @description Descriptive title displayed beside the y-axis (e.g., "Latency (ms)"). Maximum of 50 characters. */ y_label?: string; } @@ -364,30 +367,70 @@ interface DataVisualizationAxisConfig { */ interface DataVisualizationPieChart { /** - * @description The type of chart. For a pie chart, `type` is always `pie`. + * @description The type of chart. In this case, `pie`. */ type: 'pie'; /** - * @description An array of {@link DataVisualizationPieSegment} objects. Minimum 1, maximum 6 segments. + * @description Labeled slices that make up the pie. Min 1, max 12. Each is a {@link DataVisualizationPieSegment}. */ segments: DataVisualizationPieSegment[]; } /** - * @description A bar, area, or line chart for a {@link DataVisualizationBlock}. + * @description A bar chart for a {@link DataVisualizationBlock}. * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. */ -interface DataVisualizationSeriesChart { +interface DataVisualizationBarChart { /** - * @description The type of chart. One of `bar`, `area`, or `line`. + * @description The type of chart. In this case, `bar`. */ - type: 'bar' | 'area' | 'line'; + type: 'bar'; /** - * @description An array of {@link DataVisualizationSeries} objects. Minimum 1, maximum 6 series. + * @description Series to plot as bar groups. Min 1, max 12. For multiple series, bars are grouped by label. Each is + * a {@link DataVisualizationSeries}. */ series: DataVisualizationSeries[]; /** - * @description The {@link DataVisualizationAxisConfig} describing the chart axes. + * @description X-axis categories and axis titles. See {@link DataVisualizationAxisConfig}. + */ + axis_config: DataVisualizationAxisConfig; +} + +/** + * @description An area chart for a {@link DataVisualizationBlock}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +interface DataVisualizationAreaChart { + /** + * @description The type of chart. In this case, `area`. + */ + type: 'area'; + /** + * @description Series to plot as filled areas. Min 1, max 12. Series are layered in array order (first at back). + * Each is a {@link DataVisualizationSeries}. + */ + series: DataVisualizationSeries[]; + /** + * @description X-axis categories and axis titles. See {@link DataVisualizationAxisConfig}. + */ + axis_config: DataVisualizationAxisConfig; +} + +/** + * @description A line chart for a {@link DataVisualizationBlock}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +interface DataVisualizationLineChart { + /** + * @description The type of chart. In this case, `line`. + */ + type: 'line'; + /** + * @description Series to plot as lines. Min 1, max 12. Each is a {@link DataVisualizationSeries}. + */ + series: DataVisualizationSeries[]; + /** + * @description X-axis categories and axis titles. See {@link DataVisualizationAxisConfig}. */ axis_config: DataVisualizationAxisConfig; } @@ -402,14 +445,17 @@ export interface DataVisualizationBlock extends Block { */ type: 'data_visualization'; /** - * @description The title of the chart. Maximum length is 50 characters. + * @description A short label displayed above the chart. Maximum 50 characters. */ title: string; /** - * @description The chart to render. One of a pie ({@link DataVisualizationPieChart}) or bar/area/line - * ({@link DataVisualizationSeriesChart}) chart. + * @description The chart-specific payload. Must be one of the following: `pie`, `bar`, `area`, or `line`. */ - chart: DataVisualizationPieChart | DataVisualizationSeriesChart; + chart: + | DataVisualizationPieChart + | DataVisualizationBarChart + | DataVisualizationAreaChart + | DataVisualizationLineChart; } /** diff --git a/packages/types/test/blocks.test-d.ts b/packages/types/test/blocks.test-d.ts index add3efdb1..cf731d17b 100644 --- a/packages/types/test/blocks.test-d.ts +++ b/packages/types/test/blocks.test-d.ts @@ -167,6 +167,18 @@ expectAssignable({ axis_config: { categories: ['Q1', 'Q2'], x_label: 'Quarter', y_label: 'Revenue' }, }, }); +expectAssignable({ + type: 'data_visualization', + title: 'Daily active users', + chart: { + type: 'area', + series: [ + { name: 'Free tier', data: [{ label: 'Mon', value: 12000 }] }, + { name: 'Paid tier', data: [{ label: 'Mon', value: 4500 }] }, + ], + axis_config: { categories: ['Mon'], x_label: 'Day', y_label: 'Users' }, + }, +}); expectAssignable({ type: 'data_visualization', title: 'Trend',