Cards and UI Components
The Chat SDK provides a unified API for creating rich cards that automatically convert to platform-specific formats:
- Slack: Block Kit
- Microsoft Teams: Adaptive Cards
- Google Chat: Card v2
You can use either JSX syntax or function calls to build cards.
JSX Syntax
To use JSX, configure your tsconfig.json:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "chat"
}
}
Then create cards with JSX:
/** @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>
);
Function API
Prefer function calls? Same result:
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" }),
]),
],
})
);
Available Components
Card
The root container for all card content.
interface CardElement {
type: "card";
title?: string;
subtitle?: string;
imageUrl?: string;
children: CardChild[];
}
Example:
<Card
title="Welcome"
subtitle="Getting started"
imageUrl="https://example.com/banner.png"
>
<Text>Hello world</Text>
</Card>
Text
Display text content with optional styling.
interface TextElement {
type: "text";
content: string;
style?: "plain" | "bold" | "muted";
}
Example:
<Text style="bold">Important message</Text>
<Text style="muted">Secondary info</Text>
Use CardText instead of Text if you need to avoid conflicts with the global DOM Text constructor.
Image
Embed images in your cards.
interface ImageElement {
type: "image";
url: string;
alt?: string;
}
Example:
<Image
url="https://example.com/chart.png"
alt="Sales chart"
/>
Divider
A visual separator between sections.
Section
Group related content together.
<Section>
<Text>Grouped content</Text>
<Image url="..." />
</Section>
Fields
Display key-value pairs in a multi-column layout.
interface FieldElement {
type: "field";
label: string;
value: string;
}
Example:
<Fields>
<Field label="Status" value="Active" />
<Field label="Priority" value="High" />
<Field label="Assignee" value="Alice" />
</Fields>
Table
Display structured data in a table format.
interface TableElement {
type: "table";
headers: string[];
rows: string[][];
align?: ("left" | "center" | "right")[];
}
Example:
<Table
headers={["Name", "Age", "Role"]}
rows={[
["Alice", "30", "Engineer"],
["Bob", "25", "Designer"],
]}
align={["left", "center", "right"]}
/>
Link
Inline hyperlink element.
<CardLink url="https://example.com" label="Visit Site" />
Complete Example
Here’s a comprehensive card showcasing multiple components:
/** @jsxImportSource chat */
import { Card, Text, Image, Divider, Fields, Field, Table, Actions, Button, LinkButton } from "chat";
await thread.post(
<Card
title="Project Status Report"
subtitle="Q1 2024"
imageUrl="https://example.com/logo.png"
>
<Text style="bold">Executive Summary</Text>
<Text>All milestones on track for Q1 delivery.</Text>
<Divider />
<Fields>
<Field label="Status" value="On Track" />
<Field label="Budget" value="$250K" />
<Field label="Team Size" value="12" />
</Fields>
<Divider />
<Text style="bold">Milestone Progress</Text>
<Table
headers={["Milestone", "Progress", "Due Date"]}
rows={[
["Design", "100%", "Jan 15"],
["Development", "75%", "Feb 28"],
["Testing", "25%", "Mar 15"],
]}
/>
<Actions>
<Button id="approve" style="primary">Approve</Button>
<Button id="comment" style="default">Add Comment</Button>
<LinkButton url="https://project.example.com" label="View Details" />
</Actions>
</Card>
);
Fallback Text
Cards automatically generate plain text fallbacks for platforms or clients that can’t render rich cards:
import { cardToFallbackText } from "chat";
const fallback = cardToFallbackText(myCard);
// Returns markdown-formatted plain text
React Integration
If you’re using React components, convert them to card elements:
import { fromReactElement } from "chat";
import React from "react";
const reactElement = (
<Card title="Hello">
<Text>World</Text>
</Card>
);
const cardElement = fromReactElement(reactElement);
await thread.post(cardElement);
Next Steps
Actions
Add interactive buttons and handle clicks
Modals
Create forms and dialog workflows