Skip to content

feat: support mrkdwn descriptions on OptionObject (#1471) - #1645

Draft
zimeg wants to merge 3 commits into
mainfrom
option-mrkdwn-description
Draft

feat: support mrkdwn descriptions on OptionObject (#1471)#1645
zimeg wants to merge 3 commits into
mainfrom
option-mrkdwn-description

Conversation

@zimeg

@zimeg zimeg commented Sep 10, 2026

Copy link
Copy Markdown
Member

Summary

OptionObject.description was hard-typed to PlainTextObject, so a mrkdwn description on a radio-button or checkbox option was coerced to plain_text on deserialize — the markdown was lost. The option-object docs state that radio buttons and checkboxes can use mrkdwn text objects for the description.

Fixes #1471.

What changed

  • OptionObject.description: PlainTextObjectTextObject (the same type already used for OptionObject.text). This routes deserialization through the existing polymorphic text-object factory, so a mrkdwn description round-trips as a MarkdownTextObject and a plain_text description still returns a PlainTextObject.
  • Kotlin DSL (OptionObjectBuilder): added a markdownDescription(text, verbatim) overload alongside the existing plain_text description(text, emoji).
  • Tests (extended existing cases rather than adding standalone ones):
    • BlockKitTest#parseCheckboxes — now asserts a mrkdwn option description deserializes to MarkdownTextObject while a plain_text option stays PlainTextObject.
    • ActionsBlockTest#Channel select and checkboxes`` (Kotlin) — the first checkbox option now serializes via markdownDescription() to a `mrkdwn` object, the second keeps the `plain_text` path.

Compatibility

Source-compatible: existing call sites all pass plain_text, and the getter's declared type only broadens (PlainTextObject → its supertype TextObject).

Testing

  • slack-api-model BlockKitTest: 55/55 green
  • slack-api-model-kotlin-extension: 58/58 green

🤖 Generated with Claude Code

@codecov

codecov Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.77%. Comparing base (dbe498c) to head (6b352a1).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #1645      +/-   ##
============================================
+ Coverage     72.74%   72.77%   +0.03%     
- Complexity     4546     4551       +5     
============================================
  Files           483      483              
  Lines         14456    14458       +2     
  Branches       1513     1513              
============================================
+ Hits          10516    10522       +6     
+ Misses         3042     3039       -3     
+ Partials        898      897       -1     
Flag Coverage Δ
jdk-14 72.77% <100.00%> (+0.03%) ⬆️

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

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

@zimeg
zimeg force-pushed the option-mrkdwn-description branch 3 times, most recently from 97d33f2 to e5f142f Compare September 10, 2026 22:18
`OptionObject.description` was hard-typed to `PlainTextObject`, so a
`mrkdwn` description on a radio-button or checkbox option was coerced to
plain_text on deserialize, losing the markdown. The option-object docs
state that radio buttons and checkboxes can use mrkdwn text objects for
the description.

Widen the field to `TextObject` (the same type already used for
`OptionObject.text`), which routes deserialization through the existing
polymorphic text-object factory so `mrkdwn` round-trips as a
`MarkdownTextObject` and `plain_text` still returns a `PlainTextObject`.
The Kotlin DSL gains a `markdownDescription(...)` overload alongside the
existing plain_text `description(...)`. Source-compatible: all call
sites pass plain_text and the getter's declared type only broadens.

Ref: https://docs.slack.dev/reference/block-kit/composition-objects/option-object

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@zimeg
zimeg force-pushed the option-mrkdwn-description branch from e5f142f to 9b52084 Compare September 10, 2026 22:23
@zimeg zimeg added enhancement M-T: A feature request for new functionality project:slack-api-model project:slack-api-model lang:kotlin semver:minor labels Sep 10, 2026
@zimeg zimeg self-assigned this Sep 10, 2026
@zimeg zimeg added this to the 1.51.1 milestone Sep 10, 2026
@zimeg zimeg changed the title Allow mrkdwn descriptions on OptionObject (fixes #1471) feat: support mrkdwn descriptions on OptionObject (#1471) Sep 10, 2026
Exercise markdownDescription() within the existing "Channel select and
checkboxes" test rather than a standalone case, mirroring the Java-side
fold into parseCheckboxes(). The first checkbox option now asserts the
mrkdwn description path while the second keeps the plain_text path.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

@zimeg zimeg left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🗣️ note: A few callouts on these changes that are worth consideration before merge I think!

Comment on lines +32 to +38
* A plain_text text object that defines a line of descriptive text shown below
* the text field beside a single selectable item in a select menu, multi-select
* menu, checkbox group, radio button group, or overflow menu. Checkbox group and
* radio button group items can also use mrkdwn formatting.
* Maximum length for the text within this field is 75 characters.
*/
private PlainTextObject description;
private TextObject description;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🤓 note: This matches reference and becomes more general to support API requests with validation left to blocks itself.

🔗 https://docs.slack.dev/reference/block-kit/composition-objects/option-object

Comment on lines 1115 to 1118
" \"description\": {\n" +
" \"type\": \"mrkdwn\",\n" +
" \"text\": \"*this is mrkdwn text*\"\n" +
" },\n" +

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

👽 note: This existed in tests before these change but wasn't checked below.

Comment on lines +62 to +64
fun markdownDescription(text: String, verbatim: Boolean? = null) {
description = MarkdownTextObject(text, verbatim)
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

👁️‍🗨️ note: This pattern is similar to how the text object is supported although I understand this isn't identical for the current description object:

  • plainText
  • markdownText

🔗 https://github.com/slackapi/java-slack-sdk/blob/dbe498ce0a2f0ed068b4bd7028ce31d22c91998d/slack-api-model-kotlin-extension/src/main/kotlin/com/slack/api/model/kotlin_extension/block/composition/dsl/TextObjectDsl.kt

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

☁️ note: Calling this out here because I'm uncertain if we're using the best pattern without introducing a break:

  • description
  • markdownDescription

Comment on lines 439 to 448
options {
option {
description("I accept the terms and conditions")
markdownDescription("*I accept the terms and conditions*")
value("tac-accept")
}
option {
description("I have read the privacy policy")
value("privacy-policy-read")
}
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🧪 note: The existing test suite was modified to check both cases alongside one another.

…Object field

The sample-JSON generator (SampleObjects) reflectively instantiates null
model fields via a no-arg constructor. Widening OptionObject.description
from PlainTextObject to the abstract TextObject broke this for the
radio-button option fixtures that set text but left description null,
crashing MethodsResponseDumpTest's static init with InstantiationException.

Supply concrete descriptions in those builders (as the generator already
does elsewhere), giving the mrkdwn option a mrkdwn description. Regenerates
the views.* API samples to show a mrkdwn option description.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

@zimeg zimeg left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🪐 A comment of test changes for stable CI.

Comment on lines +265 to +268
initProperties(OptionObject.builder().text(initProperties(PlainTextObject.builder().build())).description(initProperties(PlainTextObject.builder().build())).build()),
initProperties(OptionObject.builder().text(initProperties(MarkdownTextObject.builder().build())).description(initProperties(MarkdownTextObject.builder().build())).build())
))
.initialOption(initProperties(OptionObject.builder().text(initProperties(PlainTextObject.builder().build())).build()))
.initialOption(initProperties(OptionObject.builder().text(initProperties(PlainTextObject.builder().build())).description(initProperties(PlainTextObject.builder().build())).build()))

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🔭 note: These description values are added to tests so JSON reflections don't error when deciding between plain_text and mrkdwn values.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

👾 note: This is a test change and wouldn't require similar from developers as I understand.

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 lang:kotlin project:slack-api-model project:slack-api-model semver:minor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support description of mrkdwn type in OptionObject

1 participant