#Cards
Cards are interactive rich messages. Each platform adapter converts the SDK's abstract card model into its native format (Block Kit, Inline Keyboard, Embed, etc.).
#Creating a Card
use BootDesk\ChatSDK\Core\Cards\Card;
use BootDesk\ChatSDK\Core\Cards\Button;
$card = Card::make()
->header('Special Offer')
->section(fn ($s) => $s->text('50% off today only!'))
->image('https://example.com/banner.jpg')
->actions([
Button::primary('Shop Now', 'action_shop'),
Button::secondary('Dismiss', 'action_dismiss'),
]);
#Card Elements
#Header
$card->header('Title');
#Sections
$card->section(function (Section $s) {
$s->text('Description text');
$s->field('Key', 'Value');
});
#Text
$card->text('Plain text');
$card->text('**Bold text**', TextStyle::Markdown);
#Images
$card->image('https://example.com/photo.jpg', 'Alt text');
#Tables
$card->table(
headers: ['Name', 'Status'],
rows: [
['Alice', '✅'],
['Bob', '❌'],
],
);
Slack limits: Native tables support up to 100 rows and 20 columns. Beyond that, the adapter falls back to an ASCII-rendered table in a code block (subject to Slack's 3000 char mrkdwn limit). Only one native table per message — subsequent tables render as ASCII.
#Buttons
$card->actions([
Button::primary('Label', 'action_id'),
Button::secondary('Label', 'action_id'),
Button::danger('Delete', 'action_delete'),
]);
Button::link('Website', 'https://example.com');
#Dividers
$card->divider();
#Sending a Card
$thread->post(PostableMessage::card($card));
#Button Action Href
Buttons can include a fallback URL for platforms that don't support native buttons:
Button::primary('View', 'action_view', actionHref: 'https://example.com');
Button::link('Open', 'https://example.com');
When actionHref is set and the adapter renders as plain text (e.g., GitHub, Linear), it renders as a markdown link. Otherwise, the platform's native button format is used.