Chat UI and theming
KletsoLauncher, KletsoChat, opening as a sheet or full screen, conversation list, KletsoTheme from your dashboard branding, dark mode.
Launcher
Scaffold(floatingActionButton: KletsoLauncher())
KletsoLauncher({client, presentation = sheet, icon, tooltip = 'Chat with us', onPressed}). Shows an unread dot when an assistant message completes while the chat is closed. Colours and size come from KletsoTheme (primary, onPrimary, launcherSize).
Opening the chat
await Kletso.instance.open(context); // bottom sheet
await Kletso.instance.open(context, presentation: KletsoPresentation.fullscreen);
Kletso.instance.close(); // from anywhere
- Sheet: a modal bottom sheet at 90% height on phones; on screens wider than 720 px it docks bottom-right at 420×640 with rounded corners.
- Fullscreen: a
MaterialPageRoutewithfullscreenDialog: true.
open is a no-op while the chat is already open (client.ui.isOpen). close works for user taps and for server commands.
Embedding
const KletsoChat(showHeader: true, composerHint: 'Message…')
KletsoChat({client, theme, markdownRenderer, showHeader, onClose, emptyStateText, composerHint}) is the whole chat: header with agent name and status, connection banner, reverse message list with streaming bubbles, tool-call chips, rendered surfaces, typing dots, a “new messages” pill and the composer. Put it in a tab, a drawer or a page.
Other widgets: KletsoConversationList (the user’s conversations plus a “new conversation” row), KletsoSurfaceView(surface: …) (render one surface anywhere, for previews or a home-screen card), KletsoChatHeader, KletsoComposer, KletsoConnectionBanner, KletsoBotBubble, KletsoUserBubble, KletsoToolCallChip.
Markdown
Assistant text is rendered with KletsoPlainMarkdownRenderer (bold, italics, lists, links, inline code; zero dependencies so Wasm builds stay clean). Implement KletsoMarkdownRenderer to plug in your own renderer.
Theming
KletsoTheme is a ThemeExtension. Add it to your ThemeData and every Kletso widget picks it up:
final kletsoTheme = KletsoTheme.fromServer(Kletso.instance.session.value!.theme);
MaterialApp(
theme: ThemeData(extensions: [kletsoTheme]),
darkTheme: ThemeData(brightness: Brightness.dark, extensions: [KletsoTheme.dark()]),
)
| Factory | Use |
|---|---|
KletsoTheme.light() / .dark() | Kletso defaults (Dutch Orange, Deep Navy, Cream; Plus Jakarta Sans bundled) |
KletsoTheme.forBrightness(b) | Pick by brightness |
KletsoTheme.fromServer(json, base:) | Apply the branding configured in Settings → Widget branding, delivered in the session bootstrap: primary, onPrimary, surface, background, text, textMuted, radius, fontFamily, launcher.position |
KletsoTheme.of(context) | Lookup; falls back to brightness defaults, never throws |
useHostFont: true | Inherit your app’s font instead of the bundled one |
Fields you can copyWith: colours (primary, primaryHover, primarySoft, surface, background, text, textMuted, line, bubbleUser, bubbleBot, success, warning, error, info and their soft variants), radii (radiusSm, radiusMd, radiusLg, radiusPill), text styles (title, subtitle, body, caption, code), launcherPosition, launcherSize.
theme.materialTheme(hostTheme) returns a ThemeData tuned to the Kletso palette if you want the chat route to follow it fully.