Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/data-table-block.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@slack/types": minor
---

feat: add `data_table` Block Kit block type (`DataTableBlock`) and the `raw_number` cell composition object (`RawNumberElement`)
38 changes: 38 additions & 0 deletions packages/types/src/block-kit/blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type {
import type {
MrkdwnElement,
PlainTextElement,
RawNumberElement,
RawTextElement,
SlackFileImageObject,
TextObject,
Expand Down Expand Up @@ -60,6 +61,7 @@ export type KnownBlock =
| CarouselBlock
| ContextBlock
| ContextActionsBlock
| DataTableBlock
| DividerBlock
| FileBlock
| HeaderBlock
Expand Down Expand Up @@ -226,6 +228,42 @@ export interface ContextActionsBlock extends Block {
elements: ContextActionsBlockElement[];
}

/**
* A helper union type of all cell types that can be used in a {@link DataTableBlock} row. Cells can be of type
* `raw_text`, `raw_number`, or `rich_text`. Note that `rich_text` cells are not allowed in the header row.
*/
export type DataTableCell = RawTextElement | RawNumberElement | RichTextBlock;

/**
* @description Displays structured, sortable, and paginated data in a table.
* @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-table-block Data table block reference}.
*/
export interface DataTableBlock extends Block {
/**
* @description The type of block. For a data table block, `type` is always `data_table`.
*/
type: 'data_table';
/**
* @description An array consisting of table rows, where the first row is the header row. Each row is an array of
* cells of type `raw_text`, `raw_number`, or `rich_text`. Minimum 2 rows (a header and one data row) and maximum 101
* rows (a header and 100 data rows). Each row must contain the same number of cells, with a minimum of 1 and a maximum
* of 20 columns. The `rich_text` cell type is not allowed in the header row.
*/
rows: DataTableCell[][];
/**
* @description A description of the table used for the underlying HTML element.
*/
caption: string;
/**
* @description The number of rows to display per page. Minimum 1, maximum 100. Defaults to 5 if not provided.
*/
page_size?: number;
/**
* @description The zero-based index of the column used as the row identifier. Defaults to 0 if not provided.
*/
row_header_column_index?: number;
}

/**
* @description Visually separates pieces of info inside of a message. A content divider, like an `<hr>`, to split up
* different blocks inside of a message. The divider block is nice and neat, requiring only a `type`.
Expand Down
19 changes: 19 additions & 0 deletions packages/types/src/block-kit/composition-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,25 @@ export interface RawTextElement {
text: string;
}

/**
* @description Defines an object containing a numeric value and its display text. Used for numeric cells in a
* {@link DataTableBlock}, allowing the column to be sorted numerically.
*/
export interface RawNumberElement {
/**
* @description The formatting to use for this object.
*/
type: 'raw_number';
/**
* @description The numeric value used for sorting the column.
*/
value: number;
/**
* @description The text used to display the value. The minimum length is 1 character.
*/
text: string;
}

interface BaseConversationFilter {
/**
* @description Indicates which type of conversations should be included in the list. When this field is provided, any
Expand Down
52 changes: 51 additions & 1 deletion packages/types/test/blocks.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expectAssignable, expectError } from 'tsd';
import type { AlertBlock, CardBlock, CarouselBlock, KnownBlock } from '../src/index';
import type { AlertBlock, CardBlock, CarouselBlock, DataTableBlock, KnownBlock } from '../src/index';

// CardBlock
// -- sad path
Expand Down Expand Up @@ -62,3 +62,53 @@ expectAssignable<KnownBlock>({
type: 'carousel',
elements: [{ type: 'card' }],
});

// DataTableBlock
// -- sad path
expectError<DataTableBlock>({}); // missing type, rows, and caption
expectError<DataTableBlock>({ type: 'data_table' }); // missing required rows and caption
expectError<DataTableBlock>({
type: 'data_table',
rows: [[{ type: 'raw_text', text: 'Name' }]],
}); // missing required caption
expectError<DataTableBlock>({
type: 'data_table',
caption: 'A list of fruit and their quantities',
}); // missing required rows
// -- happy path
expectAssignable<DataTableBlock>({
type: 'data_table',
caption: 'A list of fruit and their quantities',
rows: [
[
{ type: 'raw_text', text: 'Fruit' },
{ type: 'raw_text', text: 'Quantity' },
],
[
{ type: 'raw_text', text: 'Apples' },
{ type: 'raw_number', value: 12, text: '12' },
],
],
});
expectAssignable<DataTableBlock>({
type: 'data_table',
caption: 'A list of users',
block_id: 'users_table',
page_size: 10,
row_header_column_index: 0,
rows: [
[
{ type: 'raw_text', text: 'User' },
{ type: 'raw_text', text: 'Bio' },
],
[
{ type: 'raw_text', text: 'Mark' },
{ type: 'rich_text', elements: [{ type: 'rich_text_section', elements: [{ type: 'text', text: 'Founder' }] }] },
],
],
});
expectAssignable<KnownBlock>({
type: 'data_table',
caption: 'A minimal table',
rows: [[{ type: 'raw_text', text: 'Header' }], [{ type: 'raw_text', text: 'Value' }]],
});