BlockKit component
The public API is exactly what the package entry exports. Deep imports are unsupported. This page covers the components; validation helpers are on the validation page and exported types on the types page.
<BlockKit />
Renders a full payload: parses string input, applies the theme, provides
context, and dispatches every block. Import react-blockkit/styles.css once
from the host application's global entry; importing the component does not
load CSS automatically.
import { BlockKit, type BlockKitAction, type BlockKitInput } from "react-blockkit";
export function handleAction(action: BlockKitAction) {
console.log(action);
}
export function Preview({ payload }: { payload: BlockKitInput }) {
return <BlockKit data={payload} theme="dark" onAction={handleAction} />;
}| Prop | Type | Default | Description |
|---|---|---|---|
data | BlockKitInput | required | Payload object, block array, or JSON string; rendering does not run strict validation |
theme | "light" | "dark" | "light" | Color theme; also sets color-scheme for native controls |
surface | "message" | "modal" | "home" | "message" | Slack's per-surface presentation (control sizes, block rhythm, actions layout) plus data-surface; does not validate or filter |
onAction | (action: BlockKitAction) => void | — | Receives local interactions from supported elements with an action_id; workflow_button renders but does not emit |
resolvers | BlockKitResolvers | — | Maps user/channel/usergroup/team IDs, emoji, and dates to display values; imageSize supplies image-block byte counts |
className | string | — | Appended to the root element's class list |
aria-label | string | "Slack Block Kit preview" | Accessible name for the root role="article" element |
A string data that fails JSON.parse throws BlockKitInvariantError with
code: "invalid_json". Unknown discriminators render labeled fallbacks; see
Unknown blocks and fallbacks.
<BlockKitProvider />
Supplies surface, resolvers, and the action handler to composed blocks.
<BlockKit /> uses it internally; you only need it when rendering block or
element components directly.
| Prop | Type | Default |
|---|---|---|
children | ReactNode | required |
surface | BlockKitSurface | "message" |
onAction | (action: BlockKitAction) => void | — |
resolvers | BlockKitResolvers | — |
There is no theme prop here. Theming belongs to the <BlockKit /> root.
The useBlockKitContext() hook exposes the current context value to custom
components. Built-in block components do not branch on the context's
surface.
Block components
Every block type has a standalone component. All of them share one props shape:
import type { BlockComponentProps, SectionBlockData } from "react-blockkit";
// block, optional className, optional path for nested composition
export type SectionProps = BlockComponentProps<SectionBlockData>;| Component | Renders |
|---|---|
Block | Any typed RenderableBlock; runtime dispatch falls back on unknown types |
ActionsBlock | actions |
AlertBlock | alert |
CardBlock | card |
CarouselBlock | carousel |
ContainerBlock | container (including collapsible state) |
ContextBlock | context |
ContextActionsBlock | context_actions |
DataTableBlock | data_table |
DataVisualizationBlock | data_visualization (pie, bar, line, area) |
DividerBlock | divider |
FileBlock | file |
HeaderBlock | header (semantic h1–h4 via level) |
ImageBlock | image |
InputBlock | input, including message-surface previews |
MarkdownBlock | markdown |
PlanBlock | plan |
RichTextBlock | rich_text |
SectionBlock | section (text, fields, accessory) |
TableBlock | table (plus TableCell for individual cells) |
TaskCardBlock | task_card |
VideoBlock | video |
Element components
Elements take the Slack object as element. Action-capable components also
accept the enclosing blockId, which is copied into emitted actions.
| Component | Renders | Additional optional props |
|---|---|---|
InteractiveElement | Any interactive element; runtime dispatch falls back on unknown types | className, blockId, path |
ButtonElement | button | className, blockId |
SelectElement | All static/external/users/channels/conversations selects and their multi_* variants | className, blockId |
OverflowElement | overflow | className, blockId |
ChoiceGroup | checkboxes and radio_buttons | className, blockId |
InputElement | Text, email, URL, and number inputs; date/time/datetime pickers; file and rich-text inputs | className, blockId, path |
ImageElement | image elements and accessories | className, variant |
variant is "accessory", "cardHero", "cardIcon", or "context".
path is for nested renderer composition; it does not validate the element.
Text primitives
| Export | Role |
|---|---|
Text | Renders a TextObject, mrkdwn or plain text |
Mrkdwn | Renders a mrkdwn string (formatting, links, mentions, emoji, dates) |
RichText | Renders rich_text block elements |
Markdown | Renders CommonMark and GFM from its markdown prop |
tokenizeMrkdwn | (text: string) => readonly MrkdwnToken[]; the mrkdwn tokenizer, usable without React |
tokenizeMarkdown | A flat compatibility tokenizer; not the CommonMark/GFM render tree |
The four text models and their non-interchangeable syntax are covered in Markdown and mrkdwn.
StyleX themes
tokens, lightTheme, and darkTheme export the renderer's StyleX variable
group and themes for apps that also build with StyleX. CSS-only consumers
never need them, because the precompiled react-blockkit/styles.css already
contains both.
Accessibility
The root is a role="article" with a configurable accessible name. Blocks use
native list, table, link, image, and form semantics where the current preview
supports them. See Accessibility
for the exact behavior and known limitations before using interactive previews
as application UI.