---
title: Cards
description: Send rich interactive cards with buttons, fields, and images across all platforms.
type: guide
prerequisites:
  - /docs/usage
related:
  - /docs/actions
  - /docs/modals
---

# Cards



Cards let you send structured, interactive messages that render natively on each platform — Block Kit on Slack, Adaptive Cards on Teams, and Google Chat Cards.

## Setup

Configure your `tsconfig.json` to use the Chat SDK JSX runtime:

```json title="tsconfig.json"
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "chat"
  }
}
```

Or use a per-file pragma:

```tsx title="lib/bot.tsx"
/** @jsxImportSource chat */
```

## Basic card

```tsx title="lib/bot.tsx" lineNumbers
import { Card, CardText, Button, Actions } from "chat";

await thread.post(
  <Card title="Order #1234">
    <CardText>Your order has been received!</CardText>
    <Actions>
      <Button id="approve" style="primary">Approve</Button>
      <Button id="reject" style="danger">Reject</Button>
    </Actions>
  </Card>
);
```

## Components

### Card

The top-level container. Accepts `title` and optional `subtitle`.

```tsx title="lib/bot.tsx" lineNumbers
<Card title="My Card" subtitle="Optional subtitle">
  {/* children */}
</Card>
```

### CardText

Renders formatted text. Supports a subset of markdown.

```tsx title="lib/bot.tsx" lineNumbers
<CardText>**Bold** and _italic_ text</CardText>
<CardText style="bold">Bold section header</CardText>
```

<Callout type="info">
  Use `CardText` instead of `Text` when using JSX to avoid conflicts with React's built-in types.
</Callout>

### Section

Groups related content together.

```tsx title="lib/bot.tsx" lineNumbers
<Section>
  <CardText>Section content here</CardText>
</Section>
```

### Fields

Renders key-value pairs in a compact layout.

```tsx title="lib/bot.tsx" lineNumbers
<Fields>
  <Field label="Name" value="John Doe" />
  <Field label="Role" value="Developer" />
  <Field label="Team" value="Platform" />
</Fields>
```

### Button

An action button that triggers an `onAction` handler.

```tsx title="lib/bot.tsx" lineNumbers
<Button id="approve" style="primary">Approve</Button>
<Button id="reject" style="danger">Reject</Button>
<Button id="details">View Details</Button>
```

The `id` maps to your `onAction` handler. Optional `value` passes extra data:

```tsx title="lib/bot.tsx"
<Button id="report" value="bug">Report Bug</Button>
```

### CardLink

Inline hyperlink rendered as text. Unlike `LinkButton` (which must be inside `Actions`), `CardLink` can be placed directly in a card alongside other content.

```tsx title="lib/bot.tsx"
<CardLink url="https://example.com/order/1234" label="View order details" />
```

Or with children as the label:

```tsx title="lib/bot.tsx"
<CardLink url="https://example.com/docs">Read the docs</CardLink>
```

<Callout type="info">
  `CardLink` renders as a platform-native link: `<url|label>` on Slack, `[label](url)` on Teams/Discord/GitHub/Linear, and `<a href>` on Google Chat.
</Callout>

### LinkButton

Opens an external URL. No `onAction` handler needed.

```tsx title="lib/bot.tsx"
<LinkButton url="https://example.com/order/1234">View Order</LinkButton>
```

### Actions

Container for buttons and interactive elements.

```tsx title="lib/bot.tsx" lineNumbers
<Actions>
  <Button id="approve" style="primary">Approve</Button>
  <Button id="reject" style="danger">Reject</Button>
  <LinkButton url="https://example.com">View</LinkButton>
</Actions>
```

### Select

Inline dropdown menu.

```tsx title="lib/bot.tsx" lineNumbers
<Actions>
  <Select id="priority" label="Priority" placeholder="Select priority">
    <SelectOption label="High" value="high" description="Urgent tasks" />
    <SelectOption label="Medium" value="medium" />
    <SelectOption label="Low" value="low" />
  </Select>
</Actions>
```

Selection triggers an `onAction` handler with the `id` as the `actionId` and the selected value.

### RadioSelect

Radio button group for mutually exclusive choices.

```tsx title="lib/bot.tsx" lineNumbers
<Actions>
  <RadioSelect id="status" label="Status">
    <SelectOption label="Open" value="open" />
    <SelectOption label="In Progress" value="in_progress" />
    <SelectOption label="Done" value="done" />
  </RadioSelect>
</Actions>
```

### Table

Structured data display with column headers and rows. Renders as a native table on platforms that support it (Teams, GitHub, Linear) and as padded ASCII text elsewhere.

```tsx title="lib/bot.tsx" lineNumbers
<Table
  headers={["Name", "Age", "Role"]}
  rows={[
    ["Alice", "30", "Engineer"],
    ["Bob", "25", "Designer"],
  ]}
/>
```

Optional column alignment:

```tsx title="lib/bot.tsx"
<Table
  headers={["Name", "Amount"]}
  rows={[["Alice", "$100"], ["Bob", "$200"]]}
  align={["left", "right"]}
/>
```

### Image

Embeds an image in the card.

```tsx title="lib/bot.tsx"
<Image url="https://example.com/screenshot.png" alt="Screenshot" />
```

### Divider

A visual separator between sections.

```tsx title="lib/bot.tsx" lineNumbers
<CardText>Above the line</CardText>
<Divider />
<CardText>Below the line</CardText>
```

## Full example

```tsx title="lib/bot.tsx" lineNumbers
import {
  Card, CardText, CardLink, Button, LinkButton, Actions,
  Section, Fields, Field, Divider, Image,
  Select, SelectOption, RadioSelect,
} from "chat";

await thread.post(
  <Card title="User Profile" subtitle="Account details">
    <Image url="https://example.com/avatar.png" alt="User avatar" />
    <Fields>
      <Field label="Name" value="Jane Smith" />
      <Field label="Role" value="Engineer" />
      <Field label="Team" value="Platform" />
    </Fields>
    <CardLink url="https://example.com/profile/123">View full profile</CardLink>
    <Divider />
    <Section>
      <CardText>Select an action below to manage this profile.</CardText>
    </Section>
    <Actions>
      <Select id="role" label="Change Role" placeholder="Select role">
        <SelectOption label="Engineer" value="engineer" />
        <SelectOption label="Manager" value="manager" />
        <SelectOption label="Admin" value="admin" />
      </Select>
      <Button id="edit" style="primary">Edit Profile</Button>
      <Button id="deactivate" style="danger">Deactivate</Button>
      <LinkButton url="https://example.com/profile/123">View Full Profile</LinkButton>
    </Actions>
  </Card>
);
```
