diff --git a/packages/chat-component/src/main.ts b/packages/chat-component/src/main.ts
index 7ddc7ad3..f9312e97 100644
--- a/packages/chat-component/src/main.ts
+++ b/packages/chat-component/src/main.ts
@@ -16,6 +16,7 @@ import iconDoubleCheck from '../public/svg/doublecheck-icon.svg?inline';
import iconCopyToClipboard from '../public/svg/copy-icon.svg?inline';
import iconSend from '../public/svg/send-icon.svg?inline';
import iconClose from '../public/svg/close-icon.svg?inline';
+import iconQuestion from '../public/svg/question-icon.svg?inline';
/**
* A chat component that allows the user to ask questions and get answers from an API.
@@ -385,20 +386,29 @@ export class ChatComponent extends LitElement {
// render followup questions
if (followupQuestions && followupQuestions.length > 0) {
return html`
-
+
+
+
+
`;
}
diff --git a/packages/chat-component/src/style.ts b/packages/chat-component/src/style.ts
index b9112e2b..bc78656f 100644
--- a/packages/chat-component/src/style.ts
+++ b/packages/chat-component/src/style.ts
@@ -9,12 +9,13 @@ export const mainStyle = css`
--text-color: #123f58;
--primary-color: rgba(241, 255, 165, 0.6);
--white: #fff;
+ --black: #111111;
--light-gray: #e3e3e3;
--dark-gray: #4e5288;
- --accent-high: #0040ff;
+ --accent-high: #b200ff;
--accent-dark: #002b23;
--accent-light: #e6fbf7;
- --accent-lighter: rgba(140, 222, 242, 0.4);
+ --accent-lighter: rgba(242, 140, 241, 0.4);
--error-color: #8a0000;
}
:host(.dark) {
@@ -73,8 +74,8 @@ export const mainStyle = css`
display: flex;
width: 100%;
height: 0;
- background: var(--accent-dark);
- z-index: 1;
+ background: var(--black);
+ z-index: 2;
opacity: 0.8;
transition: all 0.3s ease-in-out;
}
@@ -147,7 +148,7 @@ export const mainStyle = css`
.aside {
top: 30px;
left: auto;
- z-index: 2;
+ z-index: 3;
background: var(--white);
display: block;
padding: 20px;
@@ -164,7 +165,10 @@ export const mainStyle = css`
position: sticky;
bottom: 0;
z-index: 1;
+ border-radius: 10px;
background: var(--secondary-color);
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ padding: 15px 10px 50px;
}
.form__label {
display: block;
@@ -185,7 +189,7 @@ export const mainStyle = css`
border-bottom: 4px solid var(--accent-high);
}
.aside__link:not(.active):hover {
- border-bottom: 4px solid var(--accent-light);
+ border-bottom: 4px solid var(--accent-lighter);
cursor: pointer;
}
.aside__link {
@@ -338,23 +342,30 @@ export const mainStyle = css`
.user-message .chat__txt--info {
text-align: right;
}
+ .items__listWrapper {
+ border-top: 1px dotted var(--light-gray);
+ display: flex;
+ }
+ .items__listWrapper .icon {
+ padding-top: 35px;
+ opacity: 0.3;
+ }
.items__list.followup {
display: flex;
flex-direction: row;
padding: 20px;
list-style-type: none;
flex-wrap: wrap;
- border-top: 1px dotted var(--light-gray);
}
.items__list {
- margin-top: 10px;
+ margin: 10px 0;
display: block;
}
.items__listItem--followup {
cursor: pointer;
- padding: 0 5px;
- border-radius: 5px;
- border: 1px solid var(--accent-high);
+ padding: 0 15px;
+ border-radius: 15px;
+ border: 2px solid var(--accent-high);
margin: 5px;
}
.items__listItem--citation {
@@ -387,6 +398,7 @@ export const mainStyle = css`
text-decoration: none;
color: var(--text-color);
display: block;
+ font-size: 1.2rem;
}
.defaults__list {
list-style-type: none;
@@ -424,6 +436,7 @@ export const mainStyle = css`
transition: all 0.3s ease-in-out;
}
.defaults__span {
+ color: var(--accent-high);
font-weight: bold;
display: block;
margin-top: 20px;
diff --git a/packages/chat-component/src/utils/index.ts b/packages/chat-component/src/utils/index.ts
index 7b05476a..a5653f73 100644
--- a/packages/chat-component/src/utils/index.ts
+++ b/packages/chat-component/src/utils/index.ts
@@ -1,19 +1,17 @@
// Util functions to process text from response, clean it up and style it
// We keep it in this util file because we may not need it once we introduce
// a new response format with TypeChat or a similar component
-import { NEXT_QUESTION_INDICATOR } from '../config/global-config.js';
// Let's give the response a type so we can use it in the component
export function processText(inputText: string, arrays: Array | Array>): ProcessTextReturn {
// Keeping all the regex at this level so they can be easily changed or removed
- const nextQuestionIndicator = NEXT_QUESTION_INDICATOR;
+ const nextQuestionMatch = `Next questions:|<<([^>]+)>>`;
const findCitations = /\[(.*?)]/g;
- const findFollowingSteps = /steps:(.*?)(?:Next Questions:|<<|$)/s;
+ const findFollowingSteps = /:(.*?)(?:Follow-up questions:|Next questions:|<<|$)/s;
const findNextQuestions = /Next Questions:(.*?)$/s;
const findQuestionsbyDoubleArrow = /<<([^<>]+)>>/g;
- const findNumberedItems = /\d+\.\s+/;
-
+ const findNumberedItems = /^\d+\.\s/;
// Find and process citations
const citation: NonNullable = {};
let citations: Citation[] = [];
@@ -24,7 +22,7 @@ export function processText(inputText: string, arrays: Array | Arr
if (!citation[citationText]) {
citation[citationText] = referenceCounter++;
}
- return `[${citation[citationText]}]`;
+ return `${citation[citationText]}`;
});
citations = Object.keys(citation).map((text, index) => ({
ref: index + 1,
@@ -34,36 +32,29 @@ export function processText(inputText: string, arrays: Array | Arr
// Because the format for followup questions is inconsistent
// and sometimes it includes a Next Questions prefix, we need do some extra work
- const nextQuestionsIndex = replacedText.indexOf(nextQuestionIndicator);
- const hasNextQuestions = nextQuestionsIndex !== -1;
+ const hasNextQuestions = replacedText.includes(nextQuestionMatch);
// Find and store 'follow this steps' portion of the response
// considering the fact that sometimes the 'next questions' indicator is present
// and sometimes it's not
const followingStepsMatch = replacedText.match(findFollowingSteps);
const followingStepsText = followingStepsMatch ? followingStepsMatch[1].trim() : '';
const followingSteps = followingStepsText.split('\n').filter(Boolean);
- arrays[1] = followingSteps;
+ const cleanFollowingSteps = followingSteps.map((item) => {
+ return item.replace(findNumberedItems, '');
+ });
+ arrays[1] = cleanFollowingSteps;
// Determine which regex to use, depending if the indicator is present
const nextRegex = hasNextQuestions ? findNextQuestions : findQuestionsbyDoubleArrow;
const nextQuestionsMatch = replacedText.match(nextRegex);
- const nextQuestionsText = nextQuestionsMatch ? nextQuestionsMatch[1].trim() : '';
let nextQuestions: string[] = [];
- // Find and store 'follow up questions' portion of the response
- if (hasNextQuestions) {
- // Remove the 'Next Questions' prefix from the response
- replacedText = replacedText.replace(nextQuestionIndicator, '');
- nextQuestions = nextQuestionsText.split(findNumberedItems).filter(Boolean);
- } else {
- nextQuestions = nextQuestionsText.split('\n').filter(Boolean);
- nextQuestions = cleanUpFollowUp(nextQuestions);
- }
+ nextQuestions = cleanUpFollowUp([...(nextQuestionsMatch as string[])]);
// Remove the 'steps', 'citation' and 'next questions' portions of the response
// from the response answer
- const stepsIndex = replacedText.indexOf('steps:');
+ const stepsIndex = replacedText.indexOf('s:');
// eslint-disable-next-line unicorn/no-negated-condition, unicorn/prefer-string-slice
- replacedText = stepsIndex !== -1 ? inputText.substring(0, stepsIndex + 6) : inputText;
+ replacedText = stepsIndex !== -1 ? inputText.substring(0, stepsIndex + 4) : inputText;
arrays[2] = nextQuestions;
return { replacedText, arrays };