From 8196ea64e3604b8d230f1e799a29b8b2fb9169df Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 26 Jun 2026 17:08:54 -0700 Subject: [PATCH] feat(block-kit): add context actions block example Add a Context Actions block example mirroring the official Block Kit docs, demonstrating feedback buttons (example01) and an icon button (example02), with a matching deep-equality test and README entry. Co-Authored-By: Claude --- block-kit/README.md | 1 + .../src/main/java/blocks/ContextActions.java | 43 ++++++++++++ .../test/java/blocks/ContextActionsTest.java | 66 +++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 block-kit/src/main/java/blocks/ContextActions.java create mode 100644 block-kit/src/test/java/blocks/ContextActionsTest.java diff --git a/block-kit/README.md b/block-kit/README.md index 3cd3768..7da7bd5 100644 --- a/block-kit/README.md +++ b/block-kit/README.md @@ -10,6 +10,7 @@ Read the [docs](https://docs.slack.dev/block-kit/) to learn concepts behind thes - **[Actions](https://docs.slack.dev/reference/block-kit/blocks/actions-block)**: Holds multiple interactive elements. [Implementation](./src/main/java/blocks/Actions.java). - **[Context](https://docs.slack.dev/reference/block-kit/blocks/context-block)**: Provides contextual info, which can include both images and text. [Implementation](./src/main/java/blocks/Context.java). +- **[Context actions](https://docs.slack.dev/reference/block-kit/blocks/context-actions-block)**: Displays interactive elements at the message level. [Implementation](./src/main/java/blocks/ContextActions.java). - **[Divider](https://docs.slack.dev/reference/block-kit/blocks/divider-block)**: Visually separates pieces of info inside of a message. [Implementation](./src/main/java/blocks/Divider.java). - **[File](https://docs.slack.dev/reference/block-kit/blocks/file-block)**: Displays info about remote files. [Implementation](./src/main/java/blocks/File.java). - **[Header](https://docs.slack.dev/reference/block-kit/blocks/header-block)**: Displays a larger-sized text. [Implementation](./src/main/java/blocks/Header.java). diff --git a/block-kit/src/main/java/blocks/ContextActions.java b/block-kit/src/main/java/blocks/ContextActions.java new file mode 100644 index 0000000..84001e6 --- /dev/null +++ b/block-kit/src/main/java/blocks/ContextActions.java @@ -0,0 +1,43 @@ +package blocks; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.ContextActionsBlock; +import com.slack.api.model.block.composition.BlockCompositions; +import com.slack.api.model.block.composition.FeedbackButtonObject; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * Displays interactive elements at the message level. + * {@link https://docs.slack.dev/reference/block-kit/blocks/context-actions-block/} + */ +public class ContextActions { + /** + * A context actions block with feedback buttons. + */ + public static ContextActionsBlock example01() { + ContextActionsBlock block = Blocks.contextActions( + c -> c.elements(List.of(BlockElements.feedbackButtons(f -> f.actionId("feedback_buttons_1") + .positiveButton(FeedbackButtonObject.builder() + .text(BlockCompositions.plainText("👍")) + .value("positive_feedback") + .build()) + .negativeButton(FeedbackButtonObject.builder() + .text(BlockCompositions.plainText("👎")) + .value("negative_feedback") + .build()))))); + return block; + } + + /** + * A context actions block with an icon button. + */ + public static ContextActionsBlock example02() { + ContextActionsBlock block = + Blocks.contextActions(c -> c.elements(List.of(BlockElements.iconButton(i -> i.icon("trash") + .text(BlockCompositions.plainText("Delete")) + .actionId("delete_button_1") + .value("delete_item"))))); + return block; + } +} diff --git a/block-kit/src/test/java/blocks/ContextActionsTest.java b/block-kit/src/test/java/blocks/ContextActionsTest.java new file mode 100644 index 0000000..8a723eb --- /dev/null +++ b/block-kit/src/test/java/blocks/ContextActionsTest.java @@ -0,0 +1,66 @@ +package blocks; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.ContextActionsBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class ContextActionsTest { + @Test + public void testExample01() { + ContextActionsBlock block = ContextActions.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "context_actions", + "elements": [ + { + "type": "feedback_buttons", + "action_id": "feedback_buttons_1", + "positive_button": { + "text": { + "type": "plain_text", + "text": "👍" + }, + "value": "positive_feedback" + }, + "negative_button": { + "text": { + "type": "plain_text", + "text": "👎" + }, + "value": "negative_feedback" + } + } + ] + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample02() { + ContextActionsBlock block = ContextActions.example02(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "context_actions", + "elements": [ + { + "type": "icon_button", + "icon": "trash", + "text": { + "type": "plain_text", + "text": "Delete" + }, + "action_id": "delete_button_1", + "value": "delete_item" + } + ] + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +}