Skip to content

Commit c3d6f9b

Browse files
authored
RI-7690 Rework the visuals of the Redis Copilot screens (#5140)
- rework the visuals of the redis copilot screens - style the chat bubbles - style the popovers - changed sass styles with styled components - added default styles for the welcome message in redis copilot - port chat history sass styles to styled components
1 parent af8e591 commit c3d6f9b

File tree

9 files changed

+167
-173
lines changed

9 files changed

+167
-173
lines changed

redisinsight/ui/src/components/side-panels/components/copilot-panel/CopilotPanel.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import styles from 'uiSrc/components/side-panels/styles.module.scss'
44
import AiAssistant from 'uiSrc/components/side-panels/panels/ai-assistant'
55
import { ONBOARDING_FEATURES } from 'uiSrc/components/onboarding-features'
66
import { OnboardingTour } from 'uiSrc/components'
7+
import { Text } from 'uiSrc/components/base/text'
78

89
export interface Props {
910
isFullScreen: boolean
@@ -25,7 +26,9 @@ const CopilotPanel = (props: Props) => {
2526
fullSize
2627
>
2728
<div className={styles.titleWrapper}>
28-
<span className={styles.title}>Redis Copilot</span>
29+
<Text size="L" color="primary">
30+
Redis Copilot
31+
</Text>
2932
</div>
3033
</OnboardingTour>
3134
</div>

redisinsight/ui/src/components/side-panels/panels/ai-assistant/components/expert-chat/components/expert-chat-header/ExpertChatHeader.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
setExplorePanelIsPageOpen,
1919
} from 'uiSrc/slices/panels/sidePanels'
2020
import { RestartChat } from 'uiSrc/components/side-panels/panels/ai-assistant/components/shared'
21-
21+
import { Row } from 'uiSrc/components/base/layout/flex'
2222
import { Spacer } from 'uiSrc/components/base/layout/spacer'
2323
import { EmptyButton, PrimaryButton } from 'uiSrc/components/base/forms/buttons'
2424
import { EraserIcon, LightBulbIcon } from 'uiSrc/components/base/icons'
@@ -102,18 +102,20 @@ const ExpertChatHeader = (props: Props) => {
102102
}
103103
>
104104
<>
105-
<Text>
105+
<Text size="m" color="primary">
106106
Open relevant tutorials to learn more about search and query.
107107
</Text>
108-
<Spacer size="s" />
109-
<PrimaryButton
110-
size="s"
111-
onClick={handleOpenTutorials}
112-
className={styles.openTutorialsBtn}
113-
data-testid="ai-expert-open-tutorials"
114-
>
115-
Open tutorials
116-
</PrimaryButton>
108+
<Spacer size="l" />
109+
<Row justify="end">
110+
<PrimaryButton
111+
size="s"
112+
onClick={handleOpenTutorials}
113+
className={styles.openTutorialsBtn}
114+
data-testid="ai-expert-open-tutorials"
115+
>
116+
Open tutorials
117+
</PrimaryButton>
118+
</Row>
117119
</>
118120
</RiPopover>
119121
</RiTooltip>

redisinsight/ui/src/components/side-panels/panels/ai-assistant/components/shared/chat-form/ChatForm.tsx

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React, { Ref, useRef, useState } from 'react'
33
import cx from 'classnames'
44
import { isModifiedEvent } from 'uiSrc/services'
55

6+
import { Row } from 'uiSrc/components/base/layout/flex'
67
import { RiPopover, RiTooltip } from 'uiSrc/components/base'
78
import { Spacer } from 'uiSrc/components/base/layout/spacer'
89
import { PrimaryButton } from 'uiSrc/components/base/forms/buttons'
@@ -99,12 +100,12 @@ const ChatForm = (props: Props) => {
99100
<div>
100101
{validation.title && (
101102
<>
102-
<Title size="XS">{validation.title}</Title>
103+
<Title size="S">{validation.title}</Title>
103104
<Spacer size="s" />
104105
</>
105106
)}
106107
{validation.content && (
107-
<Text size="xs">{validation.content}</Text>
108+
<Text size="m">{validation.content}</Text>
108109
)}
109110
</div>
110111
{validation.icon}
@@ -150,21 +151,24 @@ const ChatForm = (props: Props) => {
150151
>
151152
<>
152153
{agreements}
153-
<Spacer size="m" />
154-
<PrimaryButton
155-
size="s"
156-
className={styles.agreementsAccept}
157-
onClick={submitMessage}
158-
onKeyDown={(e: React.KeyboardEvent) => e.stopPropagation()}
159-
type="button"
160-
data-testid="ai-accept-agreements"
161-
>
162-
I accept
163-
</PrimaryButton>
154+
<Spacer size="l" />
155+
<Row justify="end">
156+
<PrimaryButton
157+
size="s"
158+
className={styles.agreementsAccept}
159+
onClick={submitMessage}
160+
onKeyDown={(e: React.KeyboardEvent) => e.stopPropagation()}
161+
type="button"
162+
data-testid="ai-accept-agreements"
163+
>
164+
I accept
165+
</PrimaryButton>
166+
</Row>
164167
</>
165168
</RiPopover>
166169
</form>
167170
</RiTooltip>
171+
<Spacer size="xs" />
168172
<Text textAlign="center" size="xs" className={styles.agreementText}>
169173
Verify the accuracy of any information provided by Redis Copilot before
170174
using it
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import styled from 'styled-components'
2+
import { AiChatMessageType } from 'uiSrc/slices/interfaces/aiAssistant'
3+
4+
export const HistoryWrapper = styled.div`
5+
width: 100%;
6+
height: 100%;
7+
`
8+
9+
export const HistoryContainer = styled.div`
10+
display: flex;
11+
flex-direction: column;
12+
height: 100%;
13+
overflow-y: auto;
14+
padding: 8px 12px;
15+
16+
> :first-child {
17+
margin-top: auto;
18+
}
19+
`
20+
21+
export const MessageWrapper = styled.div<{
22+
messageType: AiChatMessageType
23+
}>`
24+
max-width: 90%;
25+
margin: 8px 0;
26+
align-self: ${({ messageType }) =>
27+
messageType === AiChatMessageType.AIMessage ? 'flex-start' : 'flex-end'};
28+
`
29+
30+
export const MessageContainer = styled.div<{
31+
messageType: AiChatMessageType
32+
hasError?: boolean
33+
}>`
34+
overflow-wrap: break-word;
35+
padding: 8px 16px;
36+
border-radius: 8px;
37+
gap: 6px;
38+
39+
${({ messageType, theme }) =>
40+
messageType === AiChatMessageType.AIMessage &&
41+
`
42+
background-color: ${theme.components.button.variants.primary.disabled?.bgColor};
43+
`}
44+
45+
${({ messageType, theme }) =>
46+
messageType === AiChatMessageType.HumanMessage &&
47+
`
48+
background-color: ${theme.components.button.variants['secondary-invert'].normal?.bgColor};
49+
color: ${theme.components.button.variants['secondary-invert'].normal?.textColor};
50+
`}
51+
52+
${({ hasError }) =>
53+
hasError &&
54+
`
55+
opacity: .66;
56+
display: flex;
57+
`}
58+
`

redisinsight/ui/src/components/side-panels/panels/ai-assistant/components/shared/chat-history/ChatHistory.tsx

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import React, {
55
useEffect,
66
useRef,
77
} from 'react'
8-
import cx from 'classnames'
98

109
import { throttle } from 'lodash'
1110
import {
@@ -21,7 +20,12 @@ import LoadingMessage from '../loading-message'
2120
import MarkdownMessage from '../markdown-message'
2221
import ErrorMessage from '../error-message'
2322

24-
import styles from './styles.module.scss'
23+
import {
24+
HistoryContainer,
25+
HistoryWrapper,
26+
MessageContainer,
27+
MessageWrapper,
28+
} from './ChatHistory.styles'
2529

2630
export interface Props {
2731
autoScroll?: boolean
@@ -113,25 +117,16 @@ const ChatHistory = (props: Props) => {
113117

114118
return (
115119
<React.Fragment key={id}>
116-
<div
117-
className={cx({
118-
[styles.answerWrapper]:
119-
messageType === AiChatMessageType.AIMessage,
120-
[styles.questionWrapper]:
121-
messageType === AiChatMessageType.HumanMessage,
122-
})}
123-
>
124-
<div
125-
className={cx('jsx-markdown', {
126-
[styles.answer]: messageType === AiChatMessageType.AIMessage,
127-
[styles.question]:
128-
messageType === AiChatMessageType.HumanMessage,
129-
[styles.error]: !!error,
130-
})}
120+
<MessageWrapper as="div" messageType={messageType}>
121+
<MessageContainer
122+
as="div"
123+
className="jsx-markdown"
124+
messageType={messageType}
125+
hasError={!!error}
131126
data-testid={`ai-message-${messageType}_${id}`}
132127
>
133128
{error && (
134-
<RiIcon type="ToastDangerIcon" className={styles.errorIcon} />
129+
<RiIcon type="ToastDangerIcon" size="M" color="danger500" />
135130
)}
136131
{messageType === AiChatMessageType.HumanMessage ? (
137132
content
@@ -144,8 +139,8 @@ const ChatHistory = (props: Props) => {
144139
{content}
145140
</MarkdownMessage>
146141
)}
147-
</div>
148-
</div>
142+
</MessageContainer>
143+
</MessageWrapper>
149144
<ErrorMessage error={error} onRestart={onRestart} />
150145
</React.Fragment>
151146
)
@@ -155,50 +150,51 @@ const ChatHistory = (props: Props) => {
155150

156151
if (isLoading) {
157152
return (
158-
<div className={cx(styles.wrapper, styles.loader)}>
153+
<HistoryWrapper>
159154
<Loader size="xl" data-testid="ai-loading-spinner" />
160-
</div>
155+
</HistoryWrapper>
161156
)
162157
}
163158

164159
if (history.length === 0) {
165160
return (
166-
<div className={styles.wrapper}>
167-
<div className={styles.history} data-testid="ai-chat-empty-history">
168-
<div className={styles.answerWrapper}>
169-
<div
170-
className={styles.answer}
161+
<HistoryWrapper>
162+
<HistoryContainer as="div" data-testid="ai-chat-empty-history">
163+
<MessageWrapper as="div" messageType={AiChatMessageType.AIMessage}>
164+
<MessageContainer
165+
as="div"
166+
messageType={AiChatMessageType.AIMessage}
171167
data-testid="ai-message-initial-message"
172168
>
173169
{initialMessage}
174-
</div>
175-
</div>
176-
</div>
177-
</div>
170+
</MessageContainer>
171+
</MessageWrapper>
172+
</HistoryContainer>
173+
</HistoryWrapper>
178174
)
179175
}
180176

181177
const { content } = inProgressMessage || {}
182178

183179
return (
184-
<div className={styles.wrapper}>
185-
<div
186-
ref={listRef}
187-
className={styles.history}
188-
data-testid="ai-chat-history"
189-
>
180+
<HistoryWrapper>
181+
<HistoryContainer as="div" ref={listRef} data-testid="ai-chat-history">
190182
{history.map(getMessage)}
191183
{getMessage(inProgressMessage)}
192184
{content === '' && (
193-
<div className={styles.answerWrapper}>
194-
<div className={styles.answer} data-testid="ai-loading-answer">
185+
<MessageWrapper as="div" messageType={AiChatMessageType.AIMessage}>
186+
<MessageContainer
187+
as="div"
188+
messageType={AiChatMessageType.AIMessage}
189+
data-testid="ai-loading-answer"
190+
>
195191
<LoadingMessage />
196-
</div>
197-
</div>
192+
</MessageContainer>
193+
</MessageWrapper>
198194
)}
199-
<div className={styles.scrollAnchor} ref={scrollDivRef} />
200-
</div>
201-
</div>
195+
<div ref={scrollDivRef} />
196+
</HistoryContainer>
197+
</HistoryWrapper>
202198
)
203199
}
204200

redisinsight/ui/src/components/side-panels/panels/ai-assistant/components/shared/chat-history/styles.module.scss

Lines changed: 0 additions & 79 deletions
This file was deleted.

0 commit comments

Comments
 (0)