Skip to content

feat(types): add Card, Carousel, and Alert block types#2567

Merged
srtaalej merged 4 commits intomainfrom
ale-new-block-kit-elements
May 4, 2026
Merged

feat(types): add Card, Carousel, and Alert block types#2567
srtaalej merged 4 commits intomainfrom
ale-new-block-kit-elements

Conversation

@srtaalej
Copy link
Copy Markdown
Contributor

@srtaalej srtaalej commented Apr 29, 2026

Summary

  • Adds CardBlock — a rich display block for structured content (hero image, icon, title, subtitle, body, actions)
  • Adds CarouselBlock — a horizontally scrollable collection of card blocks (1–10 cards)
  • Adds AlertBlock — a prominent notice block with severity levels (default, info, warning, error, success)

All three interfaces are added to the KnownBlock discriminated union in blocks.ts and automatically barrel-exported via index.ts. Type tests cover happy paths, sad paths, and union assignability.

Note: The AlertBlock is only supported in modal views (views.open / views.update). It is not supported in chat.postMessage or other message surfaces.

Test plan

Test app.js (sends carousel + cards via chat.postMessage on startup)
import { App, LogLevel } from '@slack/bolt';
import { config } from 'dotenv';
import { registerListeners } from './listeners/index.js';

config();

/** Initialization */
const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  socketMode: true,
  appToken: process.env.SLACK_APP_TOKEN,
  logLevel: LogLevel.DEBUG,
});

/** Register Listeners */
registerListeners(app);

/** Start the Bolt App */
(async () => {
  try {
    await app.start();
    app.logger.info('⚡️ Bolt app is running!');

    await app.client.chat.postMessage({
      channel: '#test-blockkit-new-types',
      text: 'New Block Kit types demo',
      blocks: [
        {
          type: 'carousel',
          elements: [
            {
              type: 'card',
              hero_image: { type: 'image', image_url: 'https://picsum.photos/seed/a/400/200', alt_text: 'Card 1 hero' },
              title: { type: 'mrkdwn', text: 'Card Block' },
              subtitle: { type: 'mrkdwn', text: 'Rich structured content' },
              body: { type: 'mrkdwn', text: 'Recommendations, results, or work items.' },
              actions: [{ type: 'button', text: { type: 'plain_text', text: 'Learn more' }, action_id: 'card_1_btn' }],
            },
            {
              type: 'card',
              hero_image: { type: 'image', image_url: 'https://picsum.photos/seed/b/400/200', alt_text: 'Card 2 hero' },
              title: { type: 'mrkdwn', text: 'Alert Block' },
              subtitle: { type: 'mrkdwn', text: 'Prominent notices' },
              body: { type: 'mrkdwn', text: 'Warnings, status updates, and more.' },
              actions: [{ type: 'button', text: { type: 'plain_text', text: 'Learn more' }, action_id: 'card_2_btn' }],
            },
            {
              type: 'card',
              hero_image: { type: 'image', image_url: 'https://picsum.photos/seed/c/400/200', alt_text: 'Card 3 hero' },
              title: { type: 'mrkdwn', text: 'Carousel Block' },
              subtitle: { type: 'mrkdwn', text: 'Scrollable card collections' },
              body: { type: 'mrkdwn', text: 'Up to 10 cards, side by side.' },
              actions: [{ type: 'button', text: { type: 'plain_text', text: 'Learn more' }, action_id: 'card_3_btn' }],
            },
          ],
        },
      ],
    });
    app.logger.info('Sent block kit demo message');
  } catch (error) {
    app.logger.error('Failed to start the app', error);
  }
})();
Test shortcut handler (opens modal with alert blocks via global shortcut)
const sampleShortcutCallback = async ({ shortcut, ack, client, logger }) => {
  try {
    const { trigger_id } = shortcut;

    await ack();
    await client.views.open({
      trigger_id,
      view: {
        type: 'modal',
        callback_id: 'sample_view_id',
        title: {
          type: 'plain_text',
          text: 'Alert Block Demo',
        },
        blocks: [
          {
            type: 'alert',
            text: { type: 'mrkdwn', text: 'This is a *default* alert block' },
          },
          {
            type: 'alert',
            text: { type: 'mrkdwn', text: 'This is an *info* alert block' },
            level: 'info',
          },
          {
            type: 'alert',
            text: { type: 'mrkdwn', text: 'This is a *warning* alert block' },
            level: 'warning',
          },
          {
            type: 'alert',
            text: { type: 'mrkdwn', text: 'This is an *error* alert block' },
            level: 'error',
          },
          {
            type: 'alert',
            text: { type: 'mrkdwn', text: 'This is a *success* alert block' },
            level: 'success',
          },
        ],
        submit: {
          type: 'plain_text',
          text: 'Submit',
        },
      },
    });
  } catch (error) {
    logger.error(error);
  }
};

export { sampleShortcutCallback };
  • tsd type tests for all three block types (happy + sad paths)
  • KnownBlock union assignability tests
  • npm run build and npm test pass for @slack/types
  • Integration test: send a message with CardBlock to Slack
  • Integration test: send a message with CarouselBlock to Slack
  • Integration test: open a modal with AlertBlock in Slack (alert blocks are only supported in modal views)

🤖 Generated with Claude Code

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 29, 2026

🦋 Changeset detected

Latest commit: 0450dd2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@slack/types Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.38%. Comparing base (b8b88cb) to head (0450dd2).
⚠️ Report is 4 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2567   +/-   ##
=======================================
  Coverage   87.38%   87.38%           
=======================================
  Files          62       62           
  Lines       10256    10256           
  Branches      415      415           
=======================================
  Hits         8962     8962           
  Misses       1273     1273           
  Partials       21       21           
Flag Coverage Δ
cli-hooks 87.38% <ø> (ø)
cli-test 87.38% <ø> (ø)
logger 87.38% <ø> (ø)
oauth 87.38% <ø> (ø)
socket-mode 87.38% <ø> (ø)
web-api 87.38% <ø> (ø)
webhook 87.38% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@srtaalej srtaalej self-assigned this Apr 29, 2026
@srtaalej srtaalej added semver:minor enhancement M-T: A feature request for new functionality pkg:types applies to `@slack/types` server-side-issue labels Apr 29, 2026
@srtaalej srtaalej marked this pull request as ready for review April 30, 2026 19:35
@srtaalej srtaalej requested a review from a team as a code owner April 30, 2026 19:35
@zimeg
Copy link
Copy Markdown
Member

zimeg commented Apr 30, 2026

@srtaalej Would server-side-issue be blocking this still? Asking before I review!

@srtaalej
Copy link
Copy Markdown
Contributor Author

srtaalej commented May 1, 2026

@srtaalej Would server-side-issue be blocking this still? Asking before I review!

@zimeg nope! tag removed 🫡

Copy link
Copy Markdown
Member

@zimeg zimeg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@srtaalej LGTM! Thanks for introducing another set of blocks to build with 🧰 ✨

I'm approving now with solid implementations but wonder if we can order these entries within source code and also add a changeset so this can be released soon after 🚀

Comment thread packages/types/src/block-kit/blocks.ts Outdated
* At least one of `hero_image`, `title`, `actions`, or `body` must be provided.
* @see {@link https://docs.slack.dev/reference/block-kit/blocks/card-block Card block reference}.
*/
export interface CardBlock extends Block {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧮 question: Might these be ordered same as the KnownBlock pattern?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes!

@zimeg zimeg added this to the types@next milestone May 4, 2026
@zimeg
Copy link
Copy Markdown
Member

zimeg commented May 4, 2026

🛠️ praise: Meant to find a good place to thanks for the code example!

@srtaalej srtaalej merged commit 11dd0f5 into main May 4, 2026
12 checks passed
@srtaalej srtaalej deleted the ale-new-block-kit-elements branch May 4, 2026 15:55
pull Bot pushed a commit to Zezo-Ai/node-slack-sdk that referenced this pull request May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement M-T: A feature request for new functionality pkg:types applies to `@slack/types` semver:minor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants