showcase/shell-docs/src/content/reference/bot/components/Button.mdx
Button is a clickable control for an Actions row. Its onClick handler is written inline in your JSX and bound by the engine: the button that reaches the platform carries only an opaque action id, and the click is routed back to your handler. Button is generic over its value prop, so the value the click carries is fully typed.
import { Button } from "@copilotkit/bot-ui";
<Actions>
<Button
style="primary"
onClick={async ({ thread }) => {
await thread.post("🚀 Shipping!");
}}
>
Ship it
</Button>
</Actions>
The clicked button's value is what thread.awaitChoice resolves to:
function ConfirmWrite({ action }: { action: string }) {
return (
<Message>
<Section>{action}</Section>
<Actions>
<Button style="primary" value={{ confirmed: true }}>Create</Button>
<Button style="danger" value={{ confirmed: false }}>Cancel</Button>
</Actions>
</Message>
);
}
const choice = await thread.awaitChoice<{ confirmed: boolean }>(
<ConfirmWrite action="Create Linear issue CPK-1234?" />,
);
Inline handlers are re-derived from the component's props after a restart. If a handler closes over data that can't be reconstructed from props, wrap it with bind().
ck:…). Only that id and the button's value cross the wire to the platform; handler code and other props never leave the process.Renders as a button element: label truncated at 75 characters (SLACK_LIMITS.buttonText), action_id capped at 255, serialized value capped at 2000 characters (SLACK_LIMITS.buttonValue). Clicks are acked within Slack's 3-second deadline, then dispatched asynchronously.