Repository navigation
Conversation
Add support for the `table` layout block, which renders tabular data as a grid of rows and cells. Cells may be `raw_text`, `raw_number`, or a `rich_text` block, with optional per-column alignment/wrapping settings. - TableBlock (type "table") with rows, columnSettings, blockId - TableCell interface + RawTextTableCell, RawNumberTableCell impls; RichTextBlock now also implements TableCell for rich_text cells - TableColumnSetting (align, isWrapped) - GsonTableCellFactory for polymorphic cell (de)serialization, registered in GsonFactory; TableBlock registered in GsonLayoutBlockFactory - Blocks.table(...) builder helper - Tests covering parse, round-trip, and builder usage Docs: https://docs.slack.dev/reference/block-kit/blocks/table-block Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## chore/block-kit-data-table #1611 +/- ##
================================================================
+ Coverage 73.72% 73.73% +0.01%
- Complexity 4687 4690 +3
================================================================
Files 488 488
Lines 14695 14697 +2
Branches 1529 1529
================================================================
+ Hits 10834 10837 +3
+ Misses 2952 2951 -1
Partials 909 909
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
|
@zimeg Thanks for this PR. Can this be merged please to bring parity? |
zimeg
left a comment
There was a problem hiding this comment.
📝 Leaving some thoughts on the first shot implementation that I think we might want to consider before merge. I'm curious if we start with a less complete implementation - table but no cells - for sake of aligning the data_table block properties but I haven't investigated too much more.
…ta_table The data_table cells (raw_text / raw_number / rich_text) are the same cell model the table block uses. Rather than ship a parallel DataTableCell family, adopt the shared TableCell interface and its RawTextTableCell / RawNumberTableCell implementations in com.slack.api.model.block.composition, deserialized by a single GsonTableCellFactory: - Remove DataTableCell, RawTextDataTableCell, RawNumberDataTableCell, and GsonDataTableCellFactory. - Add TableCell, RawTextTableCell, RawNumberTableCell (in ...block.composition) and GsonTableCellFactory (in ...util.json). - DataTableBlock.rows is now List<List<TableCell>>; RichTextBlock implements TableCell; the client and model-test GsonFactory register TableCell -> GsonTableCellFactory. This is the same cell model the sibling table-block PR (#1611) introduces, placed in the same package with identical definitions, so whichever of the two lands second drops the now-duplicate files in a trivial merge. Mirrors how node (@slack/types composition objects) and python (slack_sdk basic_components) also share one cell model across both blocks. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
|
We'd love to see this merged! We currently publish table rows data as chunked tables in separate messages inside markdown blocks because of the markdown text limit. Would be great to also use the additional features of the table block that markdown tables don't have! |
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
build the table block on the shared RawTextObject and RawNumberObject cells from the data_table branch, drop the duplicate RawTextTableCell and RawNumberTableCell types, mirror the table-block docs in javadoc, and round-trip the docs example in BlockKitTest
… chore/block-kit-table
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
zimeg
left a comment
There was a problem hiding this comment.
⚙️ A comment about perhaps design decision but I'm open to separate classes if imports make more sense of course!
| .columnSettings(Arrays.asList( | ||
| TableBlock.ColumnSetting.builder().isWrapped(true).build(), | ||
| TableBlock.ColumnSetting.builder().align("right").build() | ||
| )) |
There was a problem hiding this comment.
🧪 note: Instead of a separate class we might prefer to nest the column settings of a table within the TableBlock class! Here's how it appears in actual code.
| * cells. Table cells can have a type of {@code rich_text}, {@code raw_text}, or {@code raw_number}. | ||
| */ | ||
| @Builder.Default | ||
| private List<List<TableCell>> rows = new ArrayList<>(); |
There was a problem hiding this comment.
🧩 question (non-blocking): rows takes any TableCell, which includes ActionCellObject, so a table can build (and GsonTableCellFactory will parse) an action_cell that the table block spec doesn't allow. Right now only the TableCell Javadoc says it's for data tables. What do you think about a narrower cell type for table rows so the type carries that rule? Fair to skip if a second factory isn't worth it 🤔
| " \"blocks\": [\n" + | ||
| " {\n" + | ||
| " \"type\": \"table\",\n" + | ||
| " \"column_settings\": [\n" + |
There was a problem hiding this comment.
🧪 suggestion (non-blocking): the spec says a null entry in column_settings skips that column. Could we add a null to this fixture? The existing toJsonTree round-trip would pin it for free.
| /** | ||
| * An array consisting of table rows. Maximum 100 rows. Each row object is an array with a max of 20 table | ||
| * cells. Table cells can have a type of {@code rich_text}, {@code raw_text}, or {@code raw_number}. | ||
| */ |
There was a problem hiding this comment.
🪓 suggestion (non-blocking): I think we might not need the field Javadoc here and on ColumnSetting. It restates the docs page (limits, defaults, even its doubled "the the" below), which the class @see already links, so it can drift. Same idea for the // TableBlock marker in Blocks.java and the docs URL comment in the test.
| /** | |
| * An array consisting of table rows. Maximum 100 rows. Each row object is an array with a max of 20 table | |
| * cells. Table cells can have a type of {@code rich_text}, {@code raw_text}, or {@code raw_number}. | |
| */ |
This pull request adds the
tablelayout block to the Java SDK model.TableBlock(table) withrows,columnSettings, andblockId.TableBlock.ColumnSetting, nested since onlytableuses it, withalign(left,center,right) andisWrapped.rowsisList<List<TableCell>>, using the sharedRawTextObject(raw_text),RawNumberObject(raw_number), andRichTextBlock(rich_text) cells from feat(block-kit): add data_table layout block #1613.TableBlockis registered inGsonLayoutBlockFactory. Cells use theGsonTableCellFactoryfrom feat(block-kit): add data_table layout block #1613, so no new Gson registration.Blocks.table(...)builder helper.BlockKitTestparses the docs example, with an addedraw_numberrow, and re-serializes it to the same JSON. It also round-trips a built block.This depends on #1613 and targets its branch so the diff shows only the
tablechanges. The base moves back tomainwhen #1613 merges.Kotlin DSL support is left for a follow-up that covers every block the Kotlin extension doesn't have yet.
Testing
Post the docs example with
chat.postMessage:Confirm
response.isOk()and that the table renders with the first column wrapped and the second column right aligned.Read the message back with
conversations.historyand confirm the block parses as aTableBlockwithRawTextObjectandRawNumberObjectcells.🤖 Generated with Claude Code