mirror of
https://github.com/QuivrHQ/quivr.git
synced 2024-12-14 07:59:00 +03:00
feat(frontend): dark mode (#2369)
# Description Please include a summary of the changes and the related issue. Please also include relevant motivation and context. ## Checklist before requesting a review Please delete options that are not relevant. - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented hard-to-understand areas - [ ] I have ideally added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged ## Screenshots (if appropriate):
This commit is contained in:
parent
d42323d34a
commit
d7d1a0155b
@ -20,6 +20,7 @@ import { ChatsProvider } from "@/lib/context/ChatsProvider";
|
||||
import { MenuProvider } from "@/lib/context/MenuProvider/Menu-provider";
|
||||
import { SearchModalProvider } from "@/lib/context/SearchModalProvider/search-modal-provider";
|
||||
import { useSupabase } from "@/lib/context/SupabaseProvider";
|
||||
import { UserSettingsProvider } from "@/lib/context/UserSettingsProvider/User-settings.provider";
|
||||
import { IntercomProvider } from "@/lib/helpers/intercom/IntercomProvider";
|
||||
import { UpdateMetadata } from "@/lib/helpers/updateMetadata";
|
||||
import { usePageTracking } from "@/services/analytics/june/usePageTracking";
|
||||
@ -90,19 +91,21 @@ const queryClient = new QueryClient();
|
||||
const AppWithQueryClient = ({ children }: PropsWithChildren): JSX.Element => {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<BrainProvider>
|
||||
<KnowledgeToFeedProvider>
|
||||
<BrainCreationProvider>
|
||||
<MenuProvider>
|
||||
<ChatsProvider>
|
||||
<ChatProvider>
|
||||
<App>{children}</App>
|
||||
</ChatProvider>
|
||||
</ChatsProvider>
|
||||
</MenuProvider>
|
||||
</BrainCreationProvider>
|
||||
</KnowledgeToFeedProvider>
|
||||
</BrainProvider>
|
||||
<UserSettingsProvider>
|
||||
<BrainProvider>
|
||||
<KnowledgeToFeedProvider>
|
||||
<BrainCreationProvider>
|
||||
<MenuProvider>
|
||||
<ChatsProvider>
|
||||
<ChatProvider>
|
||||
<App>{children}</App>
|
||||
</ChatProvider>
|
||||
</ChatsProvider>
|
||||
</MenuProvider>
|
||||
</BrainCreationProvider>
|
||||
</KnowledgeToFeedProvider>
|
||||
</BrainProvider>
|
||||
</UserSettingsProvider>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -15,7 +14,7 @@
|
||||
|
||||
&:hover,
|
||||
&.selected {
|
||||
background-color: Colors.$primary-light;
|
||||
background-color: var(--background-special-1);
|
||||
font-weight: 550;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/BoxShadow.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
.mentions_list_wrapper {
|
||||
display: flex;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
flex-direction: column;
|
||||
padding: Spacings.$spacing03;
|
||||
box-shadow: 0 1px 2px rgb(0, 0, 0, 0.25);
|
||||
box-shadow: BoxShadow.$small;
|
||||
border-radius: Radius.$normal;
|
||||
gap: Spacings.$spacing03;
|
||||
max-width: 300px;
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/IconSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
@ -8,6 +7,6 @@
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: Colors.$accent;
|
||||
color: var(--accent);
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
.chat_container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
gap: Spacings.$spacing03;
|
||||
border-radius: Radius.$big;
|
||||
border: 1px solid Colors.$lighter-grey;
|
||||
border: 1px solid var(--border-0);
|
||||
overflow: hidden;
|
||||
|
||||
.chat_wrapper {
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -26,7 +25,7 @@
|
||||
}
|
||||
|
||||
.uploaded_knowledges_title {
|
||||
color: Colors.$dark-grey;
|
||||
color: var(--text-2);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -11,14 +10,14 @@
|
||||
column-gap: Spacings.$spacing05;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px dashed Colors.$lighter-grey;
|
||||
border: 1px dashed var(--border-0);
|
||||
border-radius: Radius.$big;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
|
||||
&.dragging {
|
||||
border: 3px dashed Colors.$accent;
|
||||
background-color: Colors.$lightest-black;
|
||||
border: 3px dashed var(--accent);
|
||||
background-color: var(--background-3);
|
||||
}
|
||||
|
||||
.input {
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
@ -30,11 +29,11 @@
|
||||
display: flex;
|
||||
gap: Spacings.$spacing02;
|
||||
align-items: center;
|
||||
color: Colors.$dark-grey;
|
||||
color: var(--text-2);
|
||||
}
|
||||
|
||||
.message_row_content {
|
||||
background-color: Colors.$lightest-grey;
|
||||
background-color: var(--background-2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +46,7 @@
|
||||
|
||||
.message_row_content {
|
||||
align-self: flex-start;
|
||||
background-color: Colors.$primary-lightest;
|
||||
background-color: var(--background-special-0);
|
||||
margin-left: 1px;
|
||||
position: relative;
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
|
||||
@ -6,9 +6,13 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: Spacings.$spacing02;
|
||||
color: Colors.$black;
|
||||
color: var(--text-3);
|
||||
overflow: hidden;
|
||||
|
||||
.dark_image {
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
||||
.brain_name {
|
||||
@include Typography.EllipsisOverflow;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import Image from "next/image";
|
||||
import { Fragment, useEffect, useState } from "react";
|
||||
|
||||
import { useBrainApi } from "@/lib/api/brain/useBrainApi";
|
||||
import Icon from "@/lib/components/ui/Icon/Icon";
|
||||
import { useUserSettingsContext } from "@/lib/context/UserSettingsProvider/hooks/useUserSettingsContext";
|
||||
|
||||
import styles from "./QuestionBrain.module.scss";
|
||||
|
||||
@ -17,7 +17,7 @@ export const QuestionBrain = ({
|
||||
const [brainLogoUrl, setBrainLogoUrl] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
const { isDarkMode } = useUserSettingsContext();
|
||||
const { getBrain } = useBrainApi();
|
||||
|
||||
const getBrainLogoUrl = async () => {
|
||||
@ -41,11 +41,13 @@ export const QuestionBrain = ({
|
||||
|
||||
return (
|
||||
<div data-testid="brain-tags" className={styles.brain_name_wrapper}>
|
||||
{brainLogoUrl ? (
|
||||
<Image src={brainLogoUrl} alt="brainLogo" width={18} height={18} />
|
||||
) : (
|
||||
<Icon name="brain" color="primary" size="normal" />
|
||||
)}
|
||||
<Image
|
||||
className={isDarkMode ? styles.dark_image : ""}
|
||||
src={brainLogoUrl ? brainLogoUrl : "/default_brain_image.png"}
|
||||
alt="logo_image"
|
||||
width={18}
|
||||
height={18}
|
||||
/>
|
||||
<span className={styles.brain_name}>{brainName}</span>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,11 +1,10 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
|
||||
.prompt_name_wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: Colors.$black;
|
||||
color: var(--text-3);
|
||||
font-size: Typography.$small;
|
||||
overflow: hidden;
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -11,7 +10,7 @@
|
||||
gap: Spacings.$spacing03;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
border: 1px solid Colors.$lightest-black;
|
||||
border: 1px solid var(--border-1);
|
||||
border-radius: Radius.$big;
|
||||
|
||||
.title_wrapper {
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
.main_container {
|
||||
@ -9,7 +8,7 @@
|
||||
.chat_page_container {
|
||||
display: flex;
|
||||
flex: 1 1 0%;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
padding-block: Spacings.$spacing06;
|
||||
padding-inline: Spacings.$spacing09;
|
||||
display: flex;
|
||||
|
48
frontend/app/colors.css
Normal file
48
frontend/app/colors.css
Normal file
@ -0,0 +1,48 @@
|
||||
:root {
|
||||
/* White */
|
||||
--white-0: #ffffff;
|
||||
--white-1: #fafafa;
|
||||
--white-2: #fcfaf6;
|
||||
|
||||
/* Black */
|
||||
--black-0: #111111;
|
||||
--black-1: #171717;
|
||||
--black-2: #1c1c1c;
|
||||
--black-3: #222222;
|
||||
--black-4: #272727;
|
||||
--black-5: #2d2d2d;
|
||||
--black-6: #323232;
|
||||
--black-7: #383838;
|
||||
|
||||
/* Grey */
|
||||
--grey-O: #707070;
|
||||
--grey-1: #c8c8c8;
|
||||
--grey-2: #cbcbcb;
|
||||
--grey-3: #e7e9ec;
|
||||
--grey-4: #d3d3d3;
|
||||
--grey-5: #f5f5f5;
|
||||
|
||||
/* Primary */
|
||||
--primary-0: #6142d4;
|
||||
--primary-1: #d0c6f2;
|
||||
--primary-2: #f5f3fd;
|
||||
|
||||
/* Accent */
|
||||
--accent: #13abba;
|
||||
|
||||
/* Gold */
|
||||
--gold: #b8860b;
|
||||
|
||||
/* Error */
|
||||
--dangerous-dark: #e30c17;
|
||||
--dangerous: #9b373c;
|
||||
--dangerous-lightest: #eedddd;
|
||||
|
||||
/* Warning */
|
||||
--warning: #c77d33;
|
||||
--warning-lightest: #e9d9c9;
|
||||
|
||||
/* Success */
|
||||
--success: #47a455;
|
||||
--success-lightest: #d0edd4;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
@import "tailwindcss/base";
|
||||
@import "tailwindcss/components";
|
||||
@import "tailwindcss/utilities";
|
||||
@import './colors.css';
|
||||
|
||||
main {
|
||||
@apply max-w-screen-xl mx-auto flex flex-col;
|
||||
@ -48,3 +49,70 @@ div:focus {
|
||||
@apply h-[100vh] supports-[height:100cqh]:h-[100cqh] supports-[height:100svh]:h-[100svh];
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
/* Backgrounds */
|
||||
--background-0: var(--white-0);
|
||||
--background-1: var(--white-1);
|
||||
--background-2: var(--grey-5);
|
||||
--background-3: var(--grey-3);
|
||||
--background-4: var(--grey-0);
|
||||
--background-5: var(--black-0);
|
||||
--background-special-0: var(--primary-2);
|
||||
--background-special-1: var(--primary-1);
|
||||
--background-blur: rgba(0, 0, 0, 0.9);
|
||||
|
||||
/* Borders */
|
||||
--border-0: var(--grey-4);
|
||||
--border-1: var(--grey-3);
|
||||
--border-2: var(--grey-1);
|
||||
|
||||
/* Icons */
|
||||
--icon-0: var(--white-0);
|
||||
--icon-1: var(--grey-1);
|
||||
--icon-2: var(--grey-0);
|
||||
--icon-3: var(--black-0);
|
||||
|
||||
/* Text */
|
||||
--text-0: var(--white-0);
|
||||
--text-1: var(--grey-1);
|
||||
--text-2: var(--grey-0);
|
||||
--text-3: var(--black-0);
|
||||
|
||||
/* Box Shadow */
|
||||
--box-shadow: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
body.dark_mode {
|
||||
/* Backgrounds */
|
||||
--background-0: var(--black-0);
|
||||
--background-1: var(--black-1);
|
||||
--background-2: var(--black-2);
|
||||
--background-3: var(--black-3);
|
||||
--background-4: var(--black-4);
|
||||
--background-5: var(--black-5);
|
||||
--background-special-0: var(--black-3);
|
||||
--background-special-1: var(--black-5);
|
||||
--background-opposite: var(--white-0);
|
||||
--background-blur: rgba(0, 0, 0, 0.9);
|
||||
|
||||
/* Borders */
|
||||
--border-0: var(--white-0);
|
||||
--border-1: var(--grey-1);
|
||||
--border-2: var(--grey-2);
|
||||
|
||||
/* Icons */
|
||||
--icon-0: var(--black-0);
|
||||
--icon-1: var(--grey-0);
|
||||
--icon-2: var(--grey-1);
|
||||
--icon-3: var(--white-0);
|
||||
|
||||
/* Text */
|
||||
--text-0: var(--black-0);
|
||||
--text-1: var(--grey-0);
|
||||
--text-2: var(--grey-1);
|
||||
--text-3: var(--white-0);
|
||||
|
||||
/* Box Shadow */
|
||||
--box-shadow: rgba(255, 255, 255, 0.25);
|
||||
}
|
8
frontend/app/layout.module.scss
Normal file
8
frontend/app/layout.module.scss
Normal file
@ -0,0 +1,8 @@
|
||||
.body {
|
||||
color: var(--text-3);
|
||||
background-color: var(--background-0);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import { createServerComponentSupabaseClient } from "@supabase/auth-helpers-nextjs";
|
||||
import { Analytics as VercelAnalytics } from "@vercel/analytics/react";
|
||||
import { Outfit } from "next/font/google";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { ToastProvider } from "@/lib/components/ui/Toast";
|
||||
@ -8,8 +7,7 @@ import { SupabaseProvider } from "@/lib/context/SupabaseProvider";
|
||||
|
||||
import { App } from "./App";
|
||||
import "./globals.css";
|
||||
|
||||
const inter = Outfit({ subsets: ["latin"] });
|
||||
import styles from "./layout.module.scss";
|
||||
|
||||
export const metadata = {
|
||||
title: "Quivr - Get a Second Brain with Generative AI",
|
||||
@ -34,7 +32,8 @@ const RootLayout = async ({
|
||||
return (
|
||||
<html lang="en">
|
||||
<body
|
||||
className={`bg-white text-black h-screen flex flex-col dark:bg-black dark:text-white w-full ${inter.className}`}
|
||||
className={styles.body}
|
||||
// className={`bg-white text-black h-screen flex flex-col dark:bg-black dark:text-white w-full ${inter.className}`}
|
||||
>
|
||||
<ToastProvider>
|
||||
<SupabaseProvider session={session}>
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/IconSizes.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@ -17,7 +16,7 @@
|
||||
}
|
||||
|
||||
.search_page_container {
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
@ -48,14 +47,14 @@
|
||||
@include Typography.Big;
|
||||
|
||||
.quivr_text_primary {
|
||||
color: Colors.$primary;
|
||||
color: var(--primary-0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shortcuts_card_wrapper {
|
||||
background-color: Colors.$lightest-grey;
|
||||
background-color: var(--background-2);
|
||||
padding: Spacings.$spacing05;
|
||||
gap: Spacings.$spacing03;
|
||||
border-radius: Radius.$big;
|
||||
@ -66,7 +65,7 @@
|
||||
gap: Spacings.$spacing02;
|
||||
|
||||
.shortcut {
|
||||
color: Colors.$primary;
|
||||
color: var(--primary-0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import PageHeader from "@/lib/components/PageHeader/PageHeader";
|
||||
import { UploadDocumentModal } from "@/lib/components/UploadDocumentModal/UploadDocumentModal";
|
||||
import { SearchBar } from "@/lib/components/ui/SearchBar/SearchBar";
|
||||
import { useSupabase } from "@/lib/context/SupabaseProvider";
|
||||
import { useUserSettingsContext } from "@/lib/context/UserSettingsProvider/hooks/useUserSettingsContext";
|
||||
import { redirectToLogin } from "@/lib/router/redirectToLogin";
|
||||
import { ButtonType } from "@/lib/types/QuivrButton";
|
||||
|
||||
@ -18,6 +19,7 @@ const Search = (): JSX.Element => {
|
||||
const pathname = usePathname();
|
||||
const { session } = useSupabase();
|
||||
const { setIsBrainCreationModalOpened } = useBrainCreationContext();
|
||||
const { isDarkMode } = useUserSettingsContext();
|
||||
|
||||
useEffect(() => {
|
||||
if (session === null) {
|
||||
@ -44,7 +46,7 @@ const Search = (): JSX.Element => {
|
||||
<div className={styles.search_page_container}>
|
||||
<div className={styles.main_wrapper}>
|
||||
<div className={styles.quivr_logo_wrapper}>
|
||||
<QuivrLogo size={80} color="black" />
|
||||
<QuivrLogo size={80} color={isDarkMode ? "white" : "black"} />
|
||||
<div className={styles.quivr_text}>
|
||||
<span>Talk to </span>
|
||||
<span className={styles.quivr_text_primary}>Quivr</span>
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -14,15 +13,19 @@
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
margin-block: Spacings.$spacing03;
|
||||
border: 1px solid Colors.$lightest-black;
|
||||
border: 1px solid var(--border-1);
|
||||
border-radius: Radius.$normal;
|
||||
padding-block: Spacings.$spacing03;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
|
||||
&:hover {
|
||||
border-color: Colors.$primary;
|
||||
background-color: Colors.$primary-lightest;
|
||||
border-color: var(--primary-0);
|
||||
background-color: var(--background-special-0);
|
||||
}
|
||||
|
||||
.dark_image {
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
||||
.brain_info_wrapper {
|
||||
@ -37,13 +40,13 @@
|
||||
.name {
|
||||
@include Typography.EllipsisOverflow;
|
||||
width: 200px;
|
||||
color: Colors.$black;
|
||||
color: var(--text-3);
|
||||
}
|
||||
|
||||
.description {
|
||||
@include Typography.EllipsisOverflow;
|
||||
flex: 1;
|
||||
color: Colors.$dark-grey;
|
||||
color: var(--text-2);
|
||||
}
|
||||
|
||||
@media (max-width: ScreenSizes.$small) {
|
||||
|
@ -9,6 +9,7 @@ import Icon from "@/lib/components/ui/Icon/Icon";
|
||||
import { OptionsModal } from "@/lib/components/ui/OptionsModal/OptionsModal";
|
||||
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
||||
import { MinimalBrainForUser } from "@/lib/context/BrainProvider/types";
|
||||
import { useUserSettingsContext } from "@/lib/context/UserSettingsProvider/hooks/useUserSettingsContext";
|
||||
import { Option } from "@/lib/types/Options";
|
||||
|
||||
import styles from "./BrainItem.module.scss";
|
||||
@ -32,6 +33,7 @@ export const BrainItem = ({ brain, even }: BrainItemProps): JSX.Element => {
|
||||
brainId: brain.id,
|
||||
userAccessibleBrains: allBrains,
|
||||
});
|
||||
const { isDarkMode } = useUserSettingsContext();
|
||||
|
||||
const iconRef = useRef<HTMLDivElement | null>(null);
|
||||
const optionsRef = useRef<HTMLDivElement | null>(null);
|
||||
@ -67,7 +69,7 @@ export const BrainItem = ({ brain, even }: BrainItemProps): JSX.Element => {
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
}, [isDarkMode]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -77,16 +79,18 @@ export const BrainItem = ({ brain, even }: BrainItemProps): JSX.Element => {
|
||||
${styles.brain_item_wrapper}
|
||||
`}
|
||||
>
|
||||
{brain.integration_logo_url ? (
|
||||
<Image
|
||||
src={brain.integration_logo_url}
|
||||
alt="logo_image"
|
||||
width={18}
|
||||
height={18}
|
||||
/>
|
||||
) : (
|
||||
<Icon name="brain" size="normal" color="primary" />
|
||||
)}
|
||||
<Image
|
||||
className={isDarkMode ? styles.dark_image : ""}
|
||||
src={
|
||||
brain.integration_logo_url
|
||||
? brain.integration_logo_url
|
||||
: "/default_brain_image.png"
|
||||
}
|
||||
alt="logo_image"
|
||||
width={18}
|
||||
height={18}
|
||||
/>
|
||||
|
||||
<Link
|
||||
className={styles.brain_info_wrapper}
|
||||
href={`/studio/${brain.id}`}
|
||||
@ -94,7 +98,6 @@ export const BrainItem = ({ brain, even }: BrainItemProps): JSX.Element => {
|
||||
<span className={styles.name}>{brain.name}</span>
|
||||
<span className={styles.description}>{brain.description}</span>
|
||||
</Link>
|
||||
|
||||
<div>
|
||||
<div
|
||||
ref={iconRef}
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -17,7 +16,7 @@
|
||||
display: flex;
|
||||
padding: Spacings.$spacing05;
|
||||
gap: Spacings.$spacing05;
|
||||
background-color: Colors.$highlight;
|
||||
background-color: var(--background-1);
|
||||
margin-bottom: Spacings.$spacing03;
|
||||
padding-left: Spacings.$spacing09;
|
||||
|
||||
@ -26,7 +25,7 @@
|
||||
}
|
||||
|
||||
.description {
|
||||
color: Colors.$dark-grey;
|
||||
color: var(--text-2);
|
||||
}
|
||||
|
||||
@media (max-width: ScreenSizes.$small) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -13,15 +12,15 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-block: Spacings.$spacing03;
|
||||
border: 1px solid Colors.$lightest-black;
|
||||
border: 1px solid var(--border-1);
|
||||
border-radius: Radius.$normal;
|
||||
padding-block: Spacings.$spacing03;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
|
||||
&:hover {
|
||||
border-color: Colors.$primary;
|
||||
background-color: Colors.$primary-lightest;
|
||||
border-color: var(--primary-0);
|
||||
background-color: var(--background-special-0);
|
||||
}
|
||||
|
||||
.left {
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
|
@ -1,4 +1,4 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/BoxShadow.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -11,9 +11,9 @@
|
||||
|
||||
.section_wrapper {
|
||||
border-radius: Radius.$big;
|
||||
background-color: Colors.$highlight;
|
||||
background-color: var(--background-1);
|
||||
padding: Spacings.$spacing05;
|
||||
box-shadow: 0 1px 2px rgb(0, 0, 0, 0.25);
|
||||
box-shadow: BoxShadow.$small;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: Spacings.$spacing05;
|
||||
|
@ -1,4 +1,4 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/BoxShadow.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -15,10 +15,10 @@
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: Spacings.$spacing05;
|
||||
box-shadow: 0 1px 2px rgb(0, 0, 0, 0.25);
|
||||
box-shadow: BoxShadow.$small;
|
||||
border-radius: Radius.$big;
|
||||
padding: Spacings.$spacing06;
|
||||
background-color: Colors.$highlight;
|
||||
background-color: var(--background-1);
|
||||
|
||||
.section_title {
|
||||
@include Typography.H3;
|
||||
@ -63,10 +63,10 @@
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: Spacings.$spacing05;
|
||||
box-shadow: 0 1px 2px rgb(0, 0, 0, 0.25);
|
||||
box-shadow: BoxShadow.$small;
|
||||
border-radius: Radius.$big;
|
||||
padding: Spacings.$spacing06;
|
||||
background-color: Colors.$highlight;
|
||||
background-color: var(--background-1);
|
||||
|
||||
.section_title {
|
||||
@include Typography.H3;
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
@ -18,7 +17,7 @@
|
||||
width: 80%;
|
||||
height: 15px;
|
||||
border-radius: Radius.$normal;
|
||||
background: Colors.$primary-light;
|
||||
background: var(--primary-1);
|
||||
outline: none;
|
||||
-webkit-transition: 0.2s;
|
||||
transition: opacity 0.2s;
|
||||
@ -34,15 +33,7 @@
|
||||
width: 15px;
|
||||
height: 30px;
|
||||
border-radius: Radius.$big;
|
||||
background: Colors.$primary; /* Changez la couleur ici */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
background: #4caf50; /* Changez la couleur ici */
|
||||
background: var(--primary-0);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -40,6 +39,10 @@
|
||||
cursor: pointer;
|
||||
width: 120px;
|
||||
|
||||
.dark_image {
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
||||
.brain_title {
|
||||
font-size: Typography.$medium;
|
||||
font-weight: 500;
|
||||
@ -47,11 +50,11 @@
|
||||
|
||||
&:hover,
|
||||
&.selected {
|
||||
border-color: Colors.$primary;
|
||||
background-color: Colors.$primary-lightest;
|
||||
border-color: var(--primary-0);
|
||||
background-color: var(--background-special-0);
|
||||
|
||||
.brain_title {
|
||||
color: Colors.$primary;
|
||||
color: var(--primary-0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { IntegrationBrains } from "@/lib/api/brain/types";
|
||||
import { MessageInfoBox } from "@/lib/components/ui/MessageInfoBox/MessageInfoBox";
|
||||
import { Tag } from "@/lib/components/ui/Tag/Tag";
|
||||
import Tooltip from "@/lib/components/ui/Tooltip/Tooltip";
|
||||
import { useUserSettingsContext } from "@/lib/context/UserSettingsProvider/hooks/useUserSettingsContext";
|
||||
|
||||
import styles from "./BrainCatalogue.module.scss";
|
||||
|
||||
@ -19,6 +20,7 @@ export const BrainCatalogue = ({
|
||||
}): JSX.Element => {
|
||||
const { setCurrentSelectedBrain, currentSelectedBrain } =
|
||||
useBrainCreationContext();
|
||||
const { isDarkMode } = useUserSettingsContext();
|
||||
|
||||
return (
|
||||
<div className={styles.cards_wrapper}>
|
||||
@ -47,6 +49,7 @@ export const BrainCatalogue = ({
|
||||
}`}
|
||||
>
|
||||
<Image
|
||||
className={isDarkMode ? styles.dark_image : ""}
|
||||
src={brain.integration_logo_url}
|
||||
alt={brain.integration_name}
|
||||
width={50}
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -17,7 +16,7 @@
|
||||
.circle {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
background-color: Colors.$primary;
|
||||
background-color: var(--primary-0);
|
||||
border-radius: Radius.$circle;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -35,43 +34,43 @@
|
||||
|
||||
&.done_step {
|
||||
.circle {
|
||||
background-color: Colors.$success;
|
||||
background-color: var(--success);
|
||||
}
|
||||
|
||||
.step_info {
|
||||
.step_status {
|
||||
color: Colors.$success;
|
||||
color: var(--success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.current_step {
|
||||
.circle {
|
||||
background-color: Colors.$white;
|
||||
border: 1px solid Colors.$primary;
|
||||
background-color: var(--background-0);
|
||||
border: 1px solid var(--primary-0);
|
||||
}
|
||||
|
||||
.inside_circle {
|
||||
background-color: Colors.$primary;
|
||||
background-color: var(--primary-0);
|
||||
width: 70%;
|
||||
height: 70%;
|
||||
}
|
||||
|
||||
.step_info {
|
||||
.step_status {
|
||||
color: Colors.$primary;
|
||||
color: var(--primary-0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.pending_step {
|
||||
.circle {
|
||||
background-color: Colors.$primary-light;
|
||||
background-color: var(--primary-1);
|
||||
}
|
||||
|
||||
.step_info {
|
||||
.step_status {
|
||||
color: Colors.$normal-grey;
|
||||
color: var(--text-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,7 +84,7 @@
|
||||
|
||||
.step_index {
|
||||
white-space: nowrap;
|
||||
color: Colors.$normal-grey;
|
||||
color: var(--text-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,12 +93,12 @@
|
||||
flex-grow: 1;
|
||||
height: 4px;
|
||||
border-radius: Radius.$big;
|
||||
background-color: Colors.$primary-light;
|
||||
background-color: var(--primary-1);
|
||||
margin: 0 8px;
|
||||
margin-top: Spacings.$spacing05;
|
||||
|
||||
&.done {
|
||||
background-color: Colors.$success;
|
||||
background-color: var(--success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
|
||||
.current_brain_wrapper {
|
||||
background-color: Colors.$lightest-grey;
|
||||
background-color: var(--background-2);
|
||||
padding-inline: Spacings.$spacing05;
|
||||
padding-block: Spacings.$spacing01;
|
||||
font-size: Typography.$small;
|
||||
color: Colors.$normal-grey;
|
||||
color: var(--text-1);
|
||||
|
||||
.brain_infos {
|
||||
display: flex;
|
||||
@ -31,8 +30,12 @@
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
|
||||
.dark_image {
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
||||
.brain_name {
|
||||
color: Colors.$black;
|
||||
color: var(--text-3);
|
||||
@include Typography.EllipsisOverflow;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Image from "next/image";
|
||||
|
||||
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
||||
import { useUserSettingsContext } from "@/lib/context/UserSettingsProvider/hooks/useUserSettingsContext";
|
||||
|
||||
import styles from "./CurrentBrain.module.scss";
|
||||
|
||||
@ -14,7 +15,7 @@ export const CurrentBrain = ({
|
||||
allowingRemoveBrain,
|
||||
}: CurrentBrainProps): JSX.Element => {
|
||||
const { currentBrain, setCurrentBrainId } = useBrainContext();
|
||||
|
||||
const { isDarkMode } = useUserSettingsContext();
|
||||
const removeCurrentBrain = (): void => {
|
||||
setCurrentBrainId(null);
|
||||
};
|
||||
@ -29,16 +30,17 @@ export const CurrentBrain = ({
|
||||
<div className={styles.left}>
|
||||
<span className={styles.title}>Talking to</span>
|
||||
<div className={styles.brain_name_wrapper}>
|
||||
{currentBrain.integration_logo_url ? (
|
||||
<Image
|
||||
src={currentBrain.integration_logo_url}
|
||||
alt="brain"
|
||||
width={18}
|
||||
height={18}
|
||||
/>
|
||||
) : (
|
||||
<Icon size="small" name="brain" color="primary" />
|
||||
)}
|
||||
<Image
|
||||
className={isDarkMode ? styles.dark_image : ""}
|
||||
src={
|
||||
currentBrain.integration_logo_url
|
||||
? currentBrain.integration_logo_url
|
||||
: "/default_brain_image.png"
|
||||
}
|
||||
alt="logo_image"
|
||||
width={18}
|
||||
height={18}
|
||||
/>
|
||||
<span className={styles.brain_name}>{currentBrain.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,10 +1,9 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/ZIndexes.module.scss";
|
||||
|
||||
.menu_container {
|
||||
background-color: Colors.$highlight;
|
||||
border-right: 1px solid Colors.$lightest-black;
|
||||
background-color: var(--background-1);
|
||||
border-right: 1px solid var(--border-1);
|
||||
|
||||
.menu_wrapper {
|
||||
padding-top: Spacings.$spacing05;
|
||||
@ -37,7 +36,7 @@
|
||||
|
||||
.social_buttons_wrapper {
|
||||
padding-block: Spacings.$spacing04;
|
||||
border-top: 1px solid Colors.$lightest-black;
|
||||
border-top: 1px solid var(--border-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import { useChatsList } from "@/app/chat/[chatId]/hooks/useChatsList";
|
||||
import { QuivrLogo } from "@/lib/assets/QuivrLogo";
|
||||
import { nonProtectedPaths } from "@/lib/config/routesConfig";
|
||||
import { useMenuContext } from "@/lib/context/MenuProvider/hooks/useMenuContext";
|
||||
import { useUserSettingsContext } from "@/lib/context/UserSettingsProvider/hooks/useUserSettingsContext";
|
||||
|
||||
import styles from "./Menu.module.scss";
|
||||
import { AnimatedDiv } from "./components/AnimationDiv";
|
||||
@ -23,6 +24,7 @@ export const Menu = (): JSX.Element => {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname() ?? "";
|
||||
const [isLogoHovered, setIsLogoHovered] = useState<boolean>(false);
|
||||
const { isDarkMode } = useUserSettingsContext();
|
||||
|
||||
useChatsList();
|
||||
|
||||
@ -53,7 +55,9 @@ export const Menu = (): JSX.Element => {
|
||||
>
|
||||
<QuivrLogo
|
||||
size={50}
|
||||
color={isLogoHovered ? "primary" : "black"}
|
||||
color={
|
||||
isLogoHovered ? "primary" : isDarkMode ? "white" : "black"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/BoxShadow.module.scss";
|
||||
@use "@/styles/IconSizes.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -8,11 +8,11 @@
|
||||
padding: Spacings.$spacing03;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border: 1px solid Colors.$lighter-grey;
|
||||
border: 1px solid var(--border-0);
|
||||
border-radius: Radius.$big;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
cursor: pointer;
|
||||
color: Colors.$dark-grey;
|
||||
color: var(--text-2);
|
||||
transition: box-shadow 0.3s ease;
|
||||
|
||||
.left_wrapper {
|
||||
@ -30,7 +30,7 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
border: 1px solid Colors.$lighter-grey;
|
||||
border: 1px solid var(--border-0);
|
||||
border-radius: Radius.$small;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
@ -39,7 +39,7 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: Colors.$primary;
|
||||
box-shadow: 0 0 0 1px Colors.$primary;
|
||||
border-color: var(--primary-0);
|
||||
box-shadow: BoxShadow.$primary;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -14,7 +13,7 @@
|
||||
border-left: 2px solid transparent;
|
||||
|
||||
&.selected {
|
||||
border-left: 2px solid Colors.$primary;
|
||||
border-left: 2px solid var(--primary-0);
|
||||
border-radius: 0 Radius.$normal Radius.$normal 0;
|
||||
}
|
||||
|
||||
@ -27,19 +26,19 @@
|
||||
.title {
|
||||
@include Typography.EllipsisOverflow;
|
||||
font-size: Typography.$small;
|
||||
color: Colors.$black;
|
||||
color: var(--text-3);
|
||||
|
||||
&.gold {
|
||||
color: Colors.$gold;
|
||||
color: var(--gold);
|
||||
}
|
||||
|
||||
&.primary {
|
||||
color: Colors.$primary;
|
||||
color: var(--primary-0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: Colors.$lightest-black;
|
||||
background-color: var(--background-3);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -7,7 +6,7 @@
|
||||
position: relative;
|
||||
padding: Spacings.$spacing03;
|
||||
padding-top: 0;
|
||||
color: Colors.$dark-grey;
|
||||
color: var(--text-2);
|
||||
font-size: Typography.$small;
|
||||
max-height: 300px;
|
||||
overflow-y: scroll;
|
||||
|
@ -1,11 +1,10 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@use "@/styles/ZIndexes.module.scss";
|
||||
|
||||
.thread_item_wrapper {
|
||||
color: Colors.$black;
|
||||
color: var(--text-3);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: Spacings.$spacing03;
|
||||
@ -15,13 +14,13 @@
|
||||
.edit_thread_name {
|
||||
@include Typography.EllipsisOverflow;
|
||||
|
||||
color: Colors.$black;
|
||||
color: var(--text-3);
|
||||
border: none;
|
||||
height: 21px;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
font-size: Typography.$small;
|
||||
background-color: Colors.$lighter-grey;
|
||||
background-color: var(--background-3);
|
||||
border-radius: Radius.$small;
|
||||
|
||||
&:focus {
|
||||
@ -33,7 +32,7 @@
|
||||
@include Typography.EllipsisOverflow;
|
||||
|
||||
&:hover {
|
||||
color: Colors.$primary;
|
||||
color: var(--primary-0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
.chats_wrapper {
|
||||
border-left: 1px solid Colors.$normal-grey;
|
||||
border-left: 1px solid var(--border-2);
|
||||
padding-left: Spacings.$spacing03;
|
||||
margin: Spacings.$spacing02;
|
||||
display: flex;
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -9,7 +8,7 @@
|
||||
justify-content: space-between;
|
||||
padding: Spacings.$spacing04;
|
||||
padding-left: Spacings.$spacing09;
|
||||
border-bottom: 1px solid Colors.$lightest-black;
|
||||
border-bottom: 1px solid var(--border-1);
|
||||
|
||||
.left {
|
||||
@include Typography.H2;
|
||||
@ -32,5 +31,6 @@
|
||||
display: flex;
|
||||
gap: Spacings.$spacing03;
|
||||
align-self: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { useMenuContext } from "@/lib/context/MenuProvider/hooks/useMenuContext";
|
||||
import { useUserSettingsContext } from "@/lib/context/UserSettingsProvider/hooks/useUserSettingsContext";
|
||||
import { ButtonType } from "@/lib/types/QuivrButton";
|
||||
|
||||
import styles from "./PageHeader.module.scss";
|
||||
@ -18,6 +21,16 @@ export const PageHeader = ({
|
||||
buttons,
|
||||
}: Props): JSX.Element => {
|
||||
const { isOpened } = useMenuContext();
|
||||
const { isDarkMode, setIsDarkMode } = useUserSettingsContext();
|
||||
const [lightModeIconName, setLightModeIconName] = useState("sun");
|
||||
|
||||
const toggleTheme = () => {
|
||||
setIsDarkMode(!isDarkMode);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setLightModeIconName(isDarkMode ? "sun" : "moon");
|
||||
}, [isDarkMode]);
|
||||
|
||||
return (
|
||||
<div className={styles.page_header_wrapper}>
|
||||
@ -36,6 +49,13 @@ export const PageHeader = ({
|
||||
hidden={button.hidden}
|
||||
/>
|
||||
))}
|
||||
<Icon
|
||||
name={lightModeIconName}
|
||||
color="black"
|
||||
handleHover={true}
|
||||
size="small"
|
||||
onClick={toggleTheme}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,11 +1,10 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/ZIndexes.module.scss";
|
||||
|
||||
.search_modal_wrapper {
|
||||
display: flex;
|
||||
background-color: rgba(Colors.$dark-black, 0.94);
|
||||
background-color: var(--background-blur);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { StripePricingTable } from "./components/PricingTable/PricingTable";
|
||||
|
||||
import { Modal } from "../../ui/ModalPayment";
|
||||
import { Modal } from "../../ui/Modal/Modal";
|
||||
|
||||
type StripePricingModalProps = {
|
||||
Trigger: JSX.Element;
|
||||
@ -10,7 +10,7 @@ export const StripePricingModal = ({
|
||||
Trigger,
|
||||
}: StripePricingModalProps): JSX.Element => {
|
||||
return (
|
||||
<Modal Trigger={Trigger} CloseTrigger={<div />}>
|
||||
<Modal Trigger={Trigger} CloseTrigger={<div />} unforceWhite={true}>
|
||||
<StripePricingTable />
|
||||
</Modal>
|
||||
);
|
||||
|
@ -0,0 +1,9 @@
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
.info_content {
|
||||
padding: Spacings.$spacing06;
|
||||
|
||||
.bold {
|
||||
font-weight: 800;
|
||||
}
|
||||
}
|
@ -1,38 +1,25 @@
|
||||
import { MessageInfoBox } from "@/lib/components/ui/MessageInfoBox/MessageInfoBox";
|
||||
|
||||
import styles from "./PricingTable.module.scss";
|
||||
|
||||
const PRICING_TABLE_ID = process.env.NEXT_PUBLIC_STRIPE_PRICING_TABLE_ID;
|
||||
const PUBLISHABLE_KEY = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY;
|
||||
|
||||
export const StripePricingTable = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
<div className="grid md:grid-cols-2 gap-4 p-2 bg-highlight">
|
||||
<div className="space-y-3 text-center">
|
||||
<h3 className="text-2xl font-semibold text-black">Free Tier</h3>
|
||||
<ul className="list-none space-y-2">
|
||||
<li className="text-lg font-medium text-gray-800">🧠 3 brains</li>
|
||||
<li className="text-lg font-medium text-gray-800">
|
||||
🙋♂️ 100 questions per month
|
||||
</li>
|
||||
<li className="text-lg font-medium text-gray-800">
|
||||
💾 Up to 30Mb of storage
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="space-y-3 text-center">
|
||||
<h3 className="text-2xl font-semibold text-black">
|
||||
Premium Features
|
||||
</h3>
|
||||
<ul className="list-none space-y-2">
|
||||
<li className="text-lg font-medium text-gray-800">
|
||||
🧠 Bigger & more Brains
|
||||
</li>
|
||||
<li className="text-lg font-medium text-gray-800">
|
||||
🙋♂️ More credits & access to premium models (GPT4, Mistral)
|
||||
</li>
|
||||
<li className="text-lg font-medium text-gray-800">
|
||||
🚀 GPT3.5 = 1 credit & GPT4 = 20 credits
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className={styles.info_content}>
|
||||
<MessageInfoBox type="info" unforceWhite={true}>
|
||||
<div>
|
||||
{"The free tier allows you to have"}
|
||||
<span className={styles.bold}> 3 brains </span>
|
||||
{"and"}
|
||||
<span className={styles.bold}> 100 chat credits </span>
|
||||
{
|
||||
"per month. You can upgrade to unlock more brains, more chat credits and access to premium models."
|
||||
}
|
||||
</div>
|
||||
</MessageInfoBox>
|
||||
</div>
|
||||
<div className="p-2">
|
||||
<script async src="https://js.stripe.com/v3/pricing-table.js"></script>
|
||||
|
12
frontend/lib/components/Stripe/PricingModal/components/PricingTable/types/types.d.ts
vendored
Normal file
12
frontend/lib/components/Stripe/PricingModal/components/PricingTable/types/types.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
import * as React from "react";
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
"stripe-pricing-table": React.DetailedHTMLProps<
|
||||
React.HTMLAttributes<HTMLElement>,
|
||||
HTMLElement
|
||||
>;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/ZIndexes.module.scss";
|
||||
|
||||
@ -7,7 +6,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
|
||||
.selection {
|
||||
border-radius: Radius.$normal;
|
||||
box-shadow: none;
|
||||
cursor: pointer;
|
||||
background-color: var(--background-0);
|
||||
|
||||
&:hover {
|
||||
background-color: Colors.$lightest-black;
|
||||
background-color: var(--background-3);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
border-color: Colors.$primary;
|
||||
border-color: var(--primary-0);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -8,7 +7,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: Radius.$normal;
|
||||
border: 1px dashed Colors.$lighter-grey;
|
||||
border: 1px dashed var(--border-0);
|
||||
overflow: hidden;
|
||||
font-size: Typography.$small;
|
||||
|
||||
@ -16,7 +15,7 @@
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s Transitions.$easeOutBack;
|
||||
}
|
||||
|
||||
|
||||
.contentCollapsed {
|
||||
max-height: 0;
|
||||
}
|
||||
@ -44,10 +43,10 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: Colors.$lightest-black;
|
||||
background-color: var(--background-3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.iconRotate {
|
||||
transition: transform 0.3s Transitions.$easeOutBack;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/IconSizes.module.scss";
|
||||
|
||||
.small {
|
||||
@ -30,55 +29,55 @@
|
||||
}
|
||||
|
||||
.black {
|
||||
color: Colors.$black;
|
||||
color: var(--icon-3);
|
||||
|
||||
&.hovered {
|
||||
color: Colors.$primary;
|
||||
color: var(--primary-0);
|
||||
}
|
||||
}
|
||||
|
||||
.dark-grey {
|
||||
color: Colors.$dark-grey;
|
||||
color: var(--icon-2);
|
||||
}
|
||||
|
||||
.grey {
|
||||
color: Colors.$normal-grey;
|
||||
color: var(--icon-1);
|
||||
}
|
||||
|
||||
.primary {
|
||||
color: Colors.$primary;
|
||||
color: var(--primary-0);
|
||||
}
|
||||
|
||||
.accent {
|
||||
color: Colors.$accent;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.gold {
|
||||
color: Colors.$gold;
|
||||
color: var(--gold);
|
||||
}
|
||||
|
||||
.white {
|
||||
color: Colors.$white;
|
||||
color: var(--icon-0);
|
||||
}
|
||||
|
||||
.dangerous {
|
||||
color: Colors.$dangerous;
|
||||
color: var(--dangerous);
|
||||
|
||||
&.hovered {
|
||||
color: Colors.$dangerous-dark;
|
||||
color: var(--dangerous-dark);
|
||||
}
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: Colors.$warning;
|
||||
color: var(--warning);
|
||||
}
|
||||
|
||||
.success {
|
||||
color: Colors.$success;
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color: Colors.$black;
|
||||
color: var(--icon-3);
|
||||
pointer-events: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/IconSizes.module.scss";
|
||||
|
||||
.loader_icon {
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
@ -8,25 +7,29 @@
|
||||
align-items: center;
|
||||
gap: Spacings.$spacing03;
|
||||
width: fit-content;
|
||||
border: 1px solid Colors.$normal-grey;
|
||||
color: Colors.$black;
|
||||
border: 1px solid var(--border-2);
|
||||
color: var(--text-3);
|
||||
border-radius: Radius.$normal;
|
||||
|
||||
&.success {
|
||||
border-color: Colors.$success;
|
||||
color: Colors.$success;
|
||||
background-color: Colors.$success-lightest;
|
||||
border-color: var(--success);
|
||||
color: var(--success);
|
||||
background-color: var(--success-lightest);
|
||||
}
|
||||
|
||||
&.info {
|
||||
border-color: Colors.$primary;
|
||||
color: Colors.$primary;
|
||||
background-color: Colors.$primary-lightest;
|
||||
border-color: var(--primary-0);
|
||||
color: var(--primary-0);
|
||||
background-color: var(--primary-2);
|
||||
}
|
||||
|
||||
&.warning {
|
||||
border-color: Colors.$warning;
|
||||
color: Colors.$warning;
|
||||
background-color: Colors.$warning-lightest;
|
||||
border-color: var(--warning);
|
||||
color: var(--warning);
|
||||
background-color: var(--warning-lightest);
|
||||
}
|
||||
|
||||
&.dark {
|
||||
background-color: var(--background-special-0);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useUserSettingsContext } from "@/lib/context/UserSettingsProvider/hooks/useUserSettingsContext";
|
||||
import { iconList } from "@/lib/helpers/iconList";
|
||||
import { Color } from "@/lib/types/Colors";
|
||||
|
||||
@ -8,11 +9,13 @@ import { Icon } from "../Icon/Icon";
|
||||
export type MessageInfoBoxProps = {
|
||||
children: React.ReactNode;
|
||||
type: "info" | "success" | "warning" | "error";
|
||||
unforceWhite?: boolean;
|
||||
};
|
||||
|
||||
export const MessageInfoBox = ({
|
||||
children,
|
||||
type,
|
||||
unforceWhite,
|
||||
}: MessageInfoBoxProps): JSX.Element => {
|
||||
const getIconProps = (): {
|
||||
iconName: keyof typeof iconList;
|
||||
@ -30,8 +33,14 @@ export const MessageInfoBox = ({
|
||||
}
|
||||
};
|
||||
|
||||
const { isDarkMode } = useUserSettingsContext();
|
||||
|
||||
return (
|
||||
<div className={`${styles.message_info_box_wrapper} ${styles[type]} `}>
|
||||
<div
|
||||
className={`${styles.message_info_box_wrapper} ${styles[type]} ${
|
||||
isDarkMode && !unforceWhite ? styles.dark : ""
|
||||
}`}
|
||||
>
|
||||
<Icon
|
||||
name={getIconProps().iconName}
|
||||
size="normal"
|
||||
|
@ -1,4 +1,4 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/BoxShadow.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
.modal_container {
|
||||
display: flex;
|
||||
background-color: rgba(Colors.$dark-black, 0.94);
|
||||
background-color: var(--background-blur);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
@ -18,10 +18,10 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: Radius.$big;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
padding: Spacings.$spacing05;
|
||||
cursor: auto;
|
||||
box-shadow: 0 2px 4px rgb(0, 0, 0, 0.25);
|
||||
box-shadow: BoxShadow.$medium;
|
||||
max-width: 90vw;
|
||||
overflow: scroll;
|
||||
|
||||
@ -30,6 +30,11 @@
|
||||
height: 90vh;
|
||||
}
|
||||
|
||||
&.white {
|
||||
background-color: var(--white-0);
|
||||
color: var(--text-0);
|
||||
}
|
||||
|
||||
@media (max-width: ScreenSizes.$small) {
|
||||
&.big_modal {
|
||||
width: 90vw;
|
||||
|
@ -20,6 +20,7 @@ type CommonModalProps = {
|
||||
isOpen?: undefined;
|
||||
setOpen?: undefined;
|
||||
bigModal?: boolean;
|
||||
unforceWhite?: boolean;
|
||||
};
|
||||
|
||||
type ModalProps =
|
||||
@ -38,6 +39,7 @@ export const Modal = ({
|
||||
isOpen: customIsOpen,
|
||||
setOpen: customSetOpen,
|
||||
bigModal,
|
||||
unforceWhite,
|
||||
}: ModalProps): JSX.Element => {
|
||||
const [isOpen, setOpen] = useState(false);
|
||||
const { t } = useTranslation(["translation"]);
|
||||
@ -64,7 +66,7 @@ export const Modal = ({
|
||||
<motion.div
|
||||
className={`${styles.modal_content_wrapper} ${
|
||||
bigModal ? styles.big_modal : ""
|
||||
}`}
|
||||
} ${unforceWhite ? styles.white : ""}`}
|
||||
initial={{ opacity: 0, y: "-40%" }}
|
||||
animate={{ opacity: 1, y: "0%" }}
|
||||
exit={{ opacity: 0, y: "40%" }}
|
||||
|
@ -1,105 +0,0 @@
|
||||
/*eslint max-lines: ["error", 200 ]*/
|
||||
|
||||
"use client";
|
||||
import * as Dialog from "@radix-ui/react-dialog";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { ReactNode, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { MdClose } from "react-icons/md";
|
||||
|
||||
import Button from "./Button";
|
||||
|
||||
type CommonModalProps = {
|
||||
title?: string;
|
||||
desc?: string;
|
||||
children?: ReactNode;
|
||||
Trigger?: ReactNode;
|
||||
CloseTrigger?: ReactNode;
|
||||
isOpen?: undefined;
|
||||
setOpen?: undefined;
|
||||
};
|
||||
|
||||
type ModalProps =
|
||||
| CommonModalProps
|
||||
| (Omit<CommonModalProps, "isOpen" | "setOpen"> & {
|
||||
isOpen: boolean;
|
||||
setOpen: (isOpen: boolean) => void;
|
||||
});
|
||||
|
||||
export const Modal = ({
|
||||
title,
|
||||
desc,
|
||||
children,
|
||||
Trigger,
|
||||
CloseTrigger,
|
||||
isOpen: customIsOpen,
|
||||
setOpen: customSetOpen,
|
||||
}: ModalProps): JSX.Element => {
|
||||
const [isOpen, setOpen] = useState(false);
|
||||
const { t } = useTranslation(["translation"]);
|
||||
|
||||
return (
|
||||
<Dialog.Root
|
||||
open={customIsOpen ?? isOpen}
|
||||
onOpenChange={customSetOpen ?? setOpen}
|
||||
>
|
||||
{Trigger !== undefined && (
|
||||
<Dialog.Trigger asChild>{Trigger}</Dialog.Trigger>
|
||||
)}
|
||||
<AnimatePresence>
|
||||
{customIsOpen ?? isOpen ? (
|
||||
<Dialog.Portal forceMount>
|
||||
<Dialog.Overlay asChild forceMount>
|
||||
<motion.div
|
||||
className="z-[10000] py-20 fixed inset-0 flex justify-center overflow-auto cursor-pointer bg-black/50 backdrop-blur-sm"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<Dialog.Content asChild forceMount>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: "-40%" }}
|
||||
animate={{ opacity: 1, y: "0%" }}
|
||||
exit={{ opacity: 0, y: "40%" }}
|
||||
className="w-[90vw] my-auto flex flex-col h-fit max-w-6xl rounded-xl bg-white dark:bg-black border border-black/10 dark:border-white/25 p-10 shadow-xl dark:shadow-primary/50 focus:outline-none cursor-auto"
|
||||
>
|
||||
<Dialog.Title
|
||||
className="m-0 text-2xl font-bold"
|
||||
data-testid="modal-title"
|
||||
>
|
||||
{title}
|
||||
</Dialog.Title>
|
||||
<Dialog.Description
|
||||
className="opacity-50"
|
||||
data-testid="modal-description"
|
||||
>
|
||||
{desc}
|
||||
</Dialog.Description>
|
||||
{children}
|
||||
<Dialog.Close asChild>
|
||||
{CloseTrigger !== undefined ? (
|
||||
CloseTrigger
|
||||
) : (
|
||||
<Button variant={"secondary"} className="self-end">
|
||||
{t("doneButton")}
|
||||
</Button>
|
||||
)}
|
||||
</Dialog.Close>
|
||||
<Dialog.Close asChild>
|
||||
<button
|
||||
className="absolute top-0 p-5 right-0 inline-flex appearance-none items-center justify-center rounded-full focus:shadow-sm focus:outline-none"
|
||||
aria-label="Close"
|
||||
>
|
||||
<MdClose />
|
||||
</button>
|
||||
</Dialog.Close>
|
||||
</motion.div>
|
||||
</Dialog.Content>
|
||||
</motion.div>
|
||||
</Dialog.Overlay>
|
||||
</Dialog.Portal>
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
</Dialog.Root>
|
||||
);
|
||||
};
|
@ -1,13 +1,13 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/BoxShadow.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/ZIndexes.module.scss";
|
||||
|
||||
.options_modal_wrapper {
|
||||
background-color: Colors.$highlight;
|
||||
background-color: var(--background-1);
|
||||
border-radius: Radius.$normal;
|
||||
border-radius: Radius.$normal;
|
||||
box-shadow: 0 1px 2px rgb(0, 0, 0, 0.25);
|
||||
box-shadow: BoxShadow.$small;
|
||||
width: fit-content;
|
||||
|
||||
.option {
|
||||
@ -21,11 +21,11 @@
|
||||
overflow: hidden;
|
||||
|
||||
&:not(:first-child) {
|
||||
border-top: 1px solid Colors.$light-grey;
|
||||
border-top: 1px solid var(--border-2);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: Colors.$primary-lightest;
|
||||
background-color: var(--background-special-0);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -14,46 +13,50 @@
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.primary {
|
||||
border-color: Colors.$primary;
|
||||
color: Colors.$primary;
|
||||
border-color: var(--primary-0);
|
||||
color: var(--primary-0);
|
||||
|
||||
&:hover {
|
||||
background-color: Colors.$primary;
|
||||
color: Colors.$white;
|
||||
background-color: var(--primary-0);
|
||||
color: var(--text-0);
|
||||
}
|
||||
}
|
||||
|
||||
&.dangerous {
|
||||
border-color: Colors.$dangerous;
|
||||
color: Colors.$dangerous;
|
||||
border-color: var(--dangerous);
|
||||
color: var(--dangerous);
|
||||
|
||||
&:hover {
|
||||
background-color: Colors.$dangerous;
|
||||
color: Colors.$white;
|
||||
background-color: var(--dangerous);
|
||||
color: var(--text-0);
|
||||
}
|
||||
}
|
||||
|
||||
&.gold {
|
||||
border-color: Colors.$gold;
|
||||
color: Colors.$gold;
|
||||
border-color: var(--gold);
|
||||
color: var(--gold);
|
||||
|
||||
&:hover {
|
||||
background-color: Colors.$gold;
|
||||
color: Colors.$white;
|
||||
background-color: var(--gold);
|
||||
color: var(--text-0);
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
border-color: Colors.$normal-grey;
|
||||
border-color: var(--border-2);
|
||||
pointer-events: none;
|
||||
color: Colors.$normal-grey;
|
||||
color: var(--text-1);
|
||||
|
||||
&.dark {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { useUserSettingsContext } from "@/lib/context/UserSettingsProvider/hooks/useUserSettingsContext";
|
||||
import { ButtonType } from "@/lib/types/QuivrButton";
|
||||
|
||||
import styles from "./QuivrButton.module.scss";
|
||||
@ -17,6 +18,7 @@ export const QuivrButton = ({
|
||||
hidden,
|
||||
}: ButtonType): JSX.Element => {
|
||||
const [hovered, setHovered] = useState<boolean>(false);
|
||||
const { isDarkMode } = useUserSettingsContext();
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -24,10 +26,11 @@ export const QuivrButton = ({
|
||||
${styles.button_wrapper}
|
||||
${styles[color]}
|
||||
${disabled ? styles.disabled : ""}
|
||||
${isDarkMode ? styles.dark : ""}
|
||||
${hidden ? styles.hidden : ""}
|
||||
`}
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
onClick={() => onClick?.()}
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises, @typescript-eslint/prefer-optional-chain, @typescript-eslint/no-unnecessary-condition
|
||||
onClick={() => onClick && onClick()}
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
>
|
||||
|
@ -1,4 +1,4 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/BoxShadow.module.scss";
|
||||
@use "@/styles/IconSizes.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -7,11 +7,11 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: Spacings.$spacing03;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
border-radius: Radius.$big;
|
||||
border: 1px solid Colors.$lighter-grey;
|
||||
border: 1px solid var(--border-0);
|
||||
overflow: hidden;
|
||||
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.25);
|
||||
box-shadow: BoxShadow.$large;
|
||||
|
||||
.editor_wrapper {
|
||||
display: flex;
|
||||
@ -26,11 +26,11 @@
|
||||
.search_icon {
|
||||
width: IconSizes.$big;
|
||||
height: IconSizes.$big;
|
||||
color: Colors.$accent;
|
||||
color: var(--accent);
|
||||
cursor: pointer;
|
||||
|
||||
&.disabled {
|
||||
color: Colors.$black;
|
||||
color: var(--text-3);
|
||||
pointer-events: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/IconSizes.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -9,12 +8,12 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
|
||||
.first_line_wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border: 1px solid Colors.$normal-grey;
|
||||
border: 1px solid var(--border-2);
|
||||
border-radius: Radius.$big;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
@ -37,14 +36,14 @@
|
||||
|
||||
.label {
|
||||
@include Typography.EllipsisOverflow;
|
||||
background-color: Colors.$primary-light;
|
||||
background-color: var(--background-special-1);
|
||||
border-radius: Radius.$normal;
|
||||
padding-inline: Spacings.$spacing05;
|
||||
padding-block: Spacings.$spacing02;
|
||||
white-space: nowrap;
|
||||
|
||||
&.not_set {
|
||||
color: Colors.$normal-grey;
|
||||
color: var(--text-1);
|
||||
background-color: transparent;
|
||||
padding-inline: 0;
|
||||
}
|
||||
@ -67,10 +66,10 @@
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
width: 100%;
|
||||
top: 100%;
|
||||
border: 1px solid Colors.$normal-grey;
|
||||
border: 1px solid var(--border-2);
|
||||
border-top: none;
|
||||
border-radius: 0 0 Radius.$big Radius.$big;
|
||||
overflow: hidden;
|
||||
@ -88,7 +87,7 @@
|
||||
|
||||
&:hover {
|
||||
.option_name {
|
||||
background-color: Colors.$primary-lightest;
|
||||
background-color: var(--background-special-1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +97,7 @@
|
||||
|
||||
.option_name {
|
||||
@include Typography.EllipsisOverflow;
|
||||
border: 1px solid Colors.$lightest-black;
|
||||
border: 1px solid var(--border-1);
|
||||
border-radius: Radius.$small;
|
||||
padding-inline: Spacings.$spacing05;
|
||||
padding-block: Spacings.$spacing02;
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@ -12,25 +11,25 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
border-bottom: 2px solid Colors.$lightest-grey;
|
||||
border-bottom: 2px solid var(--border-0);
|
||||
padding-block: Spacings.$spacing03;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
gap: Spacings.$spacing03;
|
||||
|
||||
&.selected {
|
||||
border-bottom-color: Colors.$primary;
|
||||
color: Colors.$primary;
|
||||
background-color: Colors.$lightest-grey;
|
||||
border-bottom-color: var(--primary-0);
|
||||
color: var(--primary-0);
|
||||
background-color: var(--background-2);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: Colors.$primary;
|
||||
color: var(--primary-0);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
pointer-events: none;
|
||||
color: Colors.$normal-grey;
|
||||
color: var(--text-1);
|
||||
}
|
||||
|
||||
@media (max-width: ScreenSizes.$small) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -11,10 +10,10 @@
|
||||
font-size: Typography.$tiny;
|
||||
|
||||
&.primary {
|
||||
background-color: Colors.$primary-light;
|
||||
background-color: var(--primary-1);
|
||||
}
|
||||
|
||||
&.gold {
|
||||
background-color: Colors.$gold;
|
||||
background-color: var(--gold);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,16 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
.text_area_input_container {
|
||||
display: flex;
|
||||
border: 1px solid Colors.$lighter-grey;
|
||||
border: 1px solid var(--border-0);
|
||||
gap: Spacings.$spacing03;
|
||||
padding-block: Spacings.$spacing02;
|
||||
padding-inline: Spacings.$spacing03;
|
||||
border-radius: Radius.$big;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
|
||||
&.simple {
|
||||
border: none;
|
||||
@ -30,10 +29,11 @@
|
||||
}
|
||||
|
||||
.text_area_input {
|
||||
caret-color: Colors.$accent;
|
||||
caret-color: var(--accent);
|
||||
border: none;
|
||||
flex: 1;
|
||||
resize: none;
|
||||
background-color: transparent;
|
||||
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
.text_button_wrapper {
|
||||
@ -10,17 +9,17 @@
|
||||
}
|
||||
|
||||
.black {
|
||||
color: Colors.$black;
|
||||
color: var(--text-3);
|
||||
|
||||
&.hovered {
|
||||
color: Colors.$primary;
|
||||
color: var(--primary-0);
|
||||
}
|
||||
}
|
||||
|
||||
.dangerous {
|
||||
color: Colors.$dangerous;
|
||||
color: var(--dangerous);
|
||||
|
||||
&.hovered {
|
||||
color: Colors.$dangerous-dark;
|
||||
color: var(--dangerous)-dark;
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,16 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
.text_input_container {
|
||||
display: flex;
|
||||
border: 1px solid Colors.$lighter-grey;
|
||||
border: 1px solid var(--border-0);
|
||||
gap: Spacings.$spacing03;
|
||||
padding-block: Spacings.$spacing02;
|
||||
padding-inline: Spacings.$spacing03;
|
||||
border-radius: Radius.$big;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
background-color: Colors.$white;
|
||||
background-color: var(--background-0);
|
||||
|
||||
&.simple {
|
||||
border: none;
|
||||
@ -30,7 +29,7 @@
|
||||
}
|
||||
|
||||
.text_input {
|
||||
caret-color: Colors.$accent;
|
||||
caret-color: var(--accent);
|
||||
border: none;
|
||||
flex: 1;
|
||||
background-color: transparent;
|
||||
|
@ -1,4 +1,3 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@ -6,7 +5,7 @@
|
||||
|
||||
.tooltip_content_wrapper {
|
||||
z-index: ZIndexes.$tooltip;
|
||||
background-color: Colors.$lightest-black;
|
||||
background-color: var(--background-3);
|
||||
padding: Spacings.$spacing03;
|
||||
border-radius: Radius.$normal;
|
||||
font-size: Typography.$small;
|
||||
|
@ -0,0 +1,76 @@
|
||||
import { createContext, useEffect, useState } from "react";
|
||||
|
||||
import { parseBoolean } from "@/lib/helpers/parseBoolean";
|
||||
|
||||
type UserSettingsContextType = {
|
||||
isDarkMode: boolean;
|
||||
setIsDarkMode: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
export const UserSettingsContext = createContext<
|
||||
UserSettingsContextType | undefined
|
||||
>(undefined);
|
||||
|
||||
export const UserSettingsProvider = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}): JSX.Element => {
|
||||
const [isDarkMode, setIsDarkMode] = useState<boolean>(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
const localIsDarkMode = localStorage.getItem("isDarkMode");
|
||||
|
||||
return parseBoolean(localIsDarkMode);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
const prefersDarkMode = window.matchMedia(
|
||||
"(prefers-color-scheme: dark)"
|
||||
).matches;
|
||||
const localIsDarkMode = localStorage.getItem("isDarkMode");
|
||||
const newState =
|
||||
localIsDarkMode !== null
|
||||
? parseBoolean(localIsDarkMode)
|
||||
: prefersDarkMode;
|
||||
setIsDarkMode(newState);
|
||||
newState
|
||||
? document.body.classList.add("dark_mode")
|
||||
: document.body.classList.remove("dark_mode");
|
||||
|
||||
const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
const listener = (event: MediaQueryListEvent) => {
|
||||
const updatedState = event.matches;
|
||||
setIsDarkMode(updatedState);
|
||||
localStorage.setItem("isDarkMode", JSON.stringify(updatedState));
|
||||
};
|
||||
mediaQueryList.addEventListener("change", listener);
|
||||
|
||||
return () => {
|
||||
mediaQueryList.removeEventListener("change", listener);
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
isDarkMode
|
||||
? document.body.classList.add("dark_mode")
|
||||
: document.body.classList.remove("dark_mode");
|
||||
|
||||
localStorage.setItem("isDarkMode", JSON.stringify(isDarkMode));
|
||||
}, [isDarkMode]);
|
||||
|
||||
return (
|
||||
<UserSettingsContext.Provider
|
||||
value={{
|
||||
isDarkMode,
|
||||
setIsDarkMode,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</UserSettingsContext.Provider>
|
||||
);
|
||||
};
|
@ -0,0 +1,15 @@
|
||||
import { useContext } from "react";
|
||||
|
||||
import { UserSettingsContext } from "../User-settings.provider";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export const useUserSettingsContext = () => {
|
||||
const context = useContext(UserSettingsContext);
|
||||
if (context === undefined) {
|
||||
throw new Error(
|
||||
"useUserSettingsContext must be used within a UserSettingsProvider"
|
||||
);
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
@ -14,10 +14,12 @@ import {
|
||||
FaGithub,
|
||||
FaKey,
|
||||
FaLinkedin,
|
||||
FaMoon,
|
||||
FaRegFileAlt,
|
||||
FaRegKeyboard,
|
||||
FaRegStar,
|
||||
FaRegUserCircle,
|
||||
FaSun,
|
||||
FaTwitter,
|
||||
FaUnlock,
|
||||
} from "react-icons/fa";
|
||||
@ -100,6 +102,7 @@ export const iconList: { [name: string]: IconType } = {
|
||||
linkedin: FaLinkedin,
|
||||
loader: AiOutlineLoading3Quarters,
|
||||
logout: IoMdLogOut,
|
||||
moon: FaMoon,
|
||||
options: SlOptions,
|
||||
paragraph: BsTextParagraph,
|
||||
prompt: FaRegKeyboard,
|
||||
@ -110,6 +113,7 @@ export const iconList: { [name: string]: IconType } = {
|
||||
share: IoShareSocial,
|
||||
software: CgSoftwareDownload,
|
||||
star: FaRegStar,
|
||||
sun: FaSun,
|
||||
twitter: FaTwitter,
|
||||
unlock: FaUnlock,
|
||||
upload: FiUpload,
|
||||
|
7
frontend/lib/helpers/parseBoolean.ts
Normal file
7
frontend/lib/helpers/parseBoolean.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export const parseBoolean = (value: string | null): boolean => {
|
||||
if (value === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return value.toLowerCase() === "true";
|
||||
};
|
BIN
frontend/public/default_brain_image.png
Normal file
BIN
frontend/public/default_brain_image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
4
frontend/styles/_BoxShadow.module.scss
Normal file
4
frontend/styles/_BoxShadow.module.scss
Normal file
@ -0,0 +1,4 @@
|
||||
$small: 0 1px 2px var(--box-shadow);
|
||||
$medium: 0 2px 4px var(--box-shadow);
|
||||
$large: 0 4px 8px var(--box-shadow);
|
||||
$primary: 0 0 0 1px var(--box-shadow);
|
@ -1,18 +1,18 @@
|
||||
// WHITE
|
||||
$white: #ffffff;
|
||||
$dark-black: #081621;
|
||||
$secondary: #f3ecff;
|
||||
$tertiary: #f6f4ff;
|
||||
$accent: #13abba;
|
||||
$highlight: #fafafa;
|
||||
$ivory: #fcfaf6;
|
||||
$chat-bg-gray: #d9d9d9;
|
||||
|
||||
//PRIMARY
|
||||
// PRIMARY
|
||||
$primary: #6142d4;
|
||||
$primary-light: #d0c6f2;
|
||||
$primary-lightest: #f5f3fd;
|
||||
|
||||
//ACCENT
|
||||
$accent: #13abba;
|
||||
|
||||
// BLACK
|
||||
$dark-black: #081621;
|
||||
$black: #11243e;
|
||||
$light-black: #293a51;
|
||||
$lightest-black: #e7e9ec;
|
||||
|
Loading…
Reference in New Issue
Block a user