Skip to content

feat(apollo-react): add the Wind chat renderer shell - #1371

Open
BenGSchulz wants to merge 1 commit into
mainfrom
feat/wind-chat-shell
Open

BenGSchulz wants to merge 1 commit into
mainfrom
feat/wind-chat-shell

Conversation

@BenGSchulz

@BenGSchulz BenGSchulz commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

First PR of the Wind chat renderer stack for @uipath/apollo-react/chat (MST-16562).

  • wind/WindChatRenderer.tsx replaces WindChatPlaceholder and is registered as 'wind', so ApChat from /chat now renders it by default.
  • Root: class from ApChatTheme (light, dark, light-hc, dark-hc, future-light, future-dark), so the chat themes itself whatever the host's body class. Also data-density="compact" from spacing.compactMode, and data-mode / data-state for styling and tests. Menus and tooltips portal into a PortalContainerProvider boundary inside the themed root. When the host passes portalContainer, they portal into a themed node inside it instead.
  • Future themes: ApChatTheme gains future-light and future-dark (additive, existing values unchanged).
    • Wind applies them as the root class like the others, and isDark counts future-dark.
    • Material maps them to its existing apolloMaterialUiThemeFutureLight and apolloMaterialUiThemeFutureDark in MUI_THEME_MAP.
    • The playground passes the toolbar's future themes through instead of falling back to light and dark.
    • setTheme docs, DOCS.md, and the ap-chat web component README and dev page list them.
  • Layouts (wind/layout/):
    • Embedded fills embeddedContainer through the existing ChatRoot portal.
    • FullScreen is a full-width header over a column centered at CHAT_WIDTH_FULL_SCREEN_MAX_WIDTH, with right-hand drawers for history and settings. It has the same footprint as Material: 100vw by calc(100vh - 48px), or the full viewport height with fullHeight: false.
    • Closed keeps the last layout mounted for a 200 ms exit transition, skipped under reduced motion.
    • SideBySide renders an explicit placeholder at the panel size.
  • Header (wind/header/):
    • Title (override label), logo in FullScreen, and the Preview badge.
    • New chat, settings, history, close, and the custom header actions menu (nested via DropdownMenuSub, disabled and description honoured).
    • Built from apollo-wind Button, DropdownMenu, Badge and Tooltip, with lucide icons.
    • Honours disabledFeatures, headerSeparator and readOnly.
    • Expand/collapse is omitted: collapsing leads to SideBySide.
    • Action icon values are lucide names, kebab-case or the PascalCase export name. They load on demand through lucide-react/dynamic in a separate chunk, and unknown names render a neutral dashed box. Material keeps taking Material Icons names.
  • Placeholder regions for the message list, composer, history and settings. They are replaced in R-2, R-5 and R-7.
    The composer region already shows the configured inputPlaceholder and footer disclaimer.
  • Registration: renderers are registered in root/ApChat.tsx, the module that defines ApChat, not in the package entry; dist/chat/root/ApChat.{js,cjs} is listed in sideEffects next to the entry (kept so a ChatRoot-only import still registers). Production bundlers drop the entry barrel's statements under sideEffects, which left the deployed preview without a Wind renderer.
  • Material: the tiptap value sync skips a destroyed editor. It threw Cannot read properties of null (reading 'nodes') in production builds when the editor was recreated.
  • Material: the scroll container narrows its right padding only when the scrollbar actually takes width (offsetWidth > clientWidth). With overlay scrollbars (macOS) the compensation widened the content, which ended the overflow and restored the padding on the next resize: the panel jittered whenever content sat within a few pixels of the container height.
  • During the 200 ms exit the header keeps the layout's mode (no close button appearing, no logo disappearing) and the panel is inert.
  • tailwind.chat.css no longer scans chat/stories and test files (@source not).
  • Region placeholders carry the data-slot the real regions will keep (wind-chat-messages, wind-chat-composer, wind-chat-history, wind-chat-settings); tests query those, not the placeholder names.
  • The playground reuses one service per story and slot, and shows an Open chat launcher when a chat is closed.
  • No new strings. Every label reuses an existing chat catalog id with the same default message.

Hoisted into src/chat/headless (Material switched in this PR)

Helper What it carries Material change
hooks/use-chat-header-actions.ts: useChatHeaderActions, getChatHeaderActionVisibility Visibility rules for each built-in action (including the Embedded close opt-in) and the pre-hooked handlers: new chat (newChat, stopResponse, setPrompt(''), clearAttachments), history, settings, full-screen toggle, close, custom action header-actions.tsx drops its own handlers and visibility conditions
layout/chat-layout.ts: resolveChatLayout Header (always shown in FullScreen), separator, composer (!readOnly), history and settings availability, fullHeight MaterialChatRenderer.tsx feeds its layouts from it
hooks/use-chat-labels.ts: useChatLabels Title, input placeholder and footer disclaimer with their localized defaults header.tsx, chat-input.tsx, chat-input-footer.tsx
utils/publish-chat-event.ts: publishChatEvent The one place that touches the service's private event bus, since there is no public publish picker-provider.tsx custom header action click
assets/autopilot-logo.tsx The logo as a component (was an SVG under Material) header.tsx imports it

These are hooks and pure helpers only. No new contexts, and nothing is added to apollo-wind.

Storybook

pnpm storybook:design (port 6007), then Apollo React / Chat / Playground:

  • Embedded, Full Screen: the Wind renderer. Embedded docks the chat as a popup panel at the bottom right, using the same frame as the Material Embedded story (chat-story-frame.ts).
  • Compare renderers: Wind and Material on separate services. Embedded shows them side by side; FullScreen stacks them. Every control applies to both, scenarios replay into both on the same timers, and a message sent from the Material composer is mirrored into Wind.
  • Controls:
    • renderer, mode, locale, compactMode, readOnly, firstRunExperience, customHeaderActions, preHooks
    • every disabledFeatures flag (disableClose is three-way because Embedded only shows close for an explicit false)
    • title, inputPlaceholder, footerDisclaimer
    • scenario, autoReply, streamDelayMs
  • Theme follows the toolbar. Service events go to the Actions panel as chat event, prefixed [Wind] or [Material].
  • The docs page lists which controls update in place, which append and which remount.

What to try:

  • Toggle the toolbar theme, plus compactMode (shorter header, data-density) and the disabled-feature flags.
  • Open the custom actions menu in dark themes: it portals inside the chat root.
  • With preHooks on, confirm and cancel header actions.
  • Set mode to full-screen (logo appears, close shows by default).
  • In Compare, check that the header events match in the Actions panel.

Apollo React / Material (Maintenance Only) / Components / Chat keeps all three stories and every control. Its data now comes from src/chat/stories/chat-story-fixtures.ts.

Tests

  • pnpm --filter @uipath/apollo-react exec vitest --run src/chat src/material/components/ap-chat: 24 files, 138 tests pass. New tests cover:
    • renderer resolution, theme class (future themes included), compact mapping
    • isDark for every theme, and Material's theme map including the future themes
    • closed and open transition, SideBySide placeholder, read-only
    • pre-hook gating, custom actions
    • header event parity between Wind and Material
    • layout and visibility rules
    • the playground: in-place args, scenario append, request mirroring
  • tsc --noEmit -p packages/apollo-react: clean.
  • biome check on touched files: clean.
  • lingui extract stops on the known pre-existing duplicate id autopilot-chat.error.multiple-files. This PR adds no ids.

Stack

  1. R-1 Wind shell: feat(apollo-react): add the Wind chat renderer shell #1371 (this PR)
  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: feat(apollo-react): add the Wind chat first run, suggestions and thinking state #1396
  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-16562

🤖 Generated with Claude Code

Copilot AI balanced review requested due to automatic review settings October 14, 2026 20:04

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 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Apollo Coded App preview deployments are ready.

Project Status Preview Updated (PT)
apollo-design Ready Preview · Logs Oct 14, 2026, 04:54:50 PM
apollo-docs Ready Preview · Logs Oct 14, 2026, 04:54:50 PM
apollo-landing Ready Preview · Logs Oct 14, 2026, 04:54:50 PM
apollo-vertex Ready Preview · Logs Oct 14, 2026, 04:54:50 PM

@github-actions github-actions Bot added the size:XXL 1,000+ changed lines. label Oct 14, 2026
@github-actions

github-actions Bot commented Oct 14, 2026 •

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

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Storybook visual diff

⚠️ Visual changes detected: 6 changed, 6 added (of 266 compared, 254 unchanged). View report

Baseline is the deployed main Storybook, so changes merged to main after this branch was last updated can also appear here. Logs

Updated (PT): Oct 16, 2026, 01:13:06 PM

@github-actions

github-actions Bot commented Oct 14, 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 52.6% 61.8% (327/529) 7.97 MB 31.35 MB −18.0 KB
@uipath/apollo-ui-icons — — 2.86 MB 6.97 MB ±0
@uipath/apollo-vertex — — — — —
@uipath/apollo-wind — — 785.2 KB 4.55 MB +11 B
@uipath/ap-chat 85.8% — (15 untracked) 40.37 MB 45.58 MB +1.1 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-shell branch from ad83ba5 to 1425c73 Compare October 14, 2026 21:48
Copilot AI balanced review requested due to automatic review settings October 14, 2026 21:48

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.

Copilot AI balanced review requested due to automatic review settings October 14, 2026 22:13
@BenGSchulz
BenGSchulz force-pushed the feat/wind-chat-shell branch from 1425c73 to c2b13b6 Compare October 14, 2026 22:13

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.

@BenGSchulz
BenGSchulz force-pushed the feat/wind-chat-shell branch from c2b13b6 to 57940c7 Compare October 14, 2026 23:47
Copilot AI balanced review requested due to automatic review settings October 14, 2026 23:47

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.

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-docs October 16, 2026 16:11 Destroyed
@github-actions
github-actions Bot temporarily deployed to preview/apollo-landing October 16, 2026 16:11 Destroyed
@github-actions
github-actions Bot temporarily deployed to preview/apollo-design October 16, 2026 16:11 Destroyed
@github-actions
github-actions Bot temporarily deployed to preview/apollo-vertex October 16, 2026 16:11 Destroyed
Replace the Wind placeholder with WindChatRenderer, registered as 'wind'
in @uipath/apollo-react/chat. The root carries the ApChatTheme class and
data-density="compact" from spacing.compactMode; overlays portal inside
it. Embedded and FullScreen layouts match Material's footprint, Closed
animates out (reduced-motion aware), and SideBySide renders an explicit
placeholder. The header has title, logo (FullScreen), preview badge,
new chat, settings, history, close and the custom actions menu. Action
icons are lucide names loaded on demand through lucide-react/dynamic;
unknown names show a neutral box. Message list, composer, history and
settings are placeholder regions for the following tickets; the composer
region already shows the configured placeholder and disclaimer.

The renderers are registered by the module that defines ApChat rather
than the package entry, whose statements bundlers drop under
sideEffects when only re-exports are used; that module is listed in
sideEffects. During the exit fade the header keeps the layout's mode and
the panel is inert. The chat CSS no longer scans stories and tests.

Hoisted into chat/headless and adopted by Material:
- useChatHeaderActions / getChatHeaderActionVisibility: visibility rules
  and pre-hooked handlers for the header actions
- resolveChatLayout: header, composer, history, settings and fullHeight
  rules per mode
- useChatLabels: title, input placeholder and footer disclaimer with
  their localized defaults
- publishChatEvent: the single wrapper around the private event bus
- the Autopilot logo, now a component under chat/assets

Add the Apollo React/Chat playground (Embedded, FullScreen, Compare
renderers) driven by args applied in place through the service setters,
with scripted scenarios replayed into both renderers. Its fixtures are
shared with the Material showcase, which keeps all of its stories and
controls. Both renderers share the docked Embedded panel frame. Story
folders are excluded from the published build.

Material's tiptap value sync now skips an editor that was destroyed
when its extensions changed, which threw in production builds, and its
scroll container only narrows its padding for a scrollbar that takes
width: with overlay scrollbars the compensation widened the content,
ended the overflow and flipped back on every resize.

MST-16562

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@BenGSchulz
BenGSchulz force-pushed the feat/wind-chat-shell branch from 8d364a7 to 2b33ccb Compare October 16, 2026 19:52
Copilot AI balanced review requested due to automatic review settings 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-docs — 2b33ccbe Deployed Oct 16, 2026 by github-actions[bot]
preview/apollo-landing — 2b33ccbe Deployed Oct 16, 2026 by github-actions[bot]
preview/apollo-design — 2b33ccbe Deployed Oct 16, 2026 by github-actions[bot]
preview/apollo-vertex — 2b33ccbe 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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants