feat(chat): customizable loader placement, rendering and timing - #7171
Draft
shaejaz wants to merge 3 commits into
Draft
feat(chat): customizable loader placement, rendering and timing#7171shaejaz wants to merge 3 commits into
shaejaz wants to merge 3 commits into
Conversation
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 121 |
TIP This summary will be updated as you push new changes.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR enhances the Chat widget across the connector, UI components, and framework wrappers (InstantSearch.js + React) by making loader behavior customizable (placement, timing, and rendering context) and by adding a “suggestions loading” state with skeleton placeholders.
Changes:
- Add loader customization options (position, show override, show delay, min duration) and richer loader context (status/phase/message/tools), plus inline loader rendering.
- Introduce
suggestionsStatusinconnectChatand propagate it to UI to drive suggestion skeleton placeholders and click-guarding while loading. - Add supporting CSS (loader fade-in, inline loader styling, suggestion skeleton pills) and expand/adjust test coverage (UI + common + connector tests).
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/common/widgets/chat/options.tsx | Adds common widget tests for loader behavior (data-part trailing) and loader customization, plus suggestions placeholders behavior. |
| packages/react-instantsearch/src/widgets/Chat.tsx | Threads new loader props and suggestionsStatus into the React <Chat /> wrapper. |
| packages/instantsearch.js/src/widgets/chat/chat.tsx | Threads new loader props and suggestionsStatus into the InstantSearch.js widget renderer/templates. |
| packages/instantsearch.js/src/connectors/chat/connectChat.ts | Adds suggestionsStatus derivation logic and exposes it via render state. |
| packages/instantsearch.js/src/connectors/chat/tests/connectChat-test.ts | Adds unit tests covering suggestionsStatus state derivation. |
| packages/instantsearch.css/src/components/chat/_chat-suggestions.scss | Styles ChatPromptSuggestions skeleton placeholders. |
| packages/instantsearch.css/src/components/chat/_chat-message-loader.scss | Adds loader enter animation, reduced-motion override, and inline loader styling. |
| packages/instantsearch-ui-components/src/lib/utils/chat.ts | Adds utilities to ignore non-rendering parts for “progress” computations (findLastProgressPart). |
| packages/instantsearch-ui-components/src/components/chat/types.ts | Introduces exported loader-related types (ChatLoaderPosition, ChatLoaderPhase, ChatLoaderContext). |
| packages/instantsearch-ui-components/src/components/chat/ChatPromptSuggestions.tsx | Adds loading/skeleton rendering, blank filtering, and click suppression while loading. |
| packages/instantsearch-ui-components/src/components/chat/ChatMessages.tsx | Implements loader visibility smoothing, inline loader placement, loader context/phase, aria-busy, and “pending suggestions” mounting. |
| packages/instantsearch-ui-components/src/components/chat/ChatMessageLoader.tsx | Extends loader props to include turn context and adds inline rendering variant. |
| packages/instantsearch-ui-components/src/components/chat/ChatMessage.tsx | Adds loaderElement slot to render an inline loader under message parts. |
| packages/instantsearch-ui-components/src/components/chat/Chat.tsx | Wires suggestions loading into ChatMessages and updates hook wiring passed to the factory component. |
| packages/instantsearch-ui-components/src/components/chat/tests/ChatPromptSuggestions.test.tsx | Adds tests for skeleton rendering, blank filtering, and click suppression while loading. |
| packages/instantsearch-ui-components/src/components/chat/tests/ChatMessages.test.tsx | Adds extensive tests for loader visibility smoothing, context passing, inline rendering, and pending suggestions. |
| packages/instantsearch-ui-components/src/components/chat/tests/Chat.test.tsx | Updates factory wiring to include the new hooks passed through to ChatMessages. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+505
to
+507
| if (!isVisible && state.isVisible) { | ||
| state.hasHiddenInTurn = true; | ||
| } |
| } | ||
|
|
||
| return ( | ||
| <div className={cx('ais-ChatPromptSuggestions', classNames.root)}> |
More templates
algoliasearch-helper
instantsearch-ui-components
instantsearch.css
instantsearch.js
react-instantsearch
react-instantsearch-core
react-instantsearch-nextjs
react-instantsearch-router-nextjs
vue-instantsearch
commit: |
|
Size Change: +5.92 kB (+0.48%) Total Size: 1.23 MB 📦 View Changed
ℹ️ View Unchanged
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The chat loader was effectively fixed in place and hardcoded: it could only render at the end of the messages list, its display logic lived in the UI component with no way to influence it, the suggestions row appeared out of nothing at the end of a turn, and it visibly popped in and out mid-answer.
That last one had two causes. Parts that render nothing still answered for the turn's progress — a trailing
data-*payload, a text part created bytext-startbefore its first delta — whichfindLastProgressPartnow makes transparent. And the remaining sub-perceptual toggles are absorbed by timing: a loader returning mid-turn waits outloaderShowDelay, a visible one holds forloaderMinDuration, and honest long waits are untouched. Visibility is derived during render rather than from an effect, which would land a frame after the state it announces.API
ChatMessages, forwarded by both the JS widget and React<Chat>:loaderPosition'messages-end' | 'message-inline''messages-end'shouldShowLoader(ctx: ChatLoaderContext & { defaultValue: boolean }) => booleanloaderShowDelaynumber(ms)250loaderMinDurationnumber(ms)200translations.loaderTextwidens fromstringto also accept(ctx: ChatLoaderContext) => string, andloaderComponentnow receives the turn context (status,phase,message,messages,tools) plusinline.shouldShowLoadergets the built-in decision asdefaultValueso an override narrows it instead of reimplementing it.ChatMessagegainsloaderElement, so a custommessageComponentcan place the loader itself.New exported types:
ChatLoaderPosition,ChatLoaderPhase('submitted' | 'tool' | 'reasoning' | 'thinking'),ChatLoaderContext.Alongside:
aria-busyon the messages log, a loader fade-in with aprefers-reduced-motionoverride and no exit animation, and an inline loader variant without the message chrome.Suggestions
ChatPromptSuggestionsgainsisLoading,skeletonCountandclassNames.skeleton/classNames.skeletonItem, mirroring standalonePromptSuggestions; it also filters blank suggestions and ignores clicks while loading.connectChatexposessuggestionsStatus('idle' | 'loading') to drive it, inferring "still coming" from a running turn with nodata-suggestionspart yet, gated on evidence that suggestions are expected at all (metadata.suggestionsEnabled, or an earlier turn in the conversation produced some) so an agent that never sends them shows no placeholder.