Skip to content

Commit

Permalink
Merge pull request #676 from nagineko/feature/dark_theme
Browse files Browse the repository at this point in the history
Add dark theme
  • Loading branch information
Yukinobu-Mine authored Jan 16, 2025
2 parents 8afe1c9 + 3462851 commit 644a3a2
Show file tree
Hide file tree
Showing 57 changed files with 309 additions and 207 deletions.
16 changes: 15 additions & 1 deletion frontend/.ladle/components.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import React from 'react';
import React, { useEffect } from 'react';
import '../src/i18n';
import { GlobalProvider } from '@ladle/react';
import { useLadleContext } from '@ladle/react';
import '../src/index.css';

export const Provider: GlobalProvider = ({ children }) => {
const { globalState } = useLadleContext();

useEffect(() => {
const bodyClass = document.body.classList;

if (globalState.theme === 'dark') {
bodyClass.add('dark');
} else {
bodyClass.remove('dark');
}
}, [globalState.theme]);

return <>{children}</>;
};
6 changes: 3 additions & 3 deletions frontend/src/components/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,21 @@ const Alert: React.FC<Props> = (props) => {
return (
<div
className={twMerge(
'flex flex-col rounded border border-aws-squid-ink shadow-lg',
'flex flex-col rounded border border-aws-squid-ink-light dark:border-aws-squid-ink-dark shadow-lg',
props.severity === 'info' && 'bg-aws-aqua',
props.severity === 'warning' && 'bg-yellow',
props.severity === 'error' && 'bg-red',
props.className
)}>
<div
className={twMerge(
'flex gap-2 p-2 font-bold text-aws-font-color-white'
'flex gap-2 p-2 font-bold text-aws-font-color-white-light dark:text-aws-font-color-white-dark'
)}>
{icon}
<div>{props.title}</div>
</div>

<div className="px-2 pb-2 text-aws-font-color-white">
<div className="px-2 pb-2 text-aws-font-color-white-light dark:text-aws-font-color-white-dark">
{props.children}
</div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/ApiKeyItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const ApiKeyItem: React.FC<Props> = (props) => {
{isLoading ? (
<Skeleton className="h-8 w-full" />
) : (
<div className="flex flex-col gap-1 rounded border border-aws-font-color/50 p-1 text-sm">
<div className="flex flex-col gap-1 rounded border border-aws-font-color-light/50 dark:border-aws-font-color-dark p-1 text-sm">
<div className="text-base font-semibold">
{botApiKey?.description}
</div>
Expand All @@ -80,7 +80,7 @@ const ApiKeyItem: React.FC<Props> = (props) => {
{t('bot.apiSettings.label.apiKeyDetail.inactive')}
</div>
)}
<div className="text-xs text-aws-font-color/70">
<div className="text-xs text-aws-font-color-light/70 dark:text-aws-font-color-dark/70">
<div className="mr-1 inline">
{t('bot.apiSettings.label.apiKeyDetail.creationDate')}:
</div>
Expand All @@ -98,7 +98,7 @@ const ApiKeyItem: React.FC<Props> = (props) => {
<ButtonCopy text={botApiKey?.value ?? ''} className="-my-2" />
<Button
text
className="-m-2 font-bold text-aws-sea-blue"
className="-m-2 font-bold text-aws-sea-blue-light dark:text-aws-sea-blue-dark"
onClick={() => {
setIsHideKey(!isHideKey);
}}>
Expand Down
16 changes: 12 additions & 4 deletions frontend/src/components/AppContent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import ChatListDrawer from './ChatListDrawer';
import { BaseProps } from '../@types/common';
import { ConversationMeta } from '../@types/conversation';
Expand All @@ -18,6 +18,7 @@ import useUser from '../hooks/useUser';
import DialogConfirmDeleteChat from './DialogConfirmDeleteChat';
import DialogConfirmClearConversations from './DialogConfirmClearConversations';
import DialogSelectLanguage from './DialogSelectLanguage';
import useLocalStorage from '../hooks/useLocalStorage';

type Props = BaseProps & {
signOut?: () => void;
Expand All @@ -34,6 +35,13 @@ const AppContent: React.FC<Props> = (props) => {
const { newChat, isGeneratedTitle } = useChat();
const { isConversationOrNewChat, pathPattern } = usePageTitlePathPattern();
const { isAdmin } = useUser();
const [theme] = useLocalStorage(
'theme',
'light'
);
useEffect(() => {
document.documentElement.className = theme;
}, [theme]);

const onClickNewChat = useCallback(() => {
navigate('/');
Expand Down Expand Up @@ -74,7 +82,7 @@ const AppContent: React.FC<Props> = (props) => {
const [isOpenSelectLangage, setIsOpenSelectLangage] = useState(false);

return (
<div className="relative flex h-dvh w-screen bg-aws-paper">
<div className="relative flex h-dvh w-screen bg-aws-paper-light dark:bg-aws-paper-dark">
<ChatListDrawer
isAdmin={isAdmin}
conversations={conversations}
Expand Down Expand Up @@ -120,7 +128,7 @@ const AppContent: React.FC<Props> = (props) => {

<main className="min-h-dvh relative flex flex-col flex-1 overflow-y-hidden transition-width">

<header className="visible flex h-12 w-full items-center bg-aws-squid-ink p-3 text-lg text-aws-font-color-white lg:hidden lg:h-0">
<header className="visible flex h-12 w-full items-center bg-aws-squid-ink-light dark:bg-aws-squid-ink-dark p-3 text-lg text-aws-font-color-white-light dark:text-aws-font-color-white-dark lg:hidden lg:h-0">
<button
className="mr-2 rounded-full p-2 hover:brightness-50 focus:outline-none focus:ring-1 "
onClick={() => {
Expand Down Expand Up @@ -149,7 +157,7 @@ const AppContent: React.FC<Props> = (props) => {
</header>

<div
className="h-full overflow-hidden overflow-y-auto text-aws-font-color"
className="h-full overflow-hidden overflow-y-auto text-aws-font-color-light dark:text-aws-font-color-dark"
id="main">
<SnackbarProvider>
<Outlet />
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/AuthAmplify.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const AuthAmplify: React.FC<Props> = ({ socialProviders, children }) => {
socialProviders={socialProviders}
components={{
Header: () => (
<div className="mb-5 mt-10 flex justify-center text-3xl text-aws-font-color">
<div className="mb-5 mt-10 flex justify-center text-3xl text-aws-font-color-light">
{!MISTRAL_ENABLED ? t('app.name') : t('app.nameWithoutClaude')}
</div>
),
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/AuthCustom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const AuthCustom: React.FC<Props> = ({ children }) => {
</div>
) : !authenticated ? (
<div className="flex flex-col items-center gap-4">
<div className="mb-5 mt-10 text-4xl text-aws-sea-blue">
<div className="mb-5 mt-10 text-4xl text-aws-sea-blue-light">
{!MISTRAL_ENABLED ? t('app.name') : t('app.nameWithoutClaude')}
</div>
<Button onClick={() => handleSignIn()} className="px-20 text-xl">
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ const Button = forwardRef<HTMLButtonElement, Props>((props, ref) => {
ref={ref}
className={twMerge(
'flex items-center justify-center whitespace-nowrap rounded-lg border p-1 px-3',
props.text && 'border-0',
props.outlined && 'border-aws-squid-ink/50 hover:bg-white ',
props.text && 'border-0 dark:text-aws-font-color-dark',
props.outlined && 'border-aws-squid-ink-light/50 dark:border-aws-font-color-gray/50 hover:bg-white dark:hover:bg-aws-ui-color-dark dark:text-aws-font-color-dark',
!props.text &&
!props.outlined &&
'bg-aws-sea-blue text-aws-font-color-white',
'bg-aws-sea-blue-light dark:bg-aws-ui-color-dark dark:border-aws-ui-color-dark text-aws-font-color-white-light dark:text-aws-font-color-white-dark',
props.disabled || props.loading ? 'opacity-30' : 'hover:brightness-75',
props.className
)}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ButtonFileChoose.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ const ButtonFileChoose: React.FC<Props> = (props) => {
props.className,
'flex items-center justify-center whitespace-nowrap rounded-lg hover:shadow hover:brightness-75',
props.icon
? 'rounded-full p-2 text-xl text-aws-sea-blue'
: 'border bg-aws-sea-blue p-1 px-3 text-aws-font-color-white',
? 'rounded-full p-2 text-xl text-aws-sea-blue-light dark:text-aws-sea-blue-dark'
: 'border dark:border-aws-ui-color-dark bg-aws-sea-blue-light dark:bg-aws-ui-color-dark p-1 px-3 text-aws-font-color-white-light dark:text-aws-font-color-white-dark',
props.disabled ? 'opacity-30 ' : 'cursor-pointer'
)}>
{props.children}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/ButtonIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const ButtonIcon: React.FC<Props> = (props) => {
<button
className={twMerge(
'flex items-center justify-center rounded-full p-2 text-xl hover:shadow',
'dark:text-aws-font-color-dark dark:hover:shadow-aws-font-color-dark',
props.disabled ? 'opacity-30' : 'hover:brightness-75',
props.className
)}
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/ButtonSend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const ButtonSend: React.FC<Props> = (props) => {
return (
<button
className={twMerge(
'flex items-center justify-center rounded-xl bg-aws-sea-blue p-2 text-xl text-white hover:bg-aws-sea-blue-hover',
'flex items-center justify-center rounded-xl p-2 text-xl',
'bg-aws-sea-blue-light text-white hover:bg-aws-sea-blue-hover-light',
'dark:bg-aws-sea-blue-dark dark:hover:bg-aws-sea-blue-hover-dark',
props.disabled ? 'opacity-30' : '',
props.className
)}
Expand Down
47 changes: 45 additions & 2 deletions frontend/src/components/ChatListDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React, {
} from 'react';
import { BaseProps } from '../@types/common';
import { useLocation, useParams } from 'react-router-dom';
import { IoMoonSharp, IoSunnyOutline } from "react-icons/io5";
import useDrawer from '../hooks/useDrawer';
import ButtonIcon from './ButtonIcon';
import {
Expand All @@ -28,11 +29,13 @@ import { ConversationMeta } from '../@types/conversation';
import { BotListItem } from '../@types/bot';
import { isMobile } from 'react-device-detect';
import useChat from '../hooks/useChat';
import useLocalStorage from '../hooks/useLocalStorage';
import { useTranslation } from 'react-i18next';
import Menu from './Menu';
import DrawerItem from './DrawerItem';
import ExpandableDrawerGroup from './ExpandableDrawerGroup';
import { usePageLabel } from '../routes';
import Toggle from '../components/Toggle.tsx';

type Props = BaseProps & {
isAdmin: boolean;
Expand Down Expand Up @@ -194,10 +197,17 @@ const ChatListDrawer: React.FC<Props> = (props) => {
const [prevConversations, setPrevConversations] =
useState<typeof conversations>();
const [generateTitleIndex, setGenerateTitleIndex] = useState(-1);
// If you want to add a theme, change the type from boolean to string and change the UI from toggle to pulldown.
const [isDarkTheme, setIsDarkTheme] = useState(false);

const { newChat, conversationId } = useChat();
const { botId } = useParams();

const [theme, setTheme] = useLocalStorage(
'theme',
'light'
);

useEffect(() => {
setPrevConversations(conversations);
}, [conversations]);
Expand All @@ -217,6 +227,12 @@ const ChatListDrawer: React.FC<Props> = (props) => {
}
}, [conversations, prevConversations]);

useEffect(() => {
if (theme === 'dark') {
setIsDarkTheme(true);
}
}, [theme]);

const onClickNewChat = useCallback(() => {
newChat();
closeSamllDrawer();
Expand All @@ -232,6 +248,17 @@ const ChatListDrawer: React.FC<Props> = (props) => {
[]
);

const changeTheme = (isDarkTheme: boolean) => {
setIsDarkTheme(isDarkTheme);
if (isDarkTheme) {
document.documentElement.className = 'dark';
setTheme('dark');
} else {
document.documentElement.className = 'light';
setTheme('light');
}
};

const smallDrawer = useRef<HTMLDivElement>(null);

const closeSamllDrawer = useCallback(() => {
Expand Down Expand Up @@ -262,7 +289,7 @@ const ChatListDrawer: React.FC<Props> = (props) => {

return (
<>
<div className="relative h-full overflow-y-auto bg-aws-squid-ink scrollbar-thin scrollbar-track-white scrollbar-thumb-aws-squid-ink/30 ">
<div className="relative h-full overflow-y-auto bg-aws-squid-ink-light dark:bg-aws-ui-color-dark scrollbar-thin scrollbar-track-white scrollbar-thumb-aws-squid-ink-light/30 dark:scrollbar-thumb-aws-ui-color-dark/30">
<nav
className={`lg:visible lg:w-64 ${
opened ? 'visible w-64' : 'invisible w-0'
Expand Down Expand Up @@ -361,12 +388,28 @@ const ChatListDrawer: React.FC<Props> = (props) => {
<div
className={`${
opened ? 'w-64' : 'w-0'
} fixed bottom-0 flex h-12 items-center justify-start border-t bg-aws-squid-ink transition-width lg:w-64`}>
} fixed bottom-0 flex h-12 items-center justify-between p-2 border-t bg-aws-squid-ink-light dark:bg-aws-ui-color-dark transition-width lg:w-64`}>
<Menu
onSignOut={props.onSignOut}
onSelectLanguage={props.onSelectLanguage}
onClearConversations={props.onClearConversations}
/>

<div className="flex items-center gap-2">
{isDarkTheme ? (
<>
<IoMoonSharp />
</>
): (
<>
<IoSunnyOutline />
</>
)}
<Toggle
value={isDarkTheme}
onChange={(isDarkTheme) => changeTheme(isDarkTheme)}
/>
</div>
</div>
</nav>
</div>
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/components/ChatMessage.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ export const Conversation = () => {
<div
key={idx}
className={`${
message.role === 'assistant' ? 'bg-aws-squid-ink/5' : ''
message.role === 'assistant' ? 'bg-aws-squid-ink-light/5 dark:bg-aws-squid-ink-dark/5' : 'dark:text-aws-font-color-dark'
}`}>
<ChatMessage
chatContent={message}
/>

<div className="w-full border-b border-aws-squid-ink/10"></div>
<div className="w-full border-b border-aws-squid-ink-light/10 dark:border-aws-squid-ink-dark/10"></div>
</div>
))}
</>
Expand Down Expand Up @@ -123,13 +123,13 @@ export const ConversationThinking = () => {
<div
key={idx}
className={`${
message.role === 'assistant' ? 'bg-aws-squid-ink/5' : ''
message.role === 'assistant' ? 'bg-aws-squid-ink-light/5 dark:bg-aws-squid-ink-dark/5' : 'dark:text-aws-font-color-dark'
}`}>
<ChatMessage
chatContent={message}
/>

<div className="w-full border-b border-aws-squid-ink/10"></div>
<div className="w-full border-b border-aws-squid-ink-light/10 dark:border-aws-squid-ink-dark/10"></div>
</div>
))}
</>
Expand Down Expand Up @@ -272,7 +272,7 @@ export const ConversationWithAgnet = () => {
<div
key={idx}
className={`${
message.role === 'assistant' ? 'bg-aws-squid-ink/5' : ''
message.role === 'assistant' ? 'bg-aws-squid-ink-light/5 dark:bg-aws-squid-ink-dark/5' : 'dark:text-aws-font-color-dark'
}`}>
<ChatMessage
chatContent={message}
Expand Down Expand Up @@ -313,7 +313,7 @@ export const ConversationWithAgnet = () => {
]}
/>

<div className="w-full border-b border-aws-squid-ink/10"></div>
<div className="w-full border-b border-aws-squid-ink-light/10 dark:border-aws-squid-ink-dark/10"></div>
</div>
))}
</>
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/components/ChatMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ const ChatMessage: React.FC<Props> = (props) => {

<div className="order-first col-span-12 flex lg:order-none lg:col-span-8 lg:col-start-3">
{chatContent?.role === 'user' && (
<div className="h-min rounded bg-aws-sea-blue p-2 text-xl text-white">
<div className="h-min rounded bg-aws-sea-blue-light dark:bg-aws-sea-blue-dark p-2 text-xl text-white">
<PiUserFill />
</div>
)}
Expand Down Expand Up @@ -312,7 +312,7 @@ const ChatMessage: React.FC<Props> = (props) => {
<div className="flex flex-col items-end lg:items-start">
{chatContent?.role === 'user' && !isEdit && (
<ButtonIcon
className="text-dark-gray"
className="text-dark-gray dark:text-light-gray"
onClick={() => {
setChangedContent(chatContent.content[firstTextContent].body);
setIsEdit(true);
Expand All @@ -323,7 +323,7 @@ const ChatMessage: React.FC<Props> = (props) => {
{chatContent?.role === 'assistant' && (
<div className="flex">
<ButtonIcon
className="text-dark-gray"
className="text-dark-gray dark:text-light-gray"
onClick={() => setIsFeedbackOpen(true)}>
{chatContent.feedback && !chatContent.feedback.thumbsUp ? (
<PiThumbsDownFill />
Expand All @@ -332,7 +332,7 @@ const ChatMessage: React.FC<Props> = (props) => {
)}
</ButtonIcon>
<ButtonCopy
className="text-dark-gray"
className="text-dark-gray dark:text-light-gray"
text={chatContent.content[0].body}
/>
</div>
Expand Down
Loading

0 comments on commit 644a3a2

Please sign in to comment.