diff --git a/.changeset/data-table-action-cell.md b/.changeset/data-table-action-cell.md new file mode 100644 index 000000000..a3d5c9944 --- /dev/null +++ b/.changeset/data-table-action-cell.md @@ -0,0 +1,5 @@ +--- +"@slack/types": minor +--- + +feat(types): support `action_cell` cells in [`data_table`](https://docs.slack.dev/reference/block-kit/blocks/data-table-block) block rows with the new `ActionCellElement` type diff --git a/packages/types/src/block-kit/blocks.ts b/packages/types/src/block-kit/blocks.ts index 9237fbbea..2aed8fabe 100644 --- a/packages/types/src/block-kit/blocks.ts +++ b/packages/types/src/block-kit/blocks.ts @@ -26,6 +26,7 @@ import type { WorkflowButton, } from './block-elements'; import type { + ActionCellElement, MrkdwnElement, PlainTextElement, RawNumberElement, @@ -369,7 +370,7 @@ export interface DataTableBlock extends Block { /** * @description An array consisting of table rows. */ - rows: (RawTextElement | RawNumberElement | RichTextBlock)[][]; + rows: (ActionCellElement | RawTextElement | RawNumberElement | RichTextBlock)[][]; /** * @description A caption for the table; used as the value for the HTML caption element. */ diff --git a/packages/types/src/block-kit/composition-objects.ts b/packages/types/src/block-kit/composition-objects.ts index b36d1cf50..13ddb4876 100644 --- a/packages/types/src/block-kit/composition-objects.ts +++ b/packages/types/src/block-kit/composition-objects.ts @@ -1,5 +1,7 @@ // This file contains objects documented here: https://docs.slack.dev/reference/block-kit/composition-objects +import type { Button } from './block-elements'; + /** * Re-usable labels for common color schemes present in Slack. `danger` displays with a red background (red text on * mobile), while `primary` displays with a green background (green text on mobile). @@ -173,6 +175,25 @@ export interface MrkdwnElement { verbatim?: boolean; } +/** + * @description Defines a data table cell containing a button element. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-table-block#schema-action-cell Action cell reference}. + */ +export interface ActionCellElement { + /** + * @description The type of cell. In this case `type` is always `action_cell`. + */ + type: 'action_cell'; + /** + * @description A button element. + */ + element: Button; + /** + * @description A raw_text or raw_number cell. + */ + fallback?: RawTextElement | RawNumberElement; +} + /** * @description Defines an object containing a numeric value. */ diff --git a/packages/types/test/blocks.test-d.ts b/packages/types/test/blocks.test-d.ts index 26e2525c8..d6169516c 100644 --- a/packages/types/test/blocks.test-d.ts +++ b/packages/types/test/blocks.test-d.ts @@ -179,6 +179,14 @@ expectError({ type: 'data_table', caption: 'A list of fruit and their quantities', }); // missing required rows +expectError({ + type: 'data_table', + caption: 'A list of tasks', + rows: [ + [{ type: 'raw_text', text: 'Action' }], + [{ type: 'action_cell', fallback: { type: 'raw_text', text: 'Open' } }], + ], +}); // action_cell missing required element // -- happy path expectAssignable({ type: 'data_table', @@ -211,6 +219,51 @@ expectAssignable({ ], ], }); +expectAssignable({ + type: 'data_table', + caption: 'A list of tasks', + rows: [ + [ + { type: 'raw_text', text: 'Task' }, + { type: 'raw_text', text: 'Action' }, + ], + [ + { type: 'raw_text', text: 'Write docs' }, + { + type: 'action_cell', + element: { + type: 'button', + text: { type: 'plain_text', text: 'Mark done' }, + action_id: 'mark_done', + value: 'task_123', + }, + fallback: { type: 'raw_text', text: 'Open' }, + }, + ], + ], +}); +expectAssignable({ + type: 'data_table', + caption: 'A list of tasks', + rows: [ + [ + { type: 'raw_text', text: 'Task' }, + { type: 'raw_text', text: 'Action' }, + ], + [ + { type: 'raw_text', text: 'Write docs' }, + { + type: 'action_cell', + element: { + type: 'button', + text: { type: 'plain_text', text: 'Mark done' }, + action_id: 'mark_done', + value: 'task_123', + }, + }, + ], + ], +}); expectAssignable({ type: 'data_table', caption: 'A minimal table', @@ -221,6 +274,24 @@ expectAssignable({ // -- sad path expectError({}); // missing type and rows expectError({ type: 'table' }); // missing required rows +expectError({ + type: 'table', + rows: [ + [{ type: 'raw_text', text: 'Action' }], + [ + { + type: 'action_cell', + element: { + type: 'button', + text: { type: 'plain_text', text: 'Mark done' }, + action_id: 'mark_done', + value: 'task_123', + }, + fallback: { type: 'raw_text', text: 'Open' }, + }, + ], + ], +}); // action_cell is only allowed in data_table // -- happy path // Table cells can be rich_text, raw_text, or raw_number; column_settings describe column behavior. expectAssignable({ diff --git a/packages/types/test/composition-objects.test-d.ts b/packages/types/test/composition-objects.test-d.ts index 98a03259b..843084f3d 100644 --- a/packages/types/test/composition-objects.test-d.ts +++ b/packages/types/test/composition-objects.test-d.ts @@ -1,5 +1,46 @@ import { expectAssignable, expectError } from 'tsd'; -import type { RawNumberElement, RawTextElement } from '../src/index'; +import type { ActionCellElement, RawNumberElement, RawTextElement } from '../src/index'; + +// ActionCellElement +// -- sad path +expectError({}); // missing type and element +expectError({ type: 'action_cell' }); // missing required element +expectError({ type: 'action_cell', fallback: { type: 'raw_text', text: 'Open' } }); // missing required element +expectError({ + type: 'action_cell', + element: { type: 'button', text: { type: 'plain_text', text: 'Mark done' } }, + fallback: { type: 'rich_text', elements: [] }, +}); // fallback must be raw_text or raw_number +// -- happy path +expectAssignable({ + type: 'action_cell', + element: { + type: 'button', + text: { type: 'plain_text', text: 'Mark done' }, + action_id: 'mark_done', + value: 'task_123', + }, + fallback: { type: 'raw_text', text: 'Open' }, +}); +expectAssignable({ + type: 'action_cell', + element: { + type: 'button', + text: { type: 'plain_text', text: 'Mark done' }, + action_id: 'mark_done', + value: 'task_123', + }, + fallback: { type: 'raw_number', value: 1, text: '1' }, +}); +expectAssignable({ + type: 'action_cell', + element: { + type: 'button', + text: { type: 'plain_text', text: 'Mark done' }, + action_id: 'mark_done', + value: 'task_123', + }, +}); // RawNumberElement // -- sad path