StreamingTextMarkdown class
A widget that displays streaming text with Markdown support.
This widget combines the power of markdown rendering with smooth typing animations. It supports:
- Markdown formatting (headers, bold, italic, lists)
- Character-by-character or word-by-word typing
- Customizable typing speed and animations
- RTL language support
- Auto-scrolling
- Theme support through StreamingTextTheme
Provide either text (static markdown string, the default) or stream
(a Stream<String> of chunks from an LLM API). When stream is
non-null, text is ignored entirely — the stream starts from an empty
buffer and content is appended as it emits.
Use typingSpeed to control how fast each character or word appears, and wordByWord to choose between character-by-character or word-by-word animation. For unbounded streams, prefer trailingFadeEnabled over fadeInEnabled — per-character fades are auto-disabled when stream is set to avoid spawning one AnimationController per glyph.
- Inheritance
-
- Object
- DiagnosticableTree
- Widget
- StatefulWidget
- StreamingTextMarkdown
Constructors
-
StreamingTextMarkdown({Key? key, String text = '', Stream<
String> ? stream, String initialText = '', TextStyle? styleSheet, StreamingTextTheme? theme, EdgeInsets? padding, bool autoScroll = true, bool fadeInEnabled = false, Duration fadeInDuration = const Duration(milliseconds: 300), Curve fadeInCurve = Curves.easeOut, bool wordByWord = false, int chunkSize = 1, Duration typingSpeed = const Duration(milliseconds: 50), TextDirection? textDirection, TextAlign? textAlign, bool markdownEnabled = false, bool latexEnabled = false, TextStyle? latexStyle, double latexScale = 1.0, bool? latexFadeInEnabled, StreamingTextController? controller, VoidCallback? onComplete, bool animationsEnabled = true, bool trailingFadeEnabled = false, bool isLoading = false, int shimmerLineCount = 3, Widget imageBuilder(BuildContext context, String imageUrl)?, void onLinkTap(String url, String title)?, Widget codeBuilder(BuildContext context, String name, String code, bool closed)?, Widget latexBuilder(BuildContext context, String tex, TextStyle textStyle, bool inline)?, Widget sourceTagBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget highlightBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget linkBuilder(BuildContext context, InlineSpan text, String url, TextStyle style)?, List<MarkdownComponent> ? components, List<MarkdownComponent> ? inlineComponents, MarkdownRenderOptions? markdownOptions, bool selectable = false, bool? showCursor, Color? cursorColor, String? semanticsLabel, Widget errorBuilder(BuildContext context, Object error)?, bool? completeAnimationOnTap, RevealMode? revealMode = RevealMode.smoothFade, StreamPacing? pacing}) -
Creates a streaming markdown text widget.
const
-
StreamingTextMarkdown.chatGPT({Key? key, String text = '', Stream<
String> ? stream, String initialText = '', TextStyle? styleSheet, StreamingTextTheme? theme, EdgeInsets? padding, bool autoScroll = true, TextDirection? textDirection, TextAlign? textAlign, bool markdownEnabled = true, bool latexEnabled = false, TextStyle? latexStyle, double latexScale = 1.0, bool? latexFadeInEnabled, StreamingTextController? controller, VoidCallback? onComplete, bool animationsEnabled = true, bool trailingFadeEnabled = false, bool isLoading = false, int shimmerLineCount = 3, Widget imageBuilder(BuildContext context, String imageUrl)?, void onLinkTap(String url, String title)?, Widget codeBuilder(BuildContext context, String name, String code, bool closed)?, Widget latexBuilder(BuildContext context, String tex, TextStyle textStyle, bool inline)?, Widget sourceTagBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget highlightBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget linkBuilder(BuildContext context, InlineSpan text, String url, TextStyle style)?, List<MarkdownComponent> ? components, List<MarkdownComponent> ? inlineComponents, MarkdownRenderOptions? markdownOptions, bool selectable = false, bool? showCursor, Color? cursorColor, String? semanticsLabel, Widget errorBuilder(BuildContext context, Object error)?, bool? completeAnimationOnTap, RevealMode? revealMode = RevealMode.smoothFade, StreamPacing? pacing, Duration? fadeInDuration, Curve? fadeInCurve, Duration? typingSpeed}) -
Creates a StreamingTextMarkdown with ChatGPT-style animation
Perfect for fast, character-by-character streaming like ChatGPT
const
-
StreamingTextMarkdown.claude({Key? key, String text = '', Stream<
String> ? stream, String initialText = '', TextStyle? styleSheet, StreamingTextTheme? theme, EdgeInsets? padding, bool autoScroll = true, TextDirection? textDirection, TextAlign? textAlign, bool markdownEnabled = true, bool latexEnabled = false, TextStyle? latexStyle, double latexScale = 1.0, bool? latexFadeInEnabled, StreamingTextController? controller, VoidCallback? onComplete, bool animationsEnabled = true, bool trailingFadeEnabled = false, bool isLoading = false, int shimmerLineCount = 3, Widget imageBuilder(BuildContext context, String imageUrl)?, void onLinkTap(String url, String title)?, Widget codeBuilder(BuildContext context, String name, String code, bool closed)?, Widget latexBuilder(BuildContext context, String tex, TextStyle textStyle, bool inline)?, Widget sourceTagBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget highlightBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget linkBuilder(BuildContext context, InlineSpan text, String url, TextStyle style)?, List<MarkdownComponent> ? components, List<MarkdownComponent> ? inlineComponents, MarkdownRenderOptions? markdownOptions, bool selectable = false, bool? showCursor, Color? cursorColor, String? semanticsLabel, Widget errorBuilder(BuildContext context, Object error)?, bool? completeAnimationOnTap, RevealMode? revealMode = RevealMode.smoothFade, StreamPacing? pacing, Duration? fadeInDuration, Curve? fadeInCurve, Duration? typingSpeed}) -
Creates a StreamingTextMarkdown with Claude-style animation
Perfect for smooth, word-by-word streaming like Claude
const
-
StreamingTextMarkdown.fromPreset({Key? key, String text = '', Stream<
String> ? stream, required StreamingTextConfig preset, String initialText = '', TextStyle? styleSheet, StreamingTextTheme? theme, EdgeInsets? padding, bool autoScroll = true, TextDirection? textDirection, TextAlign? textAlign, bool markdownEnabled = false, bool latexEnabled = false, TextStyle? latexStyle, double latexScale = 1.0, bool? latexFadeInEnabled, StreamingTextController? controller, VoidCallback? onComplete, bool animationsEnabled = true, bool trailingFadeEnabled = false, bool isLoading = false, int shimmerLineCount = 3, Widget imageBuilder(BuildContext context, String imageUrl)?, void onLinkTap(String url, String title)?, Widget codeBuilder(BuildContext context, String name, String code, bool closed)?, Widget latexBuilder(BuildContext context, String tex, TextStyle textStyle, bool inline)?, Widget sourceTagBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget highlightBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget linkBuilder(BuildContext context, InlineSpan text, String url, TextStyle style)?, List<MarkdownComponent> ? components, List<MarkdownComponent> ? inlineComponents, MarkdownRenderOptions? markdownOptions, bool selectable = false, bool? showCursor, Color? cursorColor, String? semanticsLabel, Widget errorBuilder(BuildContext context, Object error)?, bool? completeAnimationOnTap, RevealMode? revealMode, StreamPacing? pacing}) - Creates a StreamingTextMarkdown from a preset configuration
-
StreamingTextMarkdown.instant({Key? key, String text = '', Stream<
String> ? stream, String initialText = '', TextStyle? styleSheet, StreamingTextTheme? theme, EdgeInsets? padding, bool autoScroll = true, TextDirection? textDirection, TextAlign? textAlign, bool markdownEnabled = false, bool latexEnabled = false, TextStyle? latexStyle, double latexScale = 1.0, bool? latexFadeInEnabled, StreamingTextController? controller, VoidCallback? onComplete, bool animationsEnabled = false, bool trailingFadeEnabled = false, bool isLoading = false, int shimmerLineCount = 3, Widget imageBuilder(BuildContext context, String imageUrl)?, void onLinkTap(String url, String title)?, Widget codeBuilder(BuildContext context, String name, String code, bool closed)?, Widget latexBuilder(BuildContext context, String tex, TextStyle textStyle, bool inline)?, Widget sourceTagBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget highlightBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget linkBuilder(BuildContext context, InlineSpan text, String url, TextStyle style)?, List<MarkdownComponent> ? components, List<MarkdownComponent> ? inlineComponents, MarkdownRenderOptions? markdownOptions, bool selectable = false, bool? showCursor, Color? cursorColor, String? semanticsLabel, Widget errorBuilder(BuildContext context, Object error)?, bool? completeAnimationOnTap, RevealMode? revealMode = RevealMode.instant, StreamPacing? pacing, Duration? fadeInDuration, Curve? fadeInCurve, Duration? typingSpeed}) -
Creates a StreamingTextMarkdown with instant display
For when speed is priority over animation
const
-
StreamingTextMarkdown.typewriter({Key? key, String text = '', Stream<
String> ? stream, String initialText = '', TextStyle? styleSheet, StreamingTextTheme? theme, EdgeInsets? padding, bool autoScroll = true, TextDirection? textDirection, TextAlign? textAlign, bool markdownEnabled = false, bool latexEnabled = false, TextStyle? latexStyle, double latexScale = 1.0, bool? latexFadeInEnabled, StreamingTextController? controller, VoidCallback? onComplete, bool animationsEnabled = true, bool trailingFadeEnabled = false, bool isLoading = false, int shimmerLineCount = 3, Widget imageBuilder(BuildContext context, String imageUrl)?, void onLinkTap(String url, String title)?, Widget codeBuilder(BuildContext context, String name, String code, bool closed)?, Widget latexBuilder(BuildContext context, String tex, TextStyle textStyle, bool inline)?, Widget sourceTagBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget highlightBuilder(BuildContext context, String content, TextStyle textStyle)?, Widget linkBuilder(BuildContext context, InlineSpan text, String url, TextStyle style)?, List<MarkdownComponent> ? components, List<MarkdownComponent> ? inlineComponents, MarkdownRenderOptions? markdownOptions, bool selectable = false, bool? showCursor, Color? cursorColor, String? semanticsLabel, Widget errorBuilder(BuildContext context, Object error)?, bool? completeAnimationOnTap, RevealMode? revealMode = RevealMode.typewriter, StreamPacing? pacing, Duration? fadeInDuration, Curve? fadeInCurve, Duration? typingSpeed}) -
Creates a StreamingTextMarkdown with typewriter animation
Classic typewriter effect without fade-in
const
Properties
- animationsEnabled → bool
-
Whether animations are enabled. When false, text appears instantly.
final
- autoScroll → bool
-
Whether to scroll automatically as new text arrives
final
- chunkSize → int
-
The number of grapheme clusters revealed per animation tick when
wordByWord is
false. Ignored in word-by-word mode, where one unit is a whole word instead. A very large value (see StreamingTextMarkdown.instant) reveals effectively everything on the first tick.final - codeBuilder → Widget Function(BuildContext context, String name, String code, bool closed)?
-
Custom builder for code blocks in markdown content.
final
- completeAnimationOnTap → bool?
-
Whether tapping the widget jumps the animation to completion.
final
-
components
→ List<
MarkdownComponent> ? -
Custom block-level markdown components forwarded to
gpt_markdown'sGptMarkdown.components. Use this to override how headers, lists, bold, italic, tables, etc. are rendered. Whennull, the defaultgpt_markdowncomponent list is used.final - controller → StreamingTextController?
-
Controller for programmatic animation control
final
- cursorColor → Color?
-
Color of the blinking cursor shown while showCursor resolves to
true. Defaults to the theme's text-primary token.final - errorBuilder → Widget Function(BuildContext context, Object error)?
-
Builder invoked when stream emits an error. Receives the error
object; the text revealed so far stays on screen either way.
final
- fadeInCurve → Curve
-
The curve to use for the fade-in animation
final
- fadeInDuration → Duration
-
Duration of the fade-in animation
final
- fadeInEnabled → bool
-
Whether each character (or word, in word-by-word mode) fades in as it is
revealed. Disabled automatically for Arabic/RTL content. For stream-based
usage in StreamingText, use trailingFadeEnabled instead.
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- highlightBuilder → Widget Function(BuildContext context, String content, TextStyle textStyle)?
-
Custom builder for highlighted text in markdown content.
final
- imageBuilder → Widget Function(BuildContext context, String imageUrl)?
-
Custom builder for images in markdown content.
final
- initialText → String
-
Initial text to display before the animation starts.
final
-
inlineComponents
→ List<
MarkdownComponent> ? -
Custom inline markdown components forwarded to
gpt_markdown'sGptMarkdown.inlineComponents. Whennull, the default inline component list is used.final - isLoading → bool
-
Whether to show a shimmer skeleton placeholder instead of the text widget.
final
- key → Key?
-
Controls how one widget replaces another widget in the tree.
finalinherited
- latexBuilder → Widget Function(BuildContext context, String tex, TextStyle textStyle, bool inline)?
-
Custom builder for LaTeX expressions in markdown content.
final
- latexEnabled → bool
-
Whether to enable LaTeX rendering
final
- latexFadeInEnabled → bool?
-
Whether to enable fade-in animations for LaTeX content.
final
- latexScale → double
-
Scale factor for LaTeX equations
final
- latexStyle → TextStyle?
-
Custom style for LaTeX expressions
final
- linkBuilder → Widget Function(BuildContext context, InlineSpan text, String url, TextStyle style)?
-
Custom builder for links in markdown content.
final
- markdownEnabled → bool
-
Whether to enable markdown rendering.
final
- markdownOptions → MarkdownRenderOptions?
-
Bundles
gpt_markdown1.3 pass-throughs that don't have a dedicated top-level parameter of their own (style sheet, block/inline builders, autolink config, ...). Forwarded as-is to the inner StreamingText. See MarkdownRenderOptions.final - onComplete → VoidCallback?
-
Callback when animation completes
final
- onLinkTap → void Function(String url, String title)?
-
Callback when a link is tapped in markdown content.
final
- pacing → StreamPacing?
-
How a
Stream<String>(or static text) source is paced (DESIGN.md 4.3). Whennull, stream input defaults to StreamPacing.catchUp and static text input defaults to StreamPacing.fixed using typingSpeed.final - padding → EdgeInsets?
-
Padding around the text
final
- revealMode → RevealMode?
-
How revealed text arrives on screen (DESIGN.md section 4). Defaults to
RevealMode.smoothFade on this constructor,
.chatGPTand.claude..typewriterand.instantdefault to their own matching mode.final - runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- selectable → bool
-
Whether the rendered text can be selected by the user (wraps the
output in a
SelectionArea). Defaults tofalse.final - semanticsLabel → String?
-
Semantic label used for accessibility. When set, this label (rather
than the revealed text itself) is what's announced/exposed to
assistive technology.
final
- shimmerLineCount → int
-
Number of shimmer skeleton lines shown while isLoading is true.
Defaults to 3.
final
- showCursor → bool?
-
Whether to show a blinking cursor at the end of the text while
animating. When
null(the default), resolves tostream != null— a cursor makes sense for a live stream but not for static text.final - sourceTagBuilder → Widget Function(BuildContext context, String content, TextStyle textStyle)?
-
Custom builder for source tags in markdown content.
final
-
stream
→ Stream<
String> ? -
Optional stream of text chunks from an LLM API (OpenAI, Anthropic,
Ollama, etc.). Each emitted string is appended to the rendered text and
animated using the active typing settings. When this is non-null the
inner streaming engine takes over, text is ignored, and
per-character fadeInEnabled is suppressed automatically; use
trailingFadeEnabled for a smooth reveal.
final
- styleSheet → TextStyle?
-
Markdown style configuration: a plain TextStyle applied to the
markdown renderer as its base text style. Distinct from
MarkdownRenderOptions.styleSheet (in markdownOptions), which is a
gpt_markdownGptMarkdownStyleSheetfor per-component styling (headings, tables, block quotes, etc.).final - text → String
-
The text to display. Ignored when stream is also provided — the
stream starts from an empty buffer, not from text.
final
- textAlign → TextAlign?
-
The text alignment
final
- textDirection → TextDirection?
-
The text direction
final
- theme → StreamingTextTheme?
-
Custom theme for the widget
final
- trailingFadeEnabled → bool
-
Whether to show a trailing gradient fade at the bottom edge while text is
streaming. The fade animates away when streaming completes (using
fadeInDuration / fadeInCurve for the dismiss animation). Recommended
for stream-based usage and works with markdown + RTL content.
Defaults to
false.final - typingSpeed → Duration
-
The speed at which each character or word appears
final
- wordByWord → bool
-
Whether to stream text word by word instead of character by character
final
Methods
-
createElement(
) → StatefulElement -
Creates a StatefulElement to manage this widget's location in the tree.
inherited
-
createState(
) → State< StreamingTextMarkdown> -
Creates the mutable state for this widget at a given location in the tree.
override
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children.
inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node.
inherited
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toDiagnosticsNode(
{String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by DiagnosticsNode.toStringDeep.
inherited
-
toString(
{DiagnosticLevel minLevel = DiagnosticLevel.info}) → String -
A string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String -
Returns a string representation of this node and its descendants.
inherited
-
toStringShallow(
{String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String -
Returns a one-line detailed description of the object.
inherited
-
toStringShort(
) → String -
A short, textual description of this widget.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited