diff --git a/src/components/ChatBox/ChatBox.scss b/src/components/ChatBox/ChatBox.scss
index 8403ca00..9a24f0c6 100644
--- a/src/components/ChatBox/ChatBox.scss
+++ b/src/components/ChatBox/ChatBox.scss
@@ -1,9 +1,14 @@
-.scroller {
- overflow-y: scroll;
- scrollbar-width: thin;
- width: 100%;
- opacity: 1;
- margin-right: 0;
+.xpert-chat-scroller {
+ position: relative;
+ flex: 1;
+
+ .messages-list {
+ overflow-y: scroll;
+ scrollbar-width: thin;
+ position: absolute;
+ inset: 0;
+ padding: 1rem 0;
+ }
&:after {
content: ""; /* Add an empty content area after the chat messages */
@@ -11,20 +16,38 @@
height: 0;
clear: both;
}
-}
-.loading {
- font-size: 13px;
- padding-left: 10px;
+ .loading {
+ font-size: 13px;
+ padding-left: 10px;
- &:after {
- overflow: hidden;
- display: inline-block;
- vertical-align: bottom;
- -webkit-animation: ellipsis steps(4,end) 900ms infinite;
- animation: ellipsis steps(4,end) 900ms infinite;
- content: "\2026"; /* ascii code for the ellipsis character */
- width: 0px;
+ &:after {
+ overflow: hidden;
+ display: inline-block;
+ vertical-align: bottom;
+ -webkit-animation: ellipsis steps(4,end) 900ms infinite;
+ animation: ellipsis steps(4,end) 900ms infinite;
+ content: "\2026"; /* ascii code for the ellipsis character */
+ width: 0px;
+ }
+ }
+
+ .separator {
+ position: absolute;
+ z-index: 100;
+ height: 5px;
+ padding: 5px;
+ opacity: 0.3;
+
+ &--top {
+ inset: 0 0 auto 0;
+ background: linear-gradient(180deg, rgba(0, 0, 0, 0.35), transparent);
+ }
+
+ &--bottom {
+ inset: auto 0 0 0;
+ background: linear-gradient(0, rgba(0, 0, 0, 0.35), transparent);
+ }
}
}
diff --git a/src/components/ChatBox/index.jsx b/src/components/ChatBox/index.jsx
index df2eec73..ce98fce7 100644
--- a/src/components/ChatBox/index.jsx
+++ b/src/components/ChatBox/index.jsx
@@ -1,6 +1,5 @@
-import React from 'react';
+import React, { useEffect, useRef } from 'react';
import { useSelector } from 'react-redux';
-import PropTypes from 'prop-types';
import Message from '../Message';
import './ChatBox.scss';
import MessageDivider from '../MessageDivider';
@@ -14,34 +13,53 @@ function isToday(date) {
);
}
+const scrollToBottom = (containerRef, smooth = false) => {
+ setTimeout(() => {
+ containerRef.current.scrollTo({
+ top: containerRef.current.scrollHeight,
+ behavior: smooth ? 'smooth' : 'instant',
+ });
+ });
+};
+
// container for all of the messages
-const ChatBox = ({ chatboxContainerRef }) => {
+const ChatBox = () => {
+ const firstRender = useRef(true);
+ const messageContainerRef = useRef();
+
const { messageList, apiIsLoading } = useSelector(state => state.learningAssistant);
const messagesBeforeToday = messageList.filter((m) => (!isToday(new Date(m.timestamp))));
const messagesToday = messageList.filter((m) => (isToday(new Date(m.timestamp))));
+ useEffect(() => {
+ if (firstRender.current) {
+ scrollToBottom(messageContainerRef);
+ firstRender.current = false;
+ return;
+ }
+
+ scrollToBottom(messageContainerRef, true);
+ }, [messageList.length]);
+
// message divider should not display if no messages or if all messages sent today.
return (
-
- {messagesBeforeToday.map(({ role, content, timestamp }) => (
-
- ))}
- {(messageList.length !== 0 && messagesBeforeToday.length !== 0) && (
)}
- {messagesToday.map(({ role, content, timestamp }) => (
-
- ))}
- {apiIsLoading && (
+
+
+ {messagesBeforeToday.map(({ role, content, timestamp }) => (
+
+ ))}
+ {(messageList.length !== 0 && messagesBeforeToday.length !== 0) && (
)}
+ {messagesToday.map(({ role, content, timestamp }) => (
+
+ ))}
+ {apiIsLoading && (
Xpert is thinking
- )}
+ )}
+
+
+
);
};
-ChatBox.propTypes = {
- chatboxContainerRef: PropTypes.oneOfType([
- PropTypes.func,
- PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
- ]).isRequired,
-};
-
export default ChatBox;
diff --git a/src/components/Message/index.jsx b/src/components/Message/index.jsx
index dda2e725..16180eaa 100644
--- a/src/components/Message/index.jsx
+++ b/src/components/Message/index.jsx
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
const Message = ({ variant, message }) => (
diff --git a/src/components/MessageForm/MessageForm.scss b/src/components/MessageForm/MessageForm.scss
index b58e1e39..b309cd03 100644
--- a/src/components/MessageForm/MessageForm.scss
+++ b/src/components/MessageForm/MessageForm.scss
@@ -1,4 +1,6 @@
.message-form {
+ padding: 0.75rem 1.5rem;
+
.send-message-input {
.pgn__form-control-floating-label {
color: #ADADAD;
@@ -6,6 +8,15 @@
input {
border-radius: 1rem;
+ border: 1px solid #C8C8CC;
}
}
+
+ .pgn__form-control-decorator-group {
+ margin-inline-end: 0;
+ }
+
+ button {
+ color: #8F8F8F;
+ }
}
diff --git a/src/components/MessageForm/index.jsx b/src/components/MessageForm/index.jsx
index cae5616f..ef96649d 100644
--- a/src/components/MessageForm/index.jsx
+++ b/src/components/MessageForm/index.jsx
@@ -61,18 +61,16 @@ const MessageForm = ({ courseId, shouldAutofocus, unitId }) => {
return (
-
-
+
);
};
diff --git a/src/components/Sidebar/Sidebar.scss b/src/components/Sidebar/Sidebar.scss
index 8d385146..53880460 100644
--- a/src/components/Sidebar/Sidebar.scss
+++ b/src/components/Sidebar/Sidebar.scss
@@ -9,8 +9,6 @@
background-color: white;
width: 100%;
max-width: 25rem;
- /* Add smooth scrolling behavior */
- scroll-behavior: smooth;
h1 {
font-size: 1.25rem;
@@ -18,32 +16,38 @@
}
button.chat-close {
- top: 0;
- right: 0;
+ top: 0.75rem;
+ right: 1.5rem;
+ height: 1.5rem;
+ width: 1.5rem;
+
+ .btn-icon__icon {
+ width: 1.375rem !important;
+ height: 1.375rem !important;
+ }
}
.sidebar-header {
+ display: flex;
+ align-items: center;
background: linear-gradient(to left, rgb(58, 101, 108) 0px, rgb(0, 29, 34));
width: 100%;
- height: 60px;
+ height: 48px;
+ padding: 0 1.5rem;
+
svg {
- height: 30px;
+ display: block;
+ height: 24px;
}
}
+ .sidebar-footer {
+
+ }
+
.trial-header {
font-size: 0.9em;
background-color: #F49974;
}
}
-
-.separator {
- z-index: 100;
- width: 100%;
- height: 5px;
- padding: 5px;
- background: -webkit-linear-gradient(270deg, rgba(0, 0, 0, 0.35), transparent);
- background: linear-gradient(180deg, rgba(0, 0, 0, 0.35), transparent);
- opacity: 0.3;
-}
diff --git a/src/components/Sidebar/index.jsx b/src/components/Sidebar/index.jsx
index 5f6425d8..f8cb8e20 100644
--- a/src/components/Sidebar/index.jsx
+++ b/src/components/Sidebar/index.jsx
@@ -1,4 +1,4 @@
-import React, { useRef, useEffect } from 'react';
+import React from 'react';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
@@ -37,42 +37,6 @@ const Sidebar = ({
const { track } = useTrackEvent();
- const chatboxContainerRef = useRef(null);
-
- // this use effect is intended to scroll to the bottom of the chat window, in the case
- // that a message is larger than the chat window height.
- useEffect(() => {
- const messageContainer = chatboxContainerRef.current;
-
- if (messageContainer) {
- const { scrollHeight, clientHeight } = messageContainer;
- const maxScrollTop = scrollHeight - clientHeight;
- const duration = 200;
-
- if (maxScrollTop > 0) {
- const startTime = Date.now();
- const endTime = startTime + duration;
-
- const scroll = () => {
- const currentTime = Date.now();
- const timeFraction = (currentTime - startTime) / duration;
- const scrollTop = maxScrollTop * timeFraction;
-
- messageContainer.scrollTo({
- top: scrollTop,
- behavior: 'smooth',
- });
-
- if (currentTime < endTime) {
- requestAnimationFrame(scroll);
- }
- };
-
- requestAnimationFrame(scroll);
- }
- }
- }, [messageList, isOpen, apiError]);
-
const handleClick = () => {
setIsOpen(false);
@@ -120,10 +84,10 @@ const Sidebar = ({
const getSidebar = () => (
-
+
{upgradeable
@@ -132,11 +96,7 @@ const Sidebar = ({
{getDaysRemainingMessage()}
)}
-
-
+
{
apiError
&& (
@@ -145,7 +105,9 @@ const Sidebar = ({
)
}
- {getMessageForm()}
+
+ {getMessageForm()}
+
);
@@ -165,7 +127,7 @@ const Sidebar = ({
data-testid="sidebar"
>