Style Updates

Moved inline styles to SCSS module
Added support for theme colors (fixes issues with display in dark themes)
Simplified Stack logic
This commit is contained in:
Chris Kent 2024-01-28 01:42:57 -05:00
parent 4ffa2cecad
commit df7cbc59da
6 changed files with 98 additions and 115 deletions

View File

@ -1,6 +1,7 @@
import { Stack } from "@fluentui/react";
import { Icon } from '@fluentui/react';
import * as React from "react";
import styles from "./ChatStreaming.module.scss";
export interface IAssistantResponseProps {
message: string;
@ -12,46 +13,12 @@ export default class AssistantResponse extends React.Component<
> {
public render(): React.ReactElement<IAssistantResponseProps> {
return (
<Stack horizontal tokens={{ childrenGap: 30, padding: 10 }}>
<Stack.Item>
<Icon iconName="Robot" styles={{ root: { fontSize: '22px' } }} />
</Stack.Item>
<Stack.Item
grow
styles={{ root: { display: "flex", justifyContent: "flex-start" } }}
>
<div
style={{
position: "relative",
borderRadius: "5px",
padding: "5px",
backgroundColor: "white",
fontFamily:
'"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;',
fontSize: "14px",
fontWeight: "400",
boxShadow: "0px 4px 8px rgba(0, 0, 0, 0.1)",
maxWidth: "85%",
minWidth: "350px"
}}
>
<p style={{ minWidth: '100px' }}>{this.props.message}</p>
<div
style={{
content: '""',
position: "absolute",
left: "-10px",
top: "10px", // changed right to left
width: "0",
height: "0",
borderTop: "10px solid transparent",
borderBottom: "10px solid transparent",
borderRight: "10px solid white", // changed borderLeft to borderRight
}}
/>
</div>
</Stack.Item>
<Stack horizontal className={styles.assistantResponse}>
<Icon iconName="Robot" />
<div className={styles.messageBox}>
<p className={styles.message}>{this.props.message}</p>
<div className={styles.beak}/>
</div>
</Stack>
);
}

View File

@ -4,30 +4,80 @@
overflow: hidden;
color: "[theme:bodyText, default: #323130]";
color: var(--bodyText);
min-height: 100%;
gap: 20px;
&.teams {
font-family: $ms-font-family-fallbacks;
}
}
.welcome {
text-align: left;
}
.welcomeImage {
width: 100%;
max-width: 420px;
}
.links {
a {
text-decoration: none;
color: "[theme:link, default:#03787c]";
color: var(--link); // note: CSS Custom Properties support is limited to modern browsers only
&:hover {
text-decoration: underline;
color: "[theme:linkHovered, default: #014446]";
color: var(--linkHovered); // note: CSS Custom Properties support is limited to modern browsers only
}
.messagesContainer {
min-height: 200px;
height: 100%;
position: relative;
}
}
.messagesList {
background-color: "[theme:neutralLighter, default: #f3f2f1]";
min-height: 200px;
.scrollablePane {
padding: 20px;
}
}
.userQuestion {
padding: 5px;
gap: 30px;
.beak {
right: -10px;
border-left: 10px solid "[theme:white, default: #ffffff]";
}
}
.assistantResponse {
padding: 10px;
gap: 30px;
i {
font-size: 22px;
}
.beak {
left: -10px;
border-right: 10px solid "[theme:white, default: #ffffff]";
}
}
.messageBox {
position: relative;
border-radius: 5px;
padding: 5px;
background-color: "[theme:white, default: #ffffff]";
font-family: "Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;
font-size: 14px;
font-weight: 400;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
max-width: 85%;
min-width: 350px;
.message {
min-width: 100px;
}
.beak {
content: "";
position: absolute;
top: 10px;
width: 0;
height: 0;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
}
}
.userMessage {
gap: 5px;
}

View File

@ -1,11 +1,11 @@
import * as React from 'react';
//import styles from './ChatStreaming.module.scss';
import styles from './ChatStreaming.module.scss';
import type { IChatStreamingProps } from './IChatStreamingProps';
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 } from '@fluentui/react';
import { Spinner, SpinnerSize, Stack, css } from '@fluentui/react';
import MessagesList from './MessagesList';
import UserMessage from './UserMessage';
import { IChatMessage } from '../models/IChatMessage';
@ -32,13 +32,8 @@ export default class ChatStreaming extends React.Component<IChatStreamingProps,
public render(): React.ReactElement<IChatStreamingProps> {
const content = this._validateWebPartProperties() ? (
<Stack tokens={{ childrenGap: 20 }} style={{ minHeight: "100%" }}>
<Stack.Item
grow={1}
styles={{
root: { minHeight: "200px", height: "100%", position: "relative" },
}}
>
<Stack className={css(styles.chatStreaming, this.props.hasTeamsContext && styles.teams)}>
<Stack.Item grow className={styles.messagesContainer}>
<MessagesList messages={this.state.sessionMessages} />
</Stack.Item>
{this.state.thinking && (

View File

@ -2,6 +2,7 @@ import * as React from "react";
import UserQuestion from "./UserQuestion";
import AssistantResponse from "./AssistantResponse";
import { IChatMessage } from "../models/IChatMessage";
import styles from "./ChatStreaming.module.scss";
import { ScrollablePane, ScrollbarVisibility } from '@fluentui/react';
@ -30,8 +31,8 @@ export default class MessagesList extends React.Component<IMessagesListProps, {}
});
return (
<div style= {{ backgroundColor: '#f3f3f3', minHeight: '200px' }}>
<ScrollablePane scrollbarVisibility={ScrollbarVisibility.auto} style={{ padding: '20px' }}>
<div className={styles.messagesList}>
<ScrollablePane scrollbarVisibility={ScrollbarVisibility.auto} className={styles.scrollablePane}>
{output}
</ScrollablePane>
</div>

View File

@ -1,5 +1,6 @@
import { IconButton, Stack, TextField } from '@fluentui/react';
import * as React from 'react';
import styles from './ChatStreaming.module.scss';
export interface IUserMessageProps {
onMessageChange: (query: string) => void;
@ -31,8 +32,8 @@ export default class UserMessage extends React.Component<IUserMessageProps, {}>
public render(): React.ReactElement<IUserMessageProps> {
return (
<Stack horizontal tokens={{ childrenGap: 5 }}>
<Stack.Item grow={1}>
<Stack horizontal className={styles.userMessage}>
<Stack.Item grow>
<TextField
multiline
autoAdjustHeight
@ -43,7 +44,7 @@ export default class UserMessage extends React.Component<IUserMessageProps, {}>
placeholder="Type user query here."
/>
</Stack.Item>
<Stack.Item align="end">
<Stack verticalAlign='end'>
<IconButton
iconProps={{ iconName: "Send" }}
title="Send"
@ -56,7 +57,7 @@ export default class UserMessage extends React.Component<IUserMessageProps, {}>
ariaLabel="Stop"
onClick={() => this.props.controller.abort()}
/>
</Stack.Item>
</Stack>
</Stack>
);
}

View File

@ -2,6 +2,7 @@ import { Stack } from "@fluentui/react";
import { Person } from "@microsoft/mgt-react/dist/es6/spfx";
import { ViewType } from "@microsoft/mgt-spfx";
import * as React from "react";
import styles from "./ChatStreaming.module.scss";
export interface IUserQuestionProps {
message: string;
@ -13,45 +14,13 @@ export default class UserQuestion extends React.Component<
> {
public render(): React.ReactElement<IUserQuestionProps> {
return (
<Stack horizontal horizontalAlign="end" tokens={{ childrenGap: 30, padding: 5 }}>
<Stack.Item
styles={{ root: { display: "flex", justifyContent: 'flex-end', alignItems: 'flex-end' } }}
>
<div
style={{
position: "relative",
borderRadius: "5px",
padding: "5px",
backgroundColor: "white",
fontFamily:
'"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;',
fontSize: "14px",
fontWeight: "400",
boxShadow: "0px 4px 8px rgba(0, 0, 0, 0.1)",
maxWidth: "85%",
minWidth: "350px"
}}
>
<p style={{ minWidth: '100px' }}>{this.props.message}</p>
<div
style={{
content: '""',
position: "absolute",
right: "-10px",
top: "10px",
width: "0",
height: "0",
borderTop: "10px solid transparent",
borderBottom: "10px solid transparent",
borderLeft: "10px solid white",
}}
/>
</div>
</Stack.Item>
<Stack.Item>
<Person personQuery="me" view={ViewType.image} avatarSize="auto" />
</Stack.Item>
<Stack horizontal horizontalAlign="end" className={styles.userQuestion}>
<div className={styles.messageBox}>
<p className={styles.message}>{this.props.message}</p>
<div className={styles.beak} />
</div>
<Person personQuery="me" view={ViewType.image} avatarSize="auto" />
</Stack>
);
}
}
}