Skip to main content
Card components provide a cross-platform way to create rich, interactive messages. They automatically convert to:
  • Slack: Block Kit
  • Teams: Adaptive Cards
  • Google Chat: Card v2

Usage

Cards support both function calls and JSX syntax.

Function API

import { Card, Text, Actions, Button } from "chat";

await thread.post(
  Card({
    title: "Order #1234",
    children: [
      Text("Total: $50.00"),
      Actions([
        Button({ id: "approve", label: "Approve", style: "primary" }),
        Button({ id: "reject", label: "Reject", style: "danger" })
      ])
    ]
  })
);

JSX API

Requires jsxImportSource: "chat" in tsconfig.json.
/** @jsxImportSource chat */
import { Card, Text, Actions, Button } from "chat";

await thread.post(
  <Card title="Order #1234">
    <Text>Total: $50.00</Text>
    <Actions>
      <Button id="approve" style="primary">Approve</Button>
      <Button id="reject" style="danger">Reject</Button>
    </Actions>
  </Card>
);

Card

Root container for card content.
title
string
Card title (displayed as header)
subtitle
string
Card subtitle (displayed below title)
imageUrl
string
Header image URL
children
CardChild[]
Card content elements

CardOptions Type

interface CardOptions {
  title?: string;
  subtitle?: string;
  imageUrl?: string;
  children?: CardChild[];
}

function Card(options: CardOptions): CardElement;

Text

Text content element.
content
string
required
Text content (supports markdown on some platforms)
style
'plain' | 'bold' | 'muted'
Text style
function Text(
  content: string,
  options?: { style?: "plain" | "bold" | "muted" }
): TextElement;

// Alias that avoids DOM Text constructor conflict
const CardText = Text;
Example:
Text("Hello, world!")
Text("Important", { style: "bold" })
Text("Note", { style: "muted" })

Image

Image element.
url
string
required
Image URL
alt
string
Alt text for accessibility
function Image(options: { url: string; alt?: string }): ImageElement;
Example:
Image({ url: "https://example.com/image.png", alt: "Description" })

Divider

Visual divider/separator.
function Divider(): DividerElement;
Example:
Card({
  children: [
    Text("Section 1"),
    Divider(),
    Text("Section 2")
  ]
})

Section

Container for grouping elements.
function Section(children: CardChild[]): SectionElement;
Example:
Section([
  Text("Grouped content"),
  Image({ url: "..." })
])

Actions

Container for buttons and selects.
function Actions(
  children: (
    | ButtonElement
    | LinkButtonElement
    | SelectElement
    | RadioSelectElement
  )[]
): ActionsElement;
Example:
Actions([
  Button({ id: "ok", label: "OK" }),
  Button({ id: "cancel", label: "Cancel" }),
  LinkButton({ url: "https://example.com", label: "Learn More" })
])

Button

Interactive button that triggers an action.
id
string
required
Unique action ID for callback routing
label
string
required
Button label text
style
'primary' | 'danger' | 'default'
Visual style
value
string
Optional payload value sent with action callback
disabled
boolean
If true, button is displayed inactive and doesn’t respond to clicks
interface ButtonOptions {
  id: string;
  label: string;
  style?: "primary" | "danger" | "default";
  value?: string;
  disabled?: boolean;
}

function Button(options: ButtonOptions): ButtonElement;
Example:
Button({ id: "submit", label: "Submit", style: "primary" })
Button({ id: "delete", label: "Delete", style: "danger", value: "item-123" })
Button({ id: "unavailable", label: "Unavailable", disabled: true })

LinkButton

Button that opens a URL when clicked.
url
string
required
URL to open when clicked
label
string
required
Button label text
style
'primary' | 'danger' | 'default'
Visual style
interface LinkButtonOptions {
  url: string;
  label: string;
  style?: "primary" | "danger" | "default";
}

function LinkButton(options: LinkButtonOptions): LinkButtonElement;
Example:
LinkButton({ url: "https://example.com", label: "View Docs" })
LinkButton({ url: "https://example.com", label: "Learn More", style: "primary" })

Field

Key-value pair for displaying structured data.
label
string
required
Field label
value
string
required
Field value
function Field(options: { label: string; value: string }): FieldElement;
Example:
Field({ label: "Status", value: "Active" })

Fields

Container for multi-column field layout.
function Fields(children: FieldElement[]): FieldsElement;
Example:
Fields([
  Field({ label: "Name", value: "John" }),
  Field({ label: "Email", value: "[email protected]" }),
  Field({ label: "Status", value: "Active" })
])

Table

Structured data table.
headers
string[]
required
Column header labels
rows
string[][]
required
Data rows (each row is an array of cell strings)
align
('left' | 'center' | 'right')[]
Column alignment
interface TableOptions {
  headers: string[];
  rows: string[][];
  align?: ("left" | "center" | "right")[];
}

function Table(options: TableOptions): TableElement;
Example:
Table({
  headers: ["Name", "Age", "Role"],
  rows: [
    ["Alice", "30", "Engineer"],
    ["Bob", "25", "Designer"]
  ],
  align: ["left", "right", "left"]
})
Inline hyperlink element.
url
string
required
URL to link to
label
string
required
Link label text
function CardLink(options: { url: string; label: string }): LinkElement;
Example:
CardLink({ url: "https://example.com", label: "Visit Site" })

Complete Example

import { Card, Text, Image, Divider, Fields, Field, Actions, Button, LinkButton } from "chat";

await thread.post(
  Card({
    title: "Order Confirmation",
    subtitle: "Order #1234",
    imageUrl: "https://example.com/product.png",
    children: [
      Text("Your order has been received", { style: "bold" }),
      Divider(),
      Fields([
        Field({ label: "Item", value: "Widget Pro" }),
        Field({ label: "Quantity", value: "2" }),
        Field({ label: "Total", value: "$50.00" })
      ]),
      Divider(),
      Actions([
        Button({ id: "track", label: "Track Order", style: "primary" }),
        Button({ id: "cancel", label: "Cancel", style: "danger" }),
        LinkButton({ url: "https://example.com/help", label: "Help" })
      ])
    ]
  })
);

Type Definitions

type CardChild =
  | TextElement
  | ImageElement
  | DividerElement
  | ActionsElement
  | SectionElement
  | FieldsElement
  | LinkElement
  | TableElement;

interface CardElement {
  type: "card";
  title?: string;
  subtitle?: string;
  imageUrl?: string;
  children: CardChild[];
}

interface TextElement {
  type: "text";
  content: string;
  style?: "plain" | "bold" | "muted";
}

interface ButtonElement {
  type: "button";
  id: string;
  label: string;
  style?: "primary" | "danger" | "default";
  value?: string;
  disabled?: boolean;
}