Code block
Fenced code on its own ground — built-in synchronous highlighting, a header label, and a copy affordance that reports intent.
FlowCodeBlock renders a fenced snippet on its own washed ground, under a
header that names the content and offers copy. Highlighting is built in
and synchronous — no setup call, no assets, nothing async. language
picks a rule table (Dart, JSON, JavaScript/TypeScript, Python, shell,
YAML, HTML, CSS and SQL ship in the box); unknown ids render plain,
never an error. Token inks come from the theme’s FlowSyntaxColors, so
code recolors with the rest of the palette in both themes.
In a message, code arrives as a FlowCodePart and FlowMessage renders
the block for you — copy intent surfaces on FlowThread.onCodeCopy with
the part in hand.
FlowCodeBlock( code: source, language: 'dart', filename: 'point.dart', copyTooltip: 'Copy code', copied: copied, onCopy: () async { await Clipboard.setData(ClipboardData(text: source)); setState(() => copied = true); // Hold `copied` for a beat, then clear it — the affordance shows a // primary-tinted check for as long as the host says so. },)Keys read apart from string values, and long lines scroll horizontally
inside the block (wrap: true wraps them instead):
FlowCodeBlock( code: payload, language: 'json', filename: 'screen.json', copyTooltip: 'Copy code', onCopy: () => copy(payload),)No language — or one the registry doesn’t know — renders plain ink;
the header can still carry a filename:
FlowCodeBlock( code: log, filename: 'build.log', copyTooltip: 'Copy', onCopy: () => copy(log),)Streaming
Section titled “Streaming”While isStreaming is true the copy affordance hides — there is nothing
complete to copy — and each delivery renders whole, with no per-character
reveal (streamed code arrives re-highlighted as often as appended, which
a reveal would restart on). In a thread this is automatic while the
message streams:
FlowThread( messages: messages, codeCopyTooltip: 'Copy code', copiedCodePart: copiedPart, onCodeCopy: (part) async { await Clipboard.setData(ClipboardData(text: part.code)); setState(() => copiedPart = part); },)Languages
Section titled “Languages”Resolution is by id or alias, case-insensitive, and anything unknown
renders plain — a rust fence degrades gracefully rather than erroring:
| Language | id | Aliases |
|---|---|---|
| Dart | dart |
— |
| JSON | json |
jsonc |
| JavaScript / TypeScript | javascript |
js, jsx, typescript, ts, tsx |
| Python | python |
py |
| Shell | bash |
sh, shell, zsh |
| YAML | yaml |
yml |
| HTML | html |
xml |
| CSS | css |
scss, less |
| SQL | sql |
mysql, postgres, postgresql, sqlite |
| Plain | plain |
text, txt |
YAML, for one, knows that on: is a key before it is a boolean:
The registry is host-extensible. FlowCodeLanguage is an ordered rule
table — earlier rules win, so comments and strings come first — and
register makes it resolvable from every block. A table like SQL’s,
whose keywords come in either case, sets caseSensitive: false:
FlowCodeLanguage.register( const FlowCodeLanguage( id: 'lisp', rules: [ FlowSyntaxRule(FlowSyntaxToken.comment, r';[^\n]*'), FlowSyntaxRule(FlowSyntaxToken.string, r'"(?:\\.|[^"\\])*"'), FlowSyntaxRule(FlowSyntaxToken.punctuation, r'[()]+'), ], ),);Theming
Section titled “Theming”Token inks are theme tokens. Install a FlowSyntaxColors on the theme to
recolor them; the code face is Google Sans Code, fetched through google_fonts, and
swaps via the typography:
FlowTheme( colors: FlowColors.light, syntax: FlowSyntaxColors.light.copyWith(keyword: myBrandAccent), typography: FlowTypography.standard.withCodeFontFamily('JetBrainsMono'),)Restyling
Section titled “Restyling”FlowCodeBlockStyle overrides the block’s chrome without touching the
global tokens: backgroundColor (transparent lets the code sit on the
host’s own surface), borderColor (transparent renders it borderless),
hoverBorderColor, headerStyle, and codeStyle (both merged over
their defaults). Token inks inside the code stay with the theme’s
FlowSyntaxColors. Install one on FlowTheme.codeBlockStyle for every
block — markdown fences included; the widget’s style wins field by
field.
Key API
Section titled “Key API”FlowCodeBlock—code,language(id or alias, case-insensitive),filename(header label; falls back tolanguage),onCopy/copied/copyTooltip(intent out, host-owned confirmation),isStreaming,wrap, pluspaddingandborderRadiusover the design’s 16/12 inset and 12px corner. The code is selectable: on its own the block hosts its own selection; in a thread it joins the thread’s, so a drag from the prose above runs straight through it, or stays unselectable when the thread opted out; the header label never selects.FlowCodePart—code,language,filename; rendered byFlowMessage, skipped in system messages.FlowThread/FlowMessage—onCodeCopy(handed the tapped part),copiedCodePart(pass the instance back while the confirmation lasts),codeCopyTooltip.FlowCodeLanguage—find,register,caseSensitive, and the built-ins (dart,json,javascript,python,bash,yaml,html,css,sql,plain);FlowSyntaxRulepairs a regex with aFlowSyntaxToken.FlowSyntaxColors— eight token roles with light and dark presets, onFlowTheme.syntax.