Skip to content

feat(apollo-react): add the Wind chat first run, suggestions and thinking state - #1396

Open
BenGSchulz wants to merge 1 commit into
feat/wind-chat-composerfrom
feat/wind-chat-first-run-suggestions
Open

BenGSchulz wants to merge 1 commit into
feat/wind-chat-composerfrom
feat/wind-chat-first-run-suggestions

Conversation

@BenGSchulz

@BenGSchulz BenGSchulz commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Sixth PR of the Wind chat renderer stack (MST-16567). It adds the first-run experience, suggestions and thinking state. The stack was first rebased onto main so it can use W-7's ChatHero and PromptSuggestions (#1368).

First-run experience (apollo-wind ChatHero)

  • It shows while the conversation is empty and the service's firstRunExperience has a title, description or suggestions.
  • FullScreen: a centered column with the logo, the title and description, the suggestions as one horizontal row under the welcome text (scrolling sideways with faded edges when it overflows; a chip that takes keyboard focus scrolls into view), then the composer.
  • Embedded: the docked hero sits at the bottom of the message area, above the composer, where Material's is, with Material's vertical list of suggestions.
  • It never shows for a render beside an existing conversation (hasMessages follows the service events, in the same batch as the transcript), and not while a conversation loads, where the skeleton shows. A reply awaited on an empty chat shows the thinking row inside the hero, as Material shows its loading text beside the first run.
  • First message: the transcript takes over without remounting the composer, so its draft, focus and caret stay. The hero stays mounted as a plain wrapper around the composer slot. Note that any sendRequest clears the prompt in both renderers (service behaviour), so the draft survives a first message from the host, such as a greeting reply.
  • Picking a suggestion: with sendOnClick it sends through the Request intercept; otherwise it fills the composer. Focus goes to the composer either way, as in Material.

Suggestions after messages (apollo-wind PromptSuggestions)

  • The service's setSuggestions list shows under the latest reply, titled "Suggestions" and animated in. It belongs to the user turn it was set in: replies to that turn keep it (a host may set it from its Request handler, before the reply), and the next user message leaves it behind.
  • The service clears it on every request, and the chat state clears it on a new chat, for both renderers. Material keeps showing it whenever the conversation is non-empty.
  • sendOnClick falls back to the first-run setting, as in Material.

Thinking state

  • The R-2 ThinkingIndicator row now takes its messages from the loading provider: the service's defaults rotate every duration (an earlier duration is kept when new defaults come without one), setLoadingMessage replaces them, and each request or host setShowLoading(true) starts again from the defaults.
  • It hides at the first token, as before.

Hoisted into src/chat/headless

Helper What it carries Material change
providers/loading-provider.tsx: loadingMessages, loadingMessageDuration The rotation state from Material's chat-loading-text.tsx: defaults, setLoadingMessage, duration, reset on request. useLoadingMessages reads it chat-loading-text.tsx reads it and keeps its fade
hooks/use-suggestions.ts: useSuggestionSelect Send versus set prompt, plus the focus event chat-suggestions.tsx
hooks/use-suggestions.ts: useConversationSuggestions Items, sendOnClick with the first-run fallback, and whether they still belong to the latest user turn chat-message.tsx reads items and sendOnClick (Material keeps showing them whenever the conversation is non-empty)
providers/chat-state-provider.tsx: firstRunVisible, suggestions, hasMessages The "first run shows" selector; the suggestions with the user turn they were set in, cleared on a new chat; hasMessages from the service events and the initial conversation chat-fre.tsx, chat-message.tsx

A small Material change: a setLoadingMessage sent before the loading text mounts is no longer lost.

Storybook

pnpm storybook:design, then Apollo React / Chat / Playground, Compare renderers:

  • First-run experience (firstRunExperience on) in Embedded and FullScreen.
    • Type a draft, then send it or pick a suggestion.
    • The playground's first-run config has no sendOnClick, so picking fills the composer; sending on pick is covered by Suggestions that send and the tests.
  • Suggestions (fills the composer) and Suggestions that send (sendOnClick). Send another message to see them cleared.
  • Loading message: the default messages rotate for four seconds, then a custom one shows for four seconds, then the streamed reply replaces the thinking row.
  • compactMode for the compact hero and chips.

Tests

  • vitest --run src/chat src/material/components/ap-chat src/material/components/ap-tool-call: 52 files, 293 tests pass, including Material regression tests for the loading text (rotation and set message under fake timers, nothing running after unmount), first run and suggestions, and a no-flash test beside a conversation set before mount in both renderers. New tests cover:
    • the loading provider: defaults, a set message, duration, reset on request;
    • suggestion select: send versus fill, plus focus;
    • attachment to the last message;
    • the first-run sendOnClick fallback and clearing on request;
    • firstRunVisible;
    • the Wind hero: centered with the composer inside, docked in Embedded;
    • the transcript taking over with the same composer element, draft and focus;
    • suggestion fill and send;
    • conversation suggestions shown, picked and left behind;
    • the thinking state's rotation, a set message, and hiding on the first token;
    • a Wind versus Material first-run suggestion Request parity test.
  • tsc --noEmit: clean.
  • biome check on touched files: one warning already present (extra setter dependencies in chat-state-provider.tsx's useMemo).
  • DOCS.md now says the service does not store suggestions and that only a request or newChat clears them.
  • No new Lingui ids. Reused: message.suggestions-title, message.generating-response.

Stack

  1. R-1 Wind shell: feat(apollo-react): add the Wind chat renderer shell #1371
  2. R-2 message list: feat(apollo-react): add the Wind chat message list #1372
  3. R-3 markdown renderer: feat(apollo-react): add the Wind chat markdown renderer #1375
  4. R-4 tool-call and tree renderers: feat(apollo-react): add the Wind chat tool-call and tree renderers #1376
  5. R-5 composer: feat(apollo-react): add the Wind chat composer #1378
  6. R-6 first run, suggestions and thinking state: this PR
  7. R-7 history and settings: feat(apollo-react): add the Wind chat history and settings panels #1397
  8. R-8 CSS delivery and docs: feat(apollo-react): document the Wind chat setup and its delivery #1399

Jira: MST-16567

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

Dependency License Review

  • ✅ 1947 package(s) scanned
  • ✅ No license issues found
  • ⚠️ 2 package(s) excluded (see details below)
License distribution
License Packages
MIT 1713
ISC 91
Apache-2.0 56
BSD-3-Clause 28
BSD-2-Clause 23
BlueOak-1.0.0 8
MPL-2.0 4
MIT-0 3
CC0-1.0 3
MIT OR Apache-2.0 2
(MIT OR Apache-2.0) 2
Unlicense 2
LGPL-3.0-or-later 1
Python-2.0 1
CC-BY-4.0 1
(MPL-2.0 OR Apache-2.0) 1
Unknown 1
Artistic-2.0 1
(WTFPL OR MIT) 1
(BSD-2-Clause OR MIT OR Apache-2.0) 1
CC-BY-3.0 1
0BSD 1
(MIT OR CC0-1.0) 1
MIT AND ISC 1
Excluded packages
Package Version License Reason
@img/sharp-libvips-linux-x64 1.3.4 LGPL-3.0-or-later LGPL pre-built binary, not linked
khroma 2.1.0 Unknown MIT per GitHub repo, missing license field in package.json

@BenGSchulz
BenGSchulz added this pull request to stack #1374 October 16, 2026 16:23
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

📊 Coverage + size by package

Per-package coverage and bundle size on this PR. New-line coverage = of the source lines this PR adds or changes, the % hit by tests.

Package Coverage New-line coverage Packed (gzip) Unpacked vs main
@uipath/apollo-core — — 42.02 MB 50.17 MB ±0
@uipath/apollo-react 56.7% 92.7% (89/96) 8.02 MB 31.64 MB +37.2 KB
@uipath/apollo-ui-icons — — 2.86 MB 6.97 MB ±0
@uipath/apollo-vertex — — — — —
@uipath/apollo-wind — — 785.2 KB 4.55 MB +15 B
@uipath/ap-chat 85.8% — 40.37 MB 45.59 MB +2.6 KB

"Coverage" is each package's own coverage.include scope (e.g. apollo-core instruments only scripts/). "Packed"/"Unpacked" come from npm pack --dry-run and only cover built packages — "—" means not measured this run (package not affected / not built). "vs main" is the packed (gzipped) delta against the last successful main build (the package-sizes artifact from the Release workflow); "—" there means no main baseline was available this run. The baseline is main's latest build, not this PR's exact merge-base, so it includes any drift since the branch diverged. Packages with no vitest config are omitted.

@BenGSchulz
BenGSchulz force-pushed the feat/wind-chat-first-run-suggestions branch from 3eccbfe to 61291d0 Compare October 16, 2026 18:34
Copilot AI balanced review requested due to automatic review settings October 16, 2026 18:34

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions
github-actions Bot temporarily deployed to preview/apollo-design October 16, 2026 18:35 Destroyed
@github-actions
github-actions Bot temporarily deployed to preview/apollo-docs October 16, 2026 18:35 Destroyed
@github-actions
github-actions Bot temporarily deployed to preview/apollo-landing October 16, 2026 18:35 Destroyed
@github-actions
github-actions Bot temporarily deployed to preview/apollo-vertex October 16, 2026 18:35 Destroyed
@github-actions github-actions Bot added the size:XXL 1,000+ changed lines. label Oct 16, 2026
…king state

Show the first-run experience in the Wind chat on apollo-wind's ChatHero:
centered around the composer in FullScreen and docked above it in
Embedded, giving way to the transcript on the first message without
remounting the composer. Show the service's suggestions on
PromptSuggestions under the reply they were set after, sending or
filling the composer on pick, and drive the thinking state's messages
from the loading provider.

Hoist the loading message rotation state into the loading provider, the
suggestion pick into useSuggestionSelect and the first-run and
suggestion selectors into chat state, and switch Material's loading
text, suggestions and first-run experience to them.

MST-16567

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 16, 2026 19:52
@BenGSchulz
BenGSchulz force-pushed the feat/wind-chat-first-run-suggestions branch from 61291d0 to 869302c Compare October 16, 2026 19:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

This branch was successfully deployed

4 active deployments
preview/apollo-design — 869302cb Deployed Oct 16, 2026 by github-actions[bot]
preview/apollo-landing — 869302cb Deployed Oct 16, 2026 by github-actions[bot]
preview/apollo-docs — 869302cb Deployed Oct 16, 2026 by github-actions[bot]
preview/apollo-vertex — 869302cb Deployed Oct 16, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg:apollo-react size:XXL 1,000+ changed lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants