Skip to content

feat(models): add ContainerBlock for block kit - #1949

Open
srtaalej wants to merge 2 commits into
mainfrom
ale-add-containerblock
Open

feat(models): add ContainerBlock for block kit#1949
srtaalej wants to merge 2 commits into
mainfrom
ale-add-containerblock

Conversation

@srtaalej

@srtaalej srtaalej commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds ContainerBlock (type: "container") to the Block Kit models per https://docs.slack.dev/reference/block-kit/blocks/container-block/
  • Supports all documented properties: title, rich_text_title, subtitle, child_blocks, width, icon, is_collapsible, default_collapsed, has_header_divider
  • Includes validators for title/rich_text_title presence, max lengths, child_blocks count, width enum, and mutual exclusion of is_collapsible + has_header_divider

Test plan

  • Full existing test suite passes (99 tests, 0 regressions)
  • Manually tested against the Slack API via a Bolt test app (see below)
Example Bolt test app (app.py)

Register a /container-block slash command in your test app and use the text argument to test different property combinations:

  • /container-block — base (title + child_blocks)
  • /container-block width — adds width: "wide"
  • /container-block mrkdwn-subtitle — subtitle with mrkdwn type
  • /container-block has-header-divider — adds has_header_divider: true
  • /container-block default-collapsed — adds is_collapsible + default_collapsed
  • /container-block icon — adds icon image element
  • /container-block rich-text-title — uses rich_text_title instead of title
  • /container-block all — all compatible properties together
import logging
import os

from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler

logging.basicConfig(level=logging.DEBUG)

app = App(token=os.environ.get("SLACK_BOT_TOKEN"))


@app.command("/container-block")
def container_block_command(ack, respond, command):
    ack()
    variant = command.get("text", "").strip()

    base = {
        "type": "container",
        "title": {"type": "plain_text", "text": "Container Block Test"},
        "child_blocks": [
            {"type": "section", "text": {"type": "mrkdwn", "text": "Section inside a container."}},
            {"type": "divider"},
            {"type": "section", "text": {"type": "mrkdwn", "text": "Another section below the divider."}},
        ],
    }

    if variant == "width":
        base["width"] = "wide"
    elif variant == "mrkdwn-subtitle":
        base["subtitle"] = {"type": "mrkdwn", "text": "*Bold* subtitle"}
    elif variant == "has-header-divider":
        base["has_header_divider"] = True
    elif variant == "default-collapsed":
        base["is_collapsible"] = True
        base["default_collapsed"] = True
    elif variant == "icon":
        base["icon"] = {
            "type": "image",
            "image_url": "https://api.slack.com/img/blocks/bkb_template_images/plants.png",
            "alt_text": "icon",
        }
    elif variant == "rich-text-title":
        del base["title"]
        base["rich_text_title"] = {
            "type": "rich_text",
            "elements": [
                {"type": "rich_text_section", "elements": [{"type": "text", "text": "Rich Title"}]},
            ],
        }
    elif variant == "all":
        base["subtitle"] = {"type": "plain_text", "text": "All compatible properties"}
        base["width"] = "wide"
        base["icon"] = {
            "type": "image",
            "image_url": "https://api.slack.com/img/blocks/bkb_template_images/plants.png",
            "alt_text": "icon",
        }
        base["is_collapsible"] = True
    else:
        base["subtitle"] = {
            "type": "plain_text",
            "text": "Base test (try: width, mrkdwn-subtitle, has-header-divider, default-collapsed, icon, rich-text-title, all)",
        }

    respond(blocks=[base])


if __name__ == "__main__":
    SocketModeHandler(app, os.environ.get("SLACK_APP_TOKEN")).start()

@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.08%. Comparing base (49101ef) to head (f9411e8).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1949      +/-   ##
==========================================
+ Coverage   84.06%   84.08%   +0.02%     
==========================================
  Files         118      118              
  Lines       13506    13550      +44     
==========================================
+ Hits        11354    11394      +40     
- Misses       2152     2156       +4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@srtaalej srtaalej self-assigned this Aug 31, 2026
@srtaalej srtaalej added enhancement M-T: A feature request for new functionality semver:minor models labels Aug 31, 2026
@srtaalej
srtaalej marked this pull request as ready for review August 31, 2026 16:27
@srtaalej
srtaalej requested a review from a team as a code owner August 31, 2026 16:27
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 models semver:minor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant