From 81244a50a6d59a89499103f643041cce3ae3b367 Mon Sep 17 00:00:00 2001 From: Divyanshu Bhargava Date: Thu, 20 Aug 2026 22:09:46 +0530 Subject: [PATCH] refactor: rename FlowChatScreen to FlowChatView --- AGENTS.md | 2 +- CHANGELOG.md | 5 +++++ CLAUDE.md | 2 +- README.md | 6 +++--- docs/astro.config.mjs | 4 ++++ .../{chat-screen.mdx => chat-view.mdx} | 12 ++++++------ docs/src/content/docs/components/error-state.mdx | 4 ++-- docs/src/content/docs/components/greeting.mdx | 4 ++-- .../content/docs/components/message-thread.mdx | 2 +- docs/src/content/docs/components/suggestions.mdx | 2 +- docs/src/content/docs/index.mdx | 4 ++-- docs/src/content/docs/roadmap.md | 2 +- example/lib/main.dart | 2 +- lib/flow_ui.dart | 2 +- ...flow_chat_screen.dart => flow_chat_view.dart} | 16 ++++++++-------- lib/src/widgets/flow_error_state.dart | 2 +- lib/src/widgets/flow_greeting.dart | 2 +- lib/src/widgets/flow_message.dart | 2 +- lib/src/widgets/flow_thread.dart | 2 +- playground/lib/src/demo_registry.dart | 2 +- playground/lib/src/demos/full_chat_demo.dart | 4 ++-- playground/lib/src/demos/thread_demo.dart | 2 +- 22 files changed, 47 insertions(+), 38 deletions(-) rename docs/src/content/docs/components/{chat-screen.mdx => chat-view.mdx} (87%) rename lib/src/widgets/{flow_chat_screen.dart => flow_chat_view.dart} (97%) diff --git a/AGENTS.md b/AGENTS.md index ddf11e6..f214d3f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -93,6 +93,6 @@ Status legend: ⬜ Todo · ✅ Done | # | Component | Variants / notes | Status | |---|-----------|------------------|--------| -| 24 | Chat Screen | centred 760 rail; zero state (greeting, lifted composer, starters); jump to latest | ✅ | +| 24 | Chat View | centred 760 rail; zero state (greeting, lifted composer, starters); jump to latest | ✅ | | 25 | SidePanel | | ⬜ | | 26 | Modal | | ⬜ | diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b8f481..4acb7b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,11 @@ retry pill) and a `FlowErrorPart` message part, with `onRetry`/`errorTitle`/`retryLabel` threaded through `FlowMessage` and `FlowThread`. +- **Breaking**: `FlowChatScreen` is renamed to `FlowChatView`. The widget + was never a screen — it is body-only and embeddable, and upcoming + surfaces (side panel, modal) will host it — so the name now follows + Flutter's convention for embeddable composites. Rename call sites; + the API is unchanged. - **Breaking**: a failed assistant turn no longer recolors its content into an `errorContainer` bubble — parts keep their normal ink and the turn closes with an error card (a default one when no `FlowErrorPart` diff --git a/CLAUDE.md b/CLAUDE.md index ee1eadb..94a88f0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -95,6 +95,6 @@ Values come from the Flow UI Figma file. Role names follow Material 3's `ColorSc | # | Component | Variants / notes | Status | |---|-----------|------------------|--------| -| 24 | Chat Screen | centred 760 rail; zero state (greeting, lifted composer, starters); jump to latest | ✅ | +| 24 | Chat View | centred 760 rail; zero state (greeting, lifted composer, starters); jump to latest | ✅ | | 25 | SidePanel | | ⬜ | | 26 | Modal | | ⬜ | diff --git a/README.md b/README.md index c83bfda..81f1ab9 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ | Component | What it does | |---|---| -| [`FlowChatScreen`](https://flowui.stac.dev/components/chat-screen) | The full chat surface: bounded thread over a composer, centred at a readable width, with a zero state (greeting, lifted composer, starters) and a jump-to-latest button | +| [`FlowChatView`](https://flowui.stac.dev/components/chat-view) | The full chat surface: bounded thread over a composer, centred at a readable width, with a zero state (greeting, lifted composer, starters) and a jump-to-latest button | | [`FlowThread`](https://flowui.stac.dev/components/message-thread) | Scrollable conversation anchored to the newest message | | [`FlowMessage`](https://flowui.stac.dev/components/message-thread) | One turn — ink-wash user bubble, plain assistant, error bubble, typed content parts | | [`FlowStreamingText`](https://flowui.stac.dev/components/streaming-text) | Animated text reveal while a reply arrives | @@ -136,7 +136,7 @@ class _ChatPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: FlowChatScreen( + body: FlowChatView( empty: _messages.isEmpty, greeting: const FlowGreeting( icon: Icons.wb_twilight, @@ -176,7 +176,7 @@ class _ChatPageState extends State { } ``` -`FlowChatScreen` is body-only — it builds no `Scaffold` and no app bar, so +`FlowChatView` is body-only — it builds no `Scaffold` and no app bar, so your app keeps the chrome, the background, and the keyboard inset. See [`example/lib/main.dart`](example/lib/main.dart) for a complete runnable version of this page, and the [live playground](https://flowui.stac.dev/playground) diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 6c66ec7..5e1c173 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -25,6 +25,10 @@ const playgroundDevIndex = { // https://astro.build/config export default defineConfig({ site: 'https://flowui.stac.dev', + // FlowChatScreen became FlowChatView in 0.2.0; keep the old page URL alive. + redirects: { + '/components/chat-screen': '/components/chat-view', + }, integrations: [ playgroundDevIndex, starlight({ diff --git a/docs/src/content/docs/components/chat-screen.mdx b/docs/src/content/docs/components/chat-view.mdx similarity index 87% rename from docs/src/content/docs/components/chat-screen.mdx rename to docs/src/content/docs/components/chat-view.mdx index 0b3159d..73ca2c6 100644 --- a/docs/src/content/docs/components/chat-screen.mdx +++ b/docs/src/content/docs/components/chat-view.mdx @@ -1,5 +1,5 @@ --- -title: Chat screen +title: Chat view description: The assembled surface — thread above composer on a centred rail, with a zero state and jump-to-latest. sidebar: order: 12 @@ -7,15 +7,15 @@ sidebar: import FlowDemo from '../../../components/FlowDemo.astro'; -`FlowChatScreen` is the chat surface assembled: a bounded thread above a +`FlowChatView` is the chat surface assembled: a bounded thread above a composer, centred on a readable rail (760 by default), with a zero state for the conversation that hasn't started and a jump-to-latest button once you've scrolled back through history. - + ```dart title="Assemble the surface" -FlowChatScreen( +FlowChatView( empty: messages.isEmpty, greeting: FlowGreeting(icon: Icons.wb_twilight, text: 'Good afternoon'), suggestions: FlowSuggestionGroup( @@ -30,7 +30,7 @@ FlowChatScreen( ## It takes finished widgets -The screen accepts a built `FlowThread` and `FlowComposer` rather than +The view accepts a built `FlowThread` and `FlowComposer` rather than their data, so it stays correct as those components grow. What it adds is the one thing every host would otherwise have to know: the bounded height a thread needs, the width caps, and where the zero state's pieces go — @@ -47,7 +47,7 @@ transcript. ## Jump to latest Pass the **same** `ScrollController` to the thread and to -`threadController:` — taking finished widgets means the screen can't +`threadController:` — taking finished widgets means the view can't reach in and attach its own. Null leaves the button out entirely. ## Key API diff --git a/docs/src/content/docs/components/error-state.mdx b/docs/src/content/docs/components/error-state.mdx index 78c27d9..f921890 100644 --- a/docs/src/content/docs/components/error-state.mdx +++ b/docs/src/content/docs/components/error-state.mdx @@ -89,11 +89,11 @@ FlowMessageData( Standalone, the same card serves the other failure surfaces — a thread that failed to load, a failed send below the composer, or a connection -notice pinned above the input via `FlowChatScreen.aboveComposer`, the +notice pinned above the input via `FlowChatView.aboveComposer`, the slot that already exists for exactly this: ```dart title="A connection notice above the composer" -FlowChatScreen( +FlowChatView( thread: FlowThread(messages: messages), aboveComposer: offline ? FlowErrorState( diff --git a/docs/src/content/docs/components/greeting.mdx b/docs/src/content/docs/components/greeting.mdx index dafd18a..abe73c9 100644 --- a/docs/src/content/docs/components/greeting.mdx +++ b/docs/src/content/docs/components/greeting.mdx @@ -11,7 +11,7 @@ import FlowDemo from '../../../components/FlowDemo.astro'; there is room it sets a 40px glyph beside 32px text, bottom-aligned; below 600px of available width it restacks itself — glyph above the text, at the design's 21px. The host supplies the whole string (name and all); -`FlowChatScreen` centres it when the conversation hasn't started. +`FlowChatView` centres it when the conversation hasn't started. ## Default @@ -72,5 +72,5 @@ FlowGreeting( - `text` — the whole headline; the package composes no copy. - `icon`, `iconColor` — the optional glyph. - `textStyle` — overrides the responsive sizing outright. -- In the assembled surface: pass it to `FlowChatScreen`'s `greeting:` +- In the assembled surface: pass it to `FlowChatView`'s `greeting:` slot, shown only while `empty` is true. diff --git a/docs/src/content/docs/components/message-thread.mdx b/docs/src/content/docs/components/message-thread.mdx index baf45b1..aa7dd43 100644 --- a/docs/src/content/docs/components/message-thread.mdx +++ b/docs/src/content/docs/components/message-thread.mdx @@ -99,7 +99,7 @@ card, a chart) without the library knowing what it is. ## Key classes - `FlowThread` — the scrolling conversation; give it a `ScrollController` - to pair with `FlowChatScreen`'s jump-to-latest. `padding` (the design's + to pair with `FlowChatView`'s jump-to-latest. `padding` (the design's 16) and `itemSpacing` (32) override the metrics; `messageBuilder` swaps the default `FlowMessage` per turn; `thinkingLabel`, `charactersPerSecond`, and `previewCloseTooltip` forward to every diff --git a/docs/src/content/docs/components/suggestions.mdx b/docs/src/content/docs/components/suggestions.mdx index 5b78cf0..213a324 100644 --- a/docs/src/content/docs/components/suggestions.mdx +++ b/docs/src/content/docs/components/suggestions.mdx @@ -128,5 +128,5 @@ Column( - `FlowSuggestionColumnScope` — what the column layout wraps its rows in so a hovered row shows the trailing arrow; public so a host laying out its own full-width column can opt in. -- `FlowChatScreen` places a column group in its zero state via the +- `FlowChatView` places a column group in its zero state via the `suggestions:` slot. diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 4e4ce5a..ee0e5da 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -85,13 +85,13 @@ import logo from '../../assets/flow-ui-logo.svg'; Map your Material 3 scheme across, or ship the Flow light and dark presets. - +
03
- Chat screen + Chat view Thread, composer, attachments and suggestions in one streaming surface.
diff --git a/docs/src/content/docs/roadmap.md b/docs/src/content/docs/roadmap.md index 5fae903..3d7b0de 100644 --- a/docs/src/content/docs/roadmap.md +++ b/docs/src/content/docs/roadmap.md @@ -48,6 +48,6 @@ elements and the remaining AI states are on the way. | Component | Status | | --- | --- | -| Chat screen | Shipped | +| Chat view | Shipped | | Side panel | Planned | | Modal | Planned | diff --git a/example/lib/main.dart b/example/lib/main.dart index aa5bad7..8dae4ed 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -115,7 +115,7 @@ class _ChatPageState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: context.flowColors.surface, - body: FlowChatScreen( + body: FlowChatView( empty: _messages.isEmpty, greeting: const FlowGreeting( icon: Icons.wb_twilight, diff --git a/lib/flow_ui.dart b/lib/flow_ui.dart index 5066a11..5e5cc9f 100644 --- a/lib/flow_ui.dart +++ b/lib/flow_ui.dart @@ -15,7 +15,7 @@ export 'src/theme/flow_theme.dart'; export 'src/theme/flow_typography.dart'; export 'src/widgets/flow_attachment_group.dart'; export 'src/widgets/flow_attachment_preview.dart'; -export 'src/widgets/flow_chat_screen.dart'; +export 'src/widgets/flow_chat_view.dart'; export 'src/widgets/flow_code_block.dart'; export 'src/widgets/flow_composer.dart'; export 'src/widgets/flow_error_state.dart'; diff --git a/lib/src/widgets/flow_chat_screen.dart b/lib/src/widgets/flow_chat_view.dart similarity index 97% rename from lib/src/widgets/flow_chat_screen.dart rename to lib/src/widgets/flow_chat_view.dart index ef61c55..801cd7d 100644 --- a/lib/src/widgets/flow_chat_screen.dart +++ b/lib/src/widgets/flow_chat_view.dart @@ -21,7 +21,7 @@ const Duration _jumpScroll = Duration(milliseconds: 240); /// started. /// /// ```dart -/// FlowChatScreen( +/// FlowChatView( /// empty: messages.isEmpty, /// greeting: FlowGreeting(icon: Icons.wb_twilight, text: 'Good afternoon'), /// suggestions: FlowSuggestionGroup(...), @@ -39,8 +39,8 @@ const Duration _jumpScroll = Duration(milliseconds: 240); /// Body-only: it builds no [Scaffold] and no app bar, so drop it in a /// scaffold body and the host keeps the chrome, the background, and the /// keyboard inset. -class FlowChatScreen extends StatefulWidget { - const FlowChatScreen({ +class FlowChatView extends StatefulWidget { + const FlowChatView({ super.key, this.thread, this.composer, @@ -91,7 +91,7 @@ class FlowChatScreen extends StatefulWidget { /// centre between them, per the design; on compact ones it stays docked /// with the suggestions just above it and the greeting floating centred. /// - /// The host flips this (typically `messages.isEmpty`): the screen takes + /// The host flips this (typically `messages.isEmpty`): the view takes /// finished widgets and cannot see into the thread. final bool empty; @@ -100,7 +100,7 @@ class FlowChatScreen extends StatefulWidget { final Widget? greeting; /// The zero state's starters, usually a column `FlowSuggestionGroup`. - /// Shown only while [empty]; the screen places them — 48 below the + /// Shown only while [empty]; the view places them — 48 below the /// composer on wide layouts, capped at [emptySuggestionsWidth], and 16 /// above it on compact ones, stepped in a further 8. final Widget? suggestions; @@ -134,10 +134,10 @@ class FlowChatScreen extends StatefulWidget { final EdgeInsetsGeometry? padding; @override - State createState() => _FlowChatScreenState(); + State createState() => _FlowChatViewState(); } -class _FlowChatScreenState extends State { +class _FlowChatViewState extends State { /// The design's surface metrics. Compact begins below 600, Material's /// compact/medium boundary — read from this widget's own constraints, so /// a pane or a phone frame counts, not just a phone. The composer block @@ -168,7 +168,7 @@ class _FlowChatScreenState extends State { } @override - void didUpdateWidget(FlowChatScreen oldWidget) { + void didUpdateWidget(FlowChatView oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.threadController != widget.threadController) { oldWidget.threadController?.removeListener(_handleScroll); diff --git a/lib/src/widgets/flow_error_state.dart b/lib/src/widgets/flow_error_state.dart index f6426a9..7bc2722 100644 --- a/lib/src/widgets/flow_error_state.dart +++ b/lib/src/widgets/flow_error_state.dart @@ -18,7 +18,7 @@ import '../theme/flow_theme.dart'; /// becomes this card, and a failed assistant turn closes with a default /// one even when the host supplies no part. Standalone it serves the /// other failure surfaces — a thread that failed to load, a connection -/// notice pinned in `FlowChatScreen.aboveComposer`, a failed send below +/// notice pinned in `FlowChatView.aboveComposer`, a failed send below /// the composer. /// /// Retry reports intent; what it means — re-run the turn, refetch, diff --git a/lib/src/widgets/flow_greeting.dart b/lib/src/widgets/flow_greeting.dart index 415fd1d..8b0169e 100644 --- a/lib/src/widgets/flow_greeting.dart +++ b/lib/src/widgets/flow_greeting.dart @@ -3,7 +3,7 @@ import 'package:material_ui/material_ui.dart'; import '../theme/flow_theme.dart'; /// The zero state's headline — "Good afternoon, …" over a thread nobody has -/// spoken in yet, usually through `FlowChatScreen.greeting`: +/// spoken in yet, usually through `FlowChatView.greeting`: /// /// ```dart /// FlowGreeting( diff --git a/lib/src/widgets/flow_message.dart b/lib/src/widgets/flow_message.dart index 3ac9a86..d62416d 100644 --- a/lib/src/widgets/flow_message.dart +++ b/lib/src/widgets/flow_message.dart @@ -11,7 +11,7 @@ import 'flow_streaming_text.dart'; /// Renders a [FlowCustomPart]; return null to skip it. /// -/// A full renderer registry waits for the Chat Screen surface — this +/// A full renderer registry waits for the Chat View surface — this /// callback is the extension seam until then. typedef FlowCustomPartBuilder = Widget? Function( diff --git a/lib/src/widgets/flow_thread.dart b/lib/src/widgets/flow_thread.dart index a64ace2..f006587 100644 --- a/lib/src/widgets/flow_thread.dart +++ b/lib/src/widgets/flow_thread.dart @@ -93,7 +93,7 @@ class FlowThread extends StatelessWidget { final String? thinkingLabel; /// The design's thread metrics: edge padding and the gap between turns. - /// The edge 16 is mirrored by `FlowChatScreen`'s composer-block padding, + /// The edge 16 is mirrored by `FlowChatView`'s composer-block padding, /// which promises its edges line up with the thread's. static const EdgeInsetsGeometry _defaultPadding = EdgeInsets.all(16); static const double _defaultGap = 32; diff --git a/playground/lib/src/demo_registry.dart b/playground/lib/src/demo_registry.dart index 756dc57..96d249f 100644 --- a/playground/lib/src/demo_registry.dart +++ b/playground/lib/src/demo_registry.dart @@ -145,7 +145,7 @@ String snippetFor(PlaygroundItem item) { } const String _fullChatSnippet = ''' -FlowChatScreen( +FlowChatView( empty: messages.isEmpty, greeting: const FlowGreeting( icon: PhosphorIconsRegular.sunHorizon, diff --git a/playground/lib/src/demos/full_chat_demo.dart b/playground/lib/src/demos/full_chat_demo.dart index 83b1080..7bfd138 100644 --- a/playground/lib/src/demos/full_chat_demo.dart +++ b/playground/lib/src/demos/full_chat_demo.dart @@ -24,7 +24,7 @@ const List<(IconData, String)> _starters = [ (PhosphorIconsRegular.magnifyingGlass, 'Suggest a new venture for me'), ]; -/// The Full Chat example: a whole conversation surface on [FlowChatScreen], +/// The Full Chat example: a whole conversation surface on [FlowChatView], /// live — starts in the zero state, sends for real, streams a canned reply /// behind the thinking indicator, and carries the add and model menus. class FullChatDemo extends StatefulWidget { @@ -115,7 +115,7 @@ class _FullChatDemoState extends State { @override Widget build(BuildContext context) { - return FlowChatScreen( + return FlowChatView( empty: _messages.isEmpty, greeting: const FlowGreeting( icon: PhosphorIconsRegular.sunHorizon, diff --git a/playground/lib/src/demos/thread_demo.dart b/playground/lib/src/demos/thread_demo.dart index 6d77f25..2330969 100644 --- a/playground/lib/src/demos/thread_demo.dart +++ b/playground/lib/src/demos/thread_demo.dart @@ -6,7 +6,7 @@ import 'package:material_ui/material_ui.dart'; const String threadSnippet = ''' // A reversed, scrollable conversation — newest at the bottom. Give it -// bounded height; inside FlowChatScreen that comes for free. +// bounded height; inside FlowChatView that comes for free. SizedBox( height: 480, child: FlowThread(