flutter_ai_elements

The batteries-included AI chat UI kit for Flutter — drop in a polished, streaming chat in one widget, or compose 30+ themeable pieces yourself.

flutter_ai_elements: a streaming answer with chain-of-thought and a generative-UI task card

flutter_ai_elements on pub.dev pub points License: BSD-3-Clause

Family: flutter_ai · core · client · openai · anthropic · gemini · tools · mcp · voice
Recipes · Migrating from the Vercel AI SDK


Streaming response
Streaming response
AiChat · AiResponse · AiLoader
Generative UI task card
Generative UI
AiMessageBubble (custom DataPart renderers)
Tool calls
Tool calls
AiToolGroup · AiReasoning
Source citations
Citations
AiSources · AiInlineCitation
Theming
Theming
AiThemeExtension tokens
Dark mode
Dark mode
One theme extension, light & dark

Composable, themeable Flutter UI for AI chat — the UI layer of the flutter_ai family.

It adopts the Vercel AI Elements component vocabulary but renders through a mobile-first AiThemeExtension, built from base Flutter widgets. No shadcn_flutter / forui dependency, no hardcoded Material or Cupertino look — restyle everything via theme tokens.

Widgets

Presentational (plain data + callbacks; reusable, testable):

  • AiMessageBubble — renders one message's parts (text, reasoning, tool calls, results, files, sources, data), role-aware, with streaming-safe semantics.
  • AiConversationView — a scrolling list of bubbles, optional thinking loader.
  • AiComposer — the presentational input: a leading attach (+) button and a main button that is Live while empty, Send once you type, and Stop while streaming; emits haptics. Use this only if you're wiring callbacks yourself.
  • AiLoader — a pulsing three-dot thinking indicator.

Controller-bound (wire to a UseChatController — what you usually want):

  • AiChatView — the batteries-included one-widget chat: transcript + composer + layout. The fastest way to drop in a full chat.
  • AiChat — live transcript with auto-scroll and a thinking loader.
  • AiPromptInput — the drop-in composer: wraps AiComposer and wires it to sendText / stop. Prefer this over AiComposer.

Quick start

import 'package:flutter/material.dart';
import 'package:flutter_ai_elements/flutter_ai_elements.dart';

class ChatScreen extends StatelessWidget {
  const ChatScreen({super.key, required this.controller});
  final UseChatController controller; // from flutter_ai_client

  @override
  Widget build(BuildContext context) => Scaffold(
        // Batteries-included: transcript + composer + layout in one widget.
        body: AiChatView(controller: controller),
      );
}

Need a custom layout between the transcript and composer? Compose the pieces yourself instead:

Scaffold(
  body: Column(
    children: [
      Expanded(child: AiChat(controller: controller)),
      AiPromptInput(controller: controller),
    ],
  ),
);

Theming

Register an AiThemeExtension (or override the default) on your ThemeData:

MaterialApp(
  theme: ThemeData(
    extensions: [
      AiThemeExtension.fallback().copyWith(
        userBubbleColor: const Color(0xFF7C3AED),
        bubbleRadius: const BorderRadius.all(Radius.circular(28)),
        enableHaptics: true,
      ),
    ],
  ),
  home: const ChatScreen(...),
);

Widgets read tokens via AiThemeExtension.of(context), falling back to the mobile-first default when none is registered. All visual constants live behind this one extension, so a future flutter_ai_design_system can extract them without breaking the API.

Rich text

Markdown renders by default — headings, lists, bold/italic, links, and fenced code blocks — via MarkdownTextRenderer, so streamed answers format themselves out of the box. Text flows through an injectable AiTextRenderer (TextRenderer<Widget>), so you can swap in PlainTextRenderer for raw text, or your own renderer for LaTeX or custom syntax highlighting:

// Markdown is the default — this line is optional.
AiChat(controller: controller, textRenderer: const MarkdownTextRenderer());

// Opt out to plain text, or bring your own.
AiChat(controller: controller, textRenderer: const PlainTextRenderer());

Status

Published on pub.dev (see the CHANGELOG); depends on the sibling flutter_ai packages. See example/ for a full app.

If flutter_ai saves you time, you can buy me a coffee ☕.

Libraries

flutter_ai_elements
Composable, themeable Flutter UI for AI chat.