Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ This file provides guidance to Codex (Codex.ai/code) when working with code in t

Two hard constraints shape everything here:

- **Two dependencies beyond flutter.dev, each argued.** `dependencies:` in `pubspec.yaml` holds the Flutter SDK, Flutter's own first-party packages — `material_ui` (Material's home since Flutter 3.47) and its transitive set, all published by flutter.dev — plus `file_selector` (flutter.dev), the plugin behind the composer's attach button, and `google_fonts` (material.io), which fetches Google Sans and Google Sans Code at runtime. No font files ship. Nothing else, and adding one is a decision rather than a convenience: it must not force configuration on hosts that never touch the feature (this is why `file_selector` and not `image_picker`, which writes a permission, a FileProvider and a Play-services entry into every host's Android manifest), and the PR has to argue it. What the two we have do ask for is documented: the fonts need `android.permission.INTERNET` and macOS `com.apple.security.network.client`; the picker needs macOS `com.apple.security.files.user-selected.read-only`. Dev dependencies (`flutter_test`, `flutter_lints`) are fine.
- **One dependency beyond flutter.dev, argued.** `dependencies:` in `pubspec.yaml` holds the Flutter SDK, Flutter's own first-party packages — `material_ui` (Material's home since Flutter 3.47) and its transitive set, all published by flutter.dev — plus `file_selector` (flutter.dev), the plugin behind the composer's attach button. Nothing else, and adding one is a decision rather than a convenience: it must not force configuration on hosts that never touch the feature (this is why `file_selector` and not `image_picker`, which writes a permission, a FileProvider and a Play-services entry into every host's Android manifest), and the PR has to argue it. What the one we have does ask for is documented: the picker needs macOS `com.apple.security.files.user-selected.read-only`. Dev dependencies (`flutter_test`, `flutter_lints`) are fine.
- **The typefaces ship, they are not fetched.** Google Sans and Google Sans Code live in `packages/flow_ui/fonts/` under the SIL Open Font License, declared under `flutter: fonts:` with every cut (sans 400–700, mono 300–800, each upright and italic) and addressed as `package: 'flow_ui'`. Google Sans is a Latin subset — the full cuts are ~1.95 MB each — rebuilt by `packages/flow_ui/tool/subset_fonts.sh`; the scripts it drops fall back to the platform face. Nothing reaches the network for a glyph, so hosts need no INTERNET permission and no macOS network entitlement.
- **Nothing model-facing.** Components render state passed in and report intent out through callbacks. No prompts, schemas, provider/network calls, or any LLM awareness — that belongs to the layers built on top.

The theme, the conversation components (message, thread, streaming text, actions, loading), the composer and its menus, attachments with their preview, suggestions, and the chat surface are implemented; the roadmap below tracks the rest. Message content is modeled as typed parts (`lib/src/models/`) — sealed `FlowMessagePart` subtypes rendered by `FlowMessage`, with `FlowCustomPart` + `FlowCustomPartBuilder` as the extension seam for host-injected content.

## Layout

- Root `pubspec.yaml` is the pub workspace (members under `workspace:`) with the melos scripts; root `analysis_options.yaml` (very_good_analysis) governs `tool/` and the SDK package only.
- `packages/flow_ui/` — the published package: `lib/`, `example/` (the README's chat screen against Gemini), `assets/`, its own flutter_lints `analysis_options.yaml` and `.pubignore`.
- `packages/flow_ui/` — the published package: `lib/`, `example/` (the README's chat screen against Gemini), `assets/`, `fonts/` (the bundled typefaces and their OFL texts), `tool/` (`subset_fonts.sh`, not published), its own flutter_lints `analysis_options.yaml` and `.pubignore`.
- `packages/stacflow/` — the StacFlow SDK package (see "SDK package"), with `example/` (the README's chat screen against Gemini; flutter_lints like the flow_ui example).
- `playground/` — the Flow UI Playground: a full Flutter app and workspace member depending on `flow_ui: ^0.4.0`. Use it to demo and manually exercise components (every component has a stage demo, with variant pills and code snippets).
- `docs/` — the Astro site behind flowui.stac.dev. `contracts/` — the SDK wire contract.
Expand Down
5 changes: 3 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

Two hard constraints shape everything here:

- **Two dependencies beyond flutter.dev, each argued.** `dependencies:` in `pubspec.yaml` holds the Flutter SDK, Flutter's own first-party packages — `material_ui` (Material's home since Flutter 3.47) and its transitive set, all published by flutter.dev — plus `file_selector` (flutter.dev), the plugin behind the composer's attach button, and `google_fonts` (material.io), which fetches Google Sans and Google Sans Code at runtime. No font files ship. Nothing else, and adding one is a decision rather than a convenience: it must not force configuration on hosts that never touch the feature (this is why `file_selector` and not `image_picker`, which writes a permission, a FileProvider and a Play-services entry into every host's Android manifest), and the PR has to argue it. What the two we have do ask for is documented: the fonts need `android.permission.INTERNET` and macOS `com.apple.security.network.client`; the picker needs macOS `com.apple.security.files.user-selected.read-only`. Dev dependencies (`flutter_test`, `flutter_lints`) are fine.
- **One dependency beyond flutter.dev, argued.** `dependencies:` in `pubspec.yaml` holds the Flutter SDK, Flutter's own first-party packages — `material_ui` (Material's home since Flutter 3.47) and its transitive set, all published by flutter.dev — plus `file_selector` (flutter.dev), the plugin behind the composer's attach button. Nothing else, and adding one is a decision rather than a convenience: it must not force configuration on hosts that never touch the feature (this is why `file_selector` and not `image_picker`, which writes a permission, a FileProvider and a Play-services entry into every host's Android manifest), and the PR has to argue it. What the one we have does ask for is documented: the picker needs macOS `com.apple.security.files.user-selected.read-only`. Dev dependencies (`flutter_test`, `flutter_lints`) are fine.
- **The typefaces ship, they are not fetched.** Google Sans and Google Sans Code live in `packages/flow_ui/fonts/` under the SIL Open Font License, declared under `flutter: fonts:` with every cut (sans 400–700, mono 300–800, each upright and italic) and addressed as `package: 'flow_ui'`. Google Sans is a Latin subset — the full cuts are ~1.95 MB each — rebuilt by `packages/flow_ui/tool/subset_fonts.sh`; the scripts it drops fall back to the platform face. Nothing reaches the network for a glyph, so hosts need no INTERNET permission and no macOS network entitlement.
- **Nothing model-facing.** Components render state passed in and report intent out through callbacks. No prompts, schemas, provider/network calls, or any LLM awareness — that belongs to the layers built on top.

The theme, the conversation components (message, thread, streaming text, actions, loading), the composer and its menus, attachments with their preview, suggestions, and the chat surface are implemented; the roadmap below tracks the rest. Message content is modeled as typed parts (`lib/src/models/`) — sealed `FlowMessagePart` subtypes rendered by `FlowMessage`, with `FlowCustomPart` + `FlowCustomPartBuilder` as the extension seam for host-injected content.

## Layout

- Root `pubspec.yaml` is the pub workspace (members under `workspace:`) with the melos scripts; root `analysis_options.yaml` (very_good_analysis) governs `tool/` and the SDK package only.
- `packages/flow_ui/` — the published package: `lib/`, `example/` (the README's chat screen against Gemini), `assets/`, its own flutter_lints `analysis_options.yaml` and `.pubignore`.
- `packages/flow_ui/` — the published package: `lib/`, `example/` (the README's chat screen against Gemini), `assets/`, `fonts/` (the bundled typefaces and their OFL texts), `tool/` (`subset_fonts.sh`, not published), its own flutter_lints `analysis_options.yaml` and `.pubignore`.
- `packages/stacflow/` — the StacFlow SDK package (see "SDK package"), with `example/` (the README's chat screen against Gemini; flutter_lints like the flow_ui example).
- `playground/` — the Flow UI Playground: a full Flutter app and workspace member depending on `flow_ui: ^0.4.0`. Use it to demo and manually exercise components (every component has a stage demo, with variant pills and code snippets).
- `docs/` — the Astro site behind flowui.stac.dev. `contracts/` — the SDK wire contract.
Expand Down
4 changes: 2 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ npm run dev # http://localhost:4321
npm run build # static site in dist/
```

Google Sans loads from Google Fonts via the `<link>` in `astro.config.mjs` —
the same source the package fetches from at runtime. Brand colors in
Google Sans loads from Google Fonts via the `<link>` in `astro.config.mjs`,
for this site's own chrome — the package bundles its own copy. Brand colors in
`src/styles/theme.css` mirror the package's design tokens in
`packages/flow_ui/lib/src/theme/flow_colors.dart`.

Expand Down
3 changes: 2 additions & 1 deletion docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export default defineConfig({
customCss: ['./src/styles/theme.css'],
logo: { src: './src/assets/flow-ui-logo.svg', alt: '' },
head: [
// Google Sans from Google Fonts — the same source the package fetches at runtime.
// Google Sans from Google Fonts, for this site's own chrome. The package
// bundles its own copy; this is the web page, not the Flutter build.
{ tag: 'link', attrs: { rel: 'preconnect', href: 'https://fonts.googleapis.com' } },
{
tag: 'link',
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/components/code-block.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ FlowCodeLanguage.register(
## 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
recolor them; the code face is Google Sans Code, bundled with the package, and
swaps via the typography:

```dart title="Custom syntax palette and mono face"
Expand Down
18 changes: 8 additions & 10 deletions docs/src/content/docs/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ dependencies:
flow_ui: ^0.4.0
```

That brings in the Flutter SDK, `material_ui`, `file_selector` — the
flutter.dev plugin behind the composer's attach button — and
`google_fonts`, which fetches Google Sans and Google Sans Code at
runtime. Nothing else.
That brings in the Flutter SDK, `material_ui` and `file_selector` — the
flutter.dev plugin behind the composer's attach button. Nothing else.

## Wire the theme

Expand All @@ -47,12 +45,12 @@ MaterialApp(
back to a preset matched to the ambient `ThemeData.brightness`.
</Aside>

Google Sans — the face the design system is set in — is fetched through
`google_fonts` on first use, so there is nothing to add to your `pubspec.yaml`
fonts section. The fetch needs network access: `android.permission.INTERNET`
in the main Android manifest (Flutter grants it only to debug and profile)
and the `com.apple.security.network.client` entitlement in a sandboxed macOS
app. To render offline on first launch, ship the files under `google_fonts/`.
Google Sans — the face the design system is set in — ships with the package,
along with Google Sans Code for code, so there is nothing to add to your
`pubspec.yaml` fonts section and nothing to grant. No network access, no
entitlement, and no fallback face on the first frame. Google Sans ships as a
Latin subset; text in the scripts it leaves out falls back to the platform
face, the way CJK does.

## Render a conversation

Expand Down
6 changes: 6 additions & 0 deletions docs/src/content/docs/theming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ one (`titleLargeEmphasised` at w600, `labelLargeEmphasised` at w500), so
emphasis in a heading or a control never needs an ad-hoc `copyWith`.
Styles are colorless; components pair them with color tokens at draw time.

Both faces ship with the package — Google Sans at 400 through 700 and
Google Sans Code at 300 through 800, each weight upright and italic — so
every cut the scale asks for is a real one and nothing is fetched. Google
Sans ships as a Latin subset; the scripts it leaves out fall back to the
platform face.

To keep the scale and swap the face:

```dart title="Your brand's typeface"
Expand Down
3 changes: 3 additions & 0 deletions packages/flow_ui/.pubignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ doc/
# The workspace pubspec cannot resolve outside this repo; the example ships
# as readable source, not as a standalone package.
example/pubspec.yaml

# The subsetting script is a maintainer tool, not package content.
tool/
3 changes: 3 additions & 0 deletions packages/flow_ui/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## 0.4.0 (unreleased)

- Bundles Google Sans and Google Sans Code with the package instead of fetching them through google_fonts, which is dropped as a dependency. Nothing is fetched at runtime, so hosts no longer need android.permission.INTERNET or com.apple.security.network.client, and there is no fallback face on the first frame. Google Sans ships as a Latin subset; the scripts it leaves out fall back to the platform face, as CJK already did.
- Makes `FlowTypography.standard` and `FlowTheme.typography` `const` again, and `FlowTypography.code` / `codeInline` plain fields with const defaults.
- Deprecates `FlowTypography.recut` in favour of `copyWith(fontWeight:, fontStyle:)` — the bundled families declare every cut, so the engine resolves it from the weight on the style. Removed in 0.6.0.
- Adds FlowTool, the tool-call card: one mark morphs with the call's status (a still asterisk while staged, turning while it runs, a check or an error glyph once settled), the host's title and primary argument sit on the row, and the input and output render as code blocks behind a disclosure, with a failure readable without a tap. FlowToolPart renders it in a thread, keyed by the provider's call id and copying through FlowThread.onCodeCopy; FlowToolStyle joins the component styles with a FlowTheme.toolStyle default. Metrics are provisional pending a design frame.

## 0.3.0
Expand Down
29 changes: 18 additions & 11 deletions packages/flow_ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,19 @@ MaterialApp(
)
```

The default typography — Google Sans and Google Sans Code — arrives through
[google_fonts](https://pub.dev/packages/google_fonts): each cut is fetched
on first use and cached on the device, so there is no font to bundle. The
fetch needs network access: `android.permission.INTERNET` in an Android
app's main manifest (Flutter's template grants it only to debug and profile)
and the `com.apple.security.network.client` entitlement in a sandboxed macOS
app; without it text falls back to the platform face. To render offline on
first launch, ship the files under a `google_fonts/` asset folder.
The default typography — Google Sans and Google Sans Code — ships with the
package. Nothing is fetched, so there is no permission, no entitlement and
no fallback face on the first frame, and your app declares no font of its
own. Google Sans ships as a Latin subset, which keeps the whole set near a
megabyte; the scripts it leaves out fall back to the platform face, the way
CJK does. To set the scale in your own typeface instead:

```dart
FlowTheme(
colors: FlowColors.light,
typography: FlowTypography.standard.withFontFamily('Inter'),
)
```

## Build a chat screen

Expand Down Expand Up @@ -306,6 +311,8 @@ cd playground && flutter run -d chrome

## License

Code is released under the [MIT License](LICENSE). Google Sans and Google
Sans Code are fetched from Google Fonts under the
[SIL Open Font License](https://openfontlicense.org), not bundled.
Code is released under the [MIT License](LICENSE). The bundled Google Sans
and Google Sans Code fonts are licensed separately under the
[SIL Open Font License](https://openfontlicense.org) — see
[fonts/OFL.txt](fonts/OFL.txt) and
[fonts/OFL-GoogleSansCode.txt](fonts/OFL-GoogleSansCode.txt).
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
)

set(PLUGIN_BUNDLED_LIBRARIES)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
)

set(PLUGIN_BUNDLED_LIBRARIES)
Expand Down
Binary file added packages/flow_ui/fonts/GoogleSans-Bold.ttf
Binary file not shown.
Binary file added packages/flow_ui/fonts/GoogleSans-BoldItalic.ttf
Binary file not shown.
Binary file added packages/flow_ui/fonts/GoogleSans-Italic.ttf
Binary file not shown.
Binary file added packages/flow_ui/fonts/GoogleSans-Medium.ttf
Binary file not shown.
Binary file not shown.
Binary file added packages/flow_ui/fonts/GoogleSans-Regular.ttf
Binary file not shown.
Binary file added packages/flow_ui/fonts/GoogleSans-SemiBold.ttf
Binary file not shown.
Binary file not shown.
Binary file added packages/flow_ui/fonts/GoogleSansCode-Bold.ttf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added packages/flow_ui/fonts/GoogleSansCode-Italic.ttf
Binary file not shown.
Binary file added packages/flow_ui/fonts/GoogleSansCode-Light.ttf
Binary file not shown.
Binary file not shown.
Binary file added packages/flow_ui/fonts/GoogleSansCode-Medium.ttf
Binary file not shown.
Binary file not shown.
Binary file added packages/flow_ui/fonts/GoogleSansCode-Regular.ttf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Loading