diff --git a/block-kit/README.md b/block-kit/README.md index 3cd3768..302ad39 100644 --- a/block-kit/README.md +++ b/block-kit/README.md @@ -9,6 +9,7 @@ Read the [docs](https://docs.slack.dev/block-kit/) to learn concepts behind thes ### Blocks - **[Actions](https://docs.slack.dev/reference/block-kit/blocks/actions-block)**: Holds multiple interactive elements. [Implementation](./src/main/java/blocks/Actions.java). +- **[Carousel](https://docs.slack.dev/reference/block-kit/blocks/carousel-block)**: Displays related card blocks in a horizontally-scrolling container. [Implementation](./src/main/java/blocks/Carousel.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). - **[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). diff --git a/block-kit/src/main/java/blocks/Carousel.java b/block-kit/src/main/java/blocks/Carousel.java new file mode 100644 index 0000000..e9d6581 --- /dev/null +++ b/block-kit/src/main/java/blocks/Carousel.java @@ -0,0 +1,54 @@ +package blocks; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.CarouselBlock; +import com.slack.api.model.block.composition.BlockCompositions; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * Displays related card blocks in a horizontally-scrolling container. + * {@link https://docs.slack.dev/reference/block-kit/blocks/carousel-block/} + */ +public class Carousel { + /** + * A carousel with three cards. + */ + public static CarouselBlock example01() { + CarouselBlock block = Blocks.carousel(c -> c.elements(List.of( + Blocks.card(card -> card.blockId("carousel-card-1") + .icon(BlockElements.imageElement( + i -> i.imageUrl("https://picsum.photos/36/36").altText("Icon"))) + .title(BlockCompositions.markdownText("MDR")) + .subtitle(BlockCompositions.markdownText("Refining data files")) + .heroImage(BlockElements.imageElement( + i -> i.imageUrl("https://picsum.photos/400/300").altText("Sample hero image"))) + .body(BlockCompositions.markdownText("Blue badge required to gain access.")) + .actions(List.of(BlockElements.button(b -> b.text(BlockCompositions.plainText( + pt -> pt.text("Action Button").emoji(false))) + .actionId("button_action_1"))))), + Blocks.card(card -> card.blockId("carousel-card-2") + .icon(BlockElements.imageElement( + i -> i.imageUrl("https://picsum.photos/36/36").altText("Icon"))) + .title(BlockCompositions.markdownText("O&D")) + .subtitle(BlockCompositions.markdownText("Storage, maintenance, and rotation of art pieces")) + .heroImage(BlockElements.imageElement( + i -> i.imageUrl("https://picsum.photos/400/300").altText("Sample hero image"))) + .body(BlockCompositions.markdownText("Green badge required to gain access.")) + .actions(List.of(BlockElements.button(b -> b.text(BlockCompositions.plainText( + pt -> pt.text("Action Button").emoji(false))) + .actionId("button_action_2"))))), + Blocks.card(card -> card.blockId("carousel-card-3") + .icon(BlockElements.imageElement( + i -> i.imageUrl("https://picsum.photos/36/36").altText("Icon"))) + .title(BlockCompositions.markdownText("Wellness Center")) + .subtitle(BlockCompositions.markdownText("Wellness sessions")) + .heroImage(BlockElements.imageElement( + i -> i.imageUrl("https://picsum.photos/400/300").altText("Sample hero image"))) + .body(BlockCompositions.markdownText("Please take a seat in the waiting room until called.")) + .actions(List.of(BlockElements.button(b -> b.text(BlockCompositions.plainText( + pt -> pt.text("Action Button").emoji(false))) + .actionId("button_action_3")))))))); + return block; + } +} diff --git a/block-kit/src/test/java/blocks/CarouselTest.java b/block-kit/src/test/java/blocks/CarouselTest.java new file mode 100644 index 0000000..90a84f5 --- /dev/null +++ b/block-kit/src/test/java/blocks/CarouselTest.java @@ -0,0 +1,135 @@ +package blocks; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.CarouselBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class CarouselTest { + @Test + public void testExample01() { + CarouselBlock block = Carousel.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "carousel", + "elements": [ + { + "type": "card", + "block_id": "carousel-card-1", + "icon": { + "type": "image", + "image_url": "https://picsum.photos/36/36", + "alt_text": "Icon" + }, + "title": { + "type": "mrkdwn", + "text": "MDR" + }, + "subtitle": { + "type": "mrkdwn", + "text": "Refining data files" + }, + "hero_image": { + "type": "image", + "image_url": "https://picsum.photos/400/300", + "alt_text": "Sample hero image" + }, + "body": { + "type": "mrkdwn", + "text": "Blue badge required to gain access." + }, + "actions": [ + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Action Button", + "emoji": false + }, + "action_id": "button_action_1" + } + ] + }, + { + "type": "card", + "block_id": "carousel-card-2", + "icon": { + "type": "image", + "image_url": "https://picsum.photos/36/36", + "alt_text": "Icon" + }, + "title": { + "type": "mrkdwn", + "text": "O&D" + }, + "subtitle": { + "type": "mrkdwn", + "text": "Storage, maintenance, and rotation of art pieces" + }, + "hero_image": { + "type": "image", + "image_url": "https://picsum.photos/400/300", + "alt_text": "Sample hero image" + }, + "body": { + "type": "mrkdwn", + "text": "Green badge required to gain access." + }, + "actions": [ + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Action Button", + "emoji": false + }, + "action_id": "button_action_2" + } + ] + }, + { + "type": "card", + "block_id": "carousel-card-3", + "icon": { + "type": "image", + "image_url": "https://picsum.photos/36/36", + "alt_text": "Icon" + }, + "title": { + "type": "mrkdwn", + "text": "Wellness Center" + }, + "subtitle": { + "type": "mrkdwn", + "text": "Wellness sessions" + }, + "hero_image": { + "type": "image", + "image_url": "https://picsum.photos/400/300", + "alt_text": "Sample hero image" + }, + "body": { + "type": "mrkdwn", + "text": "Please take a seat in the waiting room until called." + }, + "actions": [ + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Action Button", + "emoji": false + }, + "action_id": "button_action_3" + } + ] + } + ] + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +}