Open chloe-schoreisz opened 3 years ago
For anyone looking, we figured out a way:
We created our own main.scss
file, that looks like this:
@charset "utf-8";
@import "./variables";
@import "./helpers/mixins";
@import "./helpers/functions";
@import "@chatscope/chat-ui-kit-styles/themes/default/main.scss";
mixins
and functions
are copy pasted from @chatscope/chat-ui-kit-styles/themes/helpers/mixins
and @chatscope/chat-ui-kit-styles/themes/helpers/functions
. variables
is initially copy pasted from @chatscope/chat-ui-kit-styles/themes/variables
, and then updated with the appropriate colors for the different component (keeping the !default
for the color variables)
main.scss
into our app (we're using nextjs, which supports scss direct imports)
⚠️ I'm still getting issues for stylizing the send button and the input box.This will work if your app supports scss. You should compile this to css
if it doesn't.
@chloe-schoreisz Thank you for your explanation. It's awesome that somebody helps me maintaining the project :)
And here is the solution that I use in my projects based on Create React App.
Assuming your app supports scss (e.g. CRA, NEXTjs).
project_root/src/themes/default/_chat-overrides.scss:
/* The path depends on the current location of the scss file */
@import "../../../node_modules/@chatscope/chat-ui-kit-styles/themes/default/variables";
// Here you can override variables from the imported file above. Check its source for a list of available variables
$main-container-border: 0;
$color-text: red;
$conversation-color: pink;
// ... and so on
project_root/src/themes/default/main.scss:
@charset "utf-8";
@import "./chat-overrides";
@import "../../../node_modules/@chatscope/chat-ui-kit-styles/themes/default/main";
// ... any other imports
project_root/src/App.js:
import './themes/default/main.scss';
import MyApp from "./MyApp"
function App() {
return (<MyApp />);
}
export default App;
@chloe-schoreisz
I'm still getting issues for stylizing the send button and the input box
What's your issue with styling these items??
I was trying to obtain a specific color for the SendButton through the custom scss file. I could not change it from there, and I tried all the variables. The only way I was able to change the color was by implementing my own CustomMessageInput, and hardcode the color in the styling.
// CustomMessageInput.tsx
<MessageInput
ref={...}
onSend={sendMessage}
onChange={(_: string, textContent: string) => {
setMessageInputValue(textContent);
}}
value={messageInputValue}
sendButton={false}
attachButton={false}
/>
<SendButton
onClick={() => sendMessage(messageInputValue)}
style={{
color: '#0C3276',
backgroundColor: '#C7FED2',
width: '48px',
height: '45px'
}}
/>
I was also trying to update the icon of the send button, but couldn't find a way
@chloe-schoreisz Your solution is fine, especially when there is a need to make more changes than simply color change.
However, the send button color should be changeable by overriding $send-button-color variable https://github.com/chatscope/chat-ui-kit-styles/blob/6823363a99ef2a6be7eaf6fadd17599b4ad99138/themes/default/_variables.scss#L180 but now I see there is a bug :sweat_smile: (missing !default) I will fix fixed it in here: https://github.com/chatscope/chat-ui-kit-styles/issues/8
Just gave this a try in NextJS with my own project and ran into some issues with the styles not applying despite following the instructions that @supersnager laid out so thought it would be good to share here. The import of the variables.scss file in your custom.scss styles should be happening after your actual custom variables are assigned. We referred to this article to figure this out. Unfortunately, we weren't able to get modular styles to work (in attempts to follow NextJS conventions), having to import and apply the styles globally on _app.tsx.
$color-text: red;
@import "../../../node_modules/@chatscope/chat-ui-kit-styles/themes/default/variables";
@import "../../../node_modules/@chatscope/chat-ui-kit-styles/themes/default/main";
Not sure if this is a quirk of NextJS, but would be interested to know. Thank you!
/* The path depends on the current location of the scss file */ @import "../../../node_modules/@chatscope/chat-ui-kit-styles/themes/default/variables"; // Here you can override variables from the imported file above. Check its source for a list of available variables $main-container-border: 0; $color-text: red; $conversation-color: pink;
Using this approach, I manage to change some of the variables (i.e. the default font family), but only if i replace !default
with !important
, and that's not possible with all variables (i.e. the color variables – they throw an error if I use !important
– do you know a way around?
@axelferdinand Please share the code (e.g. your _chat-overrides.scss ), how do you override values? !default and !important are used for different things, when overriding, you don't use !default.
@supersnager Sure!
_chat-overrides.scss
// Default font family
//
$default-font-family: 'Clan', Helvetica, sans-serif !important;
// Colors
//
$color-primary: #000 !default;
$color-primary-light: #FFF !default;
$color-primary-dark: #000 !default;
$color-primary-dark: #000 !default;
main.scss
@charset "utf-8";
@font-face {
font-family: 'Clan';
src: url('fonts/ClanOffc-News.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Clan';
src: url('fonts/ClanOffc-Bold.woff2') format('woff2');
font-weight: bold;
font-style: bold;
}
@import "./chat-overrides";
@import "../../../node_modules/@chatscope/chat-ui-kit-styles/themes/default/main";
_app.txt
import type { AppProps } from "next/app";
import { FpjsProvider } from "@fingerprintjs/fingerprintjs-pro-react";
import { configureAbly } from "@ably-labs/react-hooks";
import '../themes/default/main.scss';
const prefix = process.env.API_ROOT || "";
const clientId =
Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
configureAbly({
authUrl: `${prefix}/api/createTokenRequest?clientId=${clientId}`,
clientId: clientId,
});
const fpjsPublicApiKey = process.env.FINGERPRINT as string;
export default function App({ Component, pageProps }: AppProps) {
return (
<FpjsProvider
loadOptions={{
apiKey: fpjsPublicApiKey,
}}
>
<Component {...pageProps} />
</FpjsProvider>
);
}
index.txs
import Head from "next/head";
import { useState } from "react";
import { useVisitorData } from "@fingerprintjs/fingerprintjs-pro-react";
import ReactMarkdown from "react-markdown";
import * as timeago from "timeago.js";
import styles from "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
import {
MainContainer,
ChatContainer,
MessageList,
Message,
MessageInput,
ConversationHeader,
TypingIndicator,
} from "@chatscope/chat-ui-kit-react";
import { useChannel } from "@ably-labs/react-hooks";
import { Types } from "ably";
type ConversationEntry = {
message: string;
speaker: "bot" | "user";
date: Date;
id?: string;
};
type request = {
prompt: string;
};
const updateChatbotMessage = (
conversation: ConversationEntry[],
message: Types.Message
): ConversationEntry[] => {
const interactionId = message.data.interactionId;
const updatedConversation = conversation.reduce(
(acc: ConversationEntry[], e: ConversationEntry) => [
...acc,
e.id === interactionId
? { ...e, message: e.message + message.data.token }
: e,
],
[]
);
return conversation.some((e) => e.id === interactionId)
? updatedConversation
: [
...updatedConversation,
{
id: interactionId,
message: message.data.token,
speaker: "bot",
date: new Date(),
},
];
};
export default function Home() {
const [text, setText] = useState("");
const [extendedResult, updateExtendedResult] = useState(false);
const [conversation, setConversation] = useState<ConversationEntry[]>([]);
const [botIsTyping, setBotIsTyping] = useState(false);
const [statusMessage, setStatusMessage] = useState("Skriv spørsmålet ditt...");
const { isLoading, data: visitorData } = useVisitorData(
{ extendedResult },
{ immediate: true }
);
useChannel(visitorData?.visitorId! || "default", (message) => {
switch (message.data.event) {
case "response":
setConversation((state) => updateChatbotMessage(state, message));
break;
case "status":
setStatusMessage(message.data.message);
break;
case "responseEnd":
default:
setBotIsTyping(false);
setStatusMessage("Waiting for query...");
}
});
const submit = async () => {
setConversation((state) => [
...state,
{
message: text,
speaker: "user",
date: new Date(),
},
]);
try {
setBotIsTyping(true);
const response = await fetch("/api/chat", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ prompt: text, userId: visitorData?.visitorId }),
});
await response.json();
} catch (error) {
console.error("Error submitting message:", error);
} finally {
setBotIsTyping(false);
}
setText("");
};
return (
<>
<Head>
<title>Virke</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<div
style={{ position: "relative", height: "98vh", overflow: "hidden" }}
>
<MainContainer>
<ChatContainer>
<ConversationHeader>
<ConversationHeader.Actions></ConversationHeader.Actions>
<ConversationHeader.Content
userName="Få hjelp med det juridiske innholdet på virke.no"
info={statusMessage}
/>
</ConversationHeader>
<MessageList
typingIndicator={
botIsTyping ? (
<TypingIndicator content="Vi jobber med saken..." />
) : null
}
>
{conversation.map((entry, index) => {
return (
<Message
key={index}
style={{ width: "90%" }}
model={{
type: "custom",
sender: entry.speaker,
position: "single",
direction:
entry.speaker === "bot" ? "incoming" : "outgoing",
}}
>
<Message.CustomContent>
<ReactMarkdown>{entry.message}</ReactMarkdown>
</Message.CustomContent>
<Message.Footer
sentTime={timeago.format(entry.date)}
sender={entry.speaker === "bot" ? "Virke" : "Du"}
/>
</Message>
);
})}
</MessageList>
<MessageInput
placeholder="Skriv her..."
onSend={submit}
onChange={(e, text) => {
setText(text);
}}
sendButton={true}
autoFocus
disabled={isLoading}
/>
</ChatContainer>
</MainContainer>
</div>
</main>
</>
);
}
@axelferdinand
Try to remove !default in _chat-overrides.scss
Change this:
$color-primary: #000 !default;
$color-primary-light: #FFF !default;
$color-primary-dark: #000 !default;
$color-primary-dark: #000 !default;
to this:
$color-primary: #000;
$color-primary-light: #FFF;
$color-primary-dark: #000;
$color-primary-dark: #000;
@supersnager I tried that, but it didn't work, unfortunately.
My console says this:
wait - compiling...
event - compiled successfully in 426 ms (434 modules)
...but the colors (or other variables) doesn't update. This is the only thing that will update:
$default-font-family: 'Clan', Helvetica, sans-serif !important;
@axelferdinand I think I have found the source of the problem.
Try to remove the following line from the index.tsx
:
import styles from "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
and remove className
from:
<main className={styles.main}>
Your example is not working because you import main.scss
which includes:
@import "./chat-overrides";
@import "../../../node_modules/@chatscope/chat-ui-kit-styles/themes/default/main";
and next you import @chatscope/chat-ui-kit-styles/dist/default/styles.min.css
The import of the minimized styles overrides a theme imported earlier.
After importing main.scss
all chatscope styles are ready because the theme is built in your app.
So importing @chatscope/chat-ui-kit-styles/dist/default/styles.min.css
is not necessary.
BTW in the @chatscope/chat-ui-kit-styles/dist/default/styles.min.css there is no "main" class.
@supersnager That did indeed work!! Thank you so much!!
Hello I was wondering if there is any way possible to style the chat-ui-kit using the tailwind? I tried with the MainContainer, ChatContainer, MessageList and it worked... However when I tried to style the MessageInput and the MessageSeperator using tailwind I couldn't... so I was wondering if you can help me with that please?
@dolce-emmy What exactly do you want to do?
I want dark theme
I want dark theme
Me too. It'd be nice to just add a dark mode functionality in the kit itself @supersnager
Any updated guide on how to change the style?
Just take these classnames to your styles.css and change accordingly. This overrides the default styles.
div .cs-message-list__typing-indicator-container div { color: #6d4700; }
div .cs-main-container, div .cs-chat-container .cs-message-input { border: 0px; }
div .cs-message--incoming .cs-messagecontent, div .cs-chat-container .cs-message-input, div .psthumb-y, div .psrail-y:hover .psthumb-y, div .psrail-y:active .psthumb-y { background-color: #ffc436; }
div .cs-message-inputcontent-editor, div .cs-message-inputcontent-editor-wrapper, div .cs-message-list, div .psrail-y:hover, div .ps .psrail-y:hover, div .ps__rail-y { background-color: #ffebbb; }
div .cs-message--outgoing .cs-message__content { background-color: #ffa552; }
div .cs-typing-indicator__dot { background-color: #6d4700; }
Next.js
// src/components/chat.scss
@charset "utf-8";
$color-text: white;
$blue: #2894CD;
$green: #61AD4A;
$message-content-incoming-bg-color: $blue;
$message-content-outgoing-bg-color: #444;
$color-secondary: #555;
$message-input-bg-color: white;
$message-input-content-editor-wrapper-bg-color: white;
$message-input-content-editor-color: black;
$button-attachment-color: white;
$button-send-color: $green;
$message-group-header-padding: 0.5rem;
$message-list-scroll-wrapper-padding: 1.2em 1.2em 0 0.8em;
@import "@chatscope/chat-ui-kit-styles/themes/default/variables";
@import "@chatscope/chat-ui-kit-styles/themes/default/main";
In your chat component:
import './chat.scss';
I'm trying to use it on backstage and any of those solutions work at all
I would love to see some documentations on how to stylized the different components (eg. colors, fonts, change of icons, etc)