mirror of
https://github.com/pnp/sp-dev-fx-webparts.git
synced 2025-03-02 01:39:21 +00:00
Moved from spinner to inline thinking indicator
This commit is contained in:
parent
9c8bfe0c9b
commit
4ff53d4896
@ -3,10 +3,12 @@ import { Icon } from '@fluentui/react';
|
||||
import * as React from "react";
|
||||
import styles from "./ChatStreaming.module.scss";
|
||||
import MarkdownContent from "./MarkdownContent";
|
||||
import ThinkingIndicator from "./ThinkingIndicator";
|
||||
|
||||
export interface IAssistantResponseProps {
|
||||
message: string;
|
||||
disableMarkdown?: boolean;
|
||||
thinking?: boolean;
|
||||
}
|
||||
|
||||
export default class AssistantResponse extends React.Component<
|
||||
@ -20,10 +22,13 @@ export default class AssistantResponse extends React.Component<
|
||||
<Icon iconName="Robot" />
|
||||
</div>
|
||||
<div className={styles.messageBox}>
|
||||
{this.props.disableMarkdown &&
|
||||
{this.props.thinking && this.props.message.length === 0 &&
|
||||
<ThinkingIndicator />
|
||||
}
|
||||
{this.props.disableMarkdown && this.props.message.length > 0 &&
|
||||
<p className={styles.message}>{this.props.message}</p>
|
||||
}
|
||||
{!this.props.disableMarkdown &&
|
||||
{!this.props.disableMarkdown && this.props.message.length > 0 &&
|
||||
<MarkdownContent className={styles.message}>{this.props.message}</MarkdownContent>
|
||||
}
|
||||
<div className={styles.beak}/>
|
||||
|
@ -148,4 +148,76 @@
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
$dotSize: 8px;
|
||||
$jumpHeight: 14px;
|
||||
|
||||
.thinkingIndicator {
|
||||
padding-top: 6px;
|
||||
|
||||
.allDots {
|
||||
margin-top: $jumpHeight;
|
||||
display: flex;
|
||||
gap: calc($dotSize / 2);
|
||||
|
||||
.dot {
|
||||
position: relative;
|
||||
width: $dotSize;
|
||||
height: $dotSize;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
animation: bouncedelay 2.0s infinite cubic-bezier(.62, .28, .23, .99) both;
|
||||
}
|
||||
|
||||
.dot1 {
|
||||
animation-delay: -.16s;
|
||||
}
|
||||
|
||||
.dot2 {
|
||||
animation-delay: -.08s;
|
||||
}
|
||||
|
||||
.dot3 {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes bouncedelay {
|
||||
0% {
|
||||
bottom: 0;
|
||||
background-color: "[theme: themePrimary, default: #0078d4]";
|
||||
}
|
||||
|
||||
16.66% {
|
||||
bottom: $jumpHeight;
|
||||
background-color: "[theme: themeDark, default: #005a9e]";
|
||||
}
|
||||
|
||||
33.33% {
|
||||
bottom: 0px;
|
||||
background-color: "[theme: themeDark, default: #005a9e]";
|
||||
}
|
||||
|
||||
50% {
|
||||
bottom: $jumpHeight;
|
||||
background-color: "[theme: themeLight, default: #c7e0f4]";
|
||||
}
|
||||
|
||||
66.66% {
|
||||
bottom: 0px;
|
||||
background-color: "[theme: themeLight, default: #c7e0f4]";
|
||||
}
|
||||
|
||||
83.33% {
|
||||
bottom: $jumpHeight;
|
||||
background-color: "[theme: themePrimary, default: #0078d4]";
|
||||
}
|
||||
|
||||
100% {
|
||||
bottom: 0;
|
||||
background-color: "[theme: themePrimary, default: #0078d4]";
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import { IChatStreamingState } from './IChatStreamingState';
|
||||
import { cloneDeep } from '@microsoft/sp-lodash-subset';
|
||||
import { fetchEventSource } from '@microsoft/fetch-event-source';
|
||||
import CompletionsRequestBuilder from '../models/CompletionsRequestBuilder';
|
||||
import { Spinner, SpinnerSize, Stack, css } from '@fluentui/react';
|
||||
import { Stack, css } from '@fluentui/react';
|
||||
import MessagesList from './MessagesList';
|
||||
import UserMessage from './UserMessage';
|
||||
import { IChatMessage } from '../models/IChatMessage';
|
||||
@ -38,18 +38,8 @@ export default class ChatStreaming extends React.Component<IChatStreamingProps,
|
||||
const content = this._validateWebPartProperties() ? (
|
||||
<Stack className={css(styles.chatStreaming, this.props.hasTeamsContext && styles.teams)}>
|
||||
<Stack.Item grow className={styles.messagesContainer}>
|
||||
<MessagesList messages={this.state.sessionMessages} disableMarkdown={this.state.disableMarkdown} />
|
||||
<MessagesList messages={this.state.sessionMessages} disableMarkdown={this.state.disableMarkdown} thinking={this.state.thinking} />
|
||||
</Stack.Item>
|
||||
{this.state.thinking && (
|
||||
<Stack.Item>
|
||||
<Spinner
|
||||
size={SpinnerSize.large}
|
||||
label="Wait till our super cool AI system answers your question..."
|
||||
ariaLive="assertive"
|
||||
labelPosition="right"
|
||||
/>
|
||||
</Stack.Item>
|
||||
)}
|
||||
<Stack.Item>
|
||||
<UserMessage
|
||||
textFieldValue={this.state.userQuery}
|
||||
@ -79,6 +69,10 @@ export default class ChatStreaming extends React.Component<IChatStreamingProps,
|
||||
role: 'user', text: this.state.userQuery
|
||||
});
|
||||
|
||||
this.state.sessionMessages.push({
|
||||
role: 'assistant', text: ''
|
||||
});
|
||||
|
||||
await this._chatAsStream();
|
||||
|
||||
this.setState({
|
||||
|
@ -9,6 +9,7 @@ import { ScrollablePane, ScrollbarVisibility } from '@fluentui/react';
|
||||
export interface IMessagesListProps {
|
||||
messages: IChatMessage[];
|
||||
disableMarkdown?: boolean;
|
||||
thinking?: boolean;
|
||||
}
|
||||
|
||||
export default class MessagesList extends React.Component<IMessagesListProps, {}> {
|
||||
@ -28,7 +29,7 @@ export default class MessagesList extends React.Component<IMessagesListProps, {}
|
||||
if (m.role === 'user') {
|
||||
return <UserQuestion key={i} message={m.text} />
|
||||
}
|
||||
return <AssistantResponse key={i} message={m.text} disableMarkdown={this.props.disableMarkdown} />
|
||||
return <AssistantResponse key={i} message={m.text} disableMarkdown={this.props.disableMarkdown} thinking={this.props.thinking} />
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -0,0 +1,22 @@
|
||||
import * as React from "react";
|
||||
import styles from "./ChatStreaming.module.scss";
|
||||
import { css } from "@fluentui/react";
|
||||
|
||||
export interface IThinkingIndicatorProps {}
|
||||
|
||||
export default class ThinkingIndicator extends React.Component<
|
||||
IThinkingIndicatorProps,
|
||||
{}
|
||||
> {
|
||||
public render(): React.ReactElement<IThinkingIndicatorProps> {
|
||||
return (
|
||||
<div className={styles.thinkingIndicator}>
|
||||
<div className={styles.allDots}>
|
||||
<div className={css(styles.dot, styles.dot1)} />
|
||||
<div className={css(styles.dot, styles.dot2)} />
|
||||
<div className={css(styles.dot, styles.dot3)} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user