feat: light theme mode

This commit is contained in:
butterfly
2024-04-25 21:57:50 +08:00
parent bb7422c526
commit 59583e53bd
34 changed files with 335 additions and 174 deletions

View File

@@ -182,7 +182,7 @@ export function ChatActions(props: {
return (
<div
key={act.text}
className={`flex items-center gap-3 p-3 bg-white hover:bg-select-btn rounded-action-btn leading-6`}
className={`flex items-center gap-3 p-3 rounded-action-btn leading-6`}
onClick={act.onClick}
>
{act.icon}
@@ -200,14 +200,14 @@ export function ChatActions(props: {
trigger="click"
placement="rt"
noArrow
popoverClassName="border-actions-popover border-gray-200 rounded-md shadow-actions-popover w-actions-popover bg-white "
popoverClassName="border border-chat-actions-popover-mobile rounded-md shadow-chat-actions-popover-mobile w-actions-popover bg-chat-actions-popover-panel-mobile "
>
<AddCircleIcon />
</Popover>
);
}
const popoverClassName = `bg-chat-actions-popover-color whitespace-nowrap px-3 py-2.5 text-white text-sm-title rounded-md`;
const popoverClassName = `bg-chat-actions-btn-popover whitespace-nowrap px-3 py-2.5 text-text-chat-actions-btn-popover text-sm-title rounded-md`;
return (
<div className={`flex gap-2 item-center ${props.className}`}>
@@ -222,7 +222,7 @@ export function ChatActions(props: {
placement={ind ? "t" : "lt"}
>
<div
className="h-[32px] w-[32px] flex items-center justify-center hover:bg-gray-200 hover:rounded-action-btn"
className="h-[32px] w-[32px] flex items-center justify-center hover:bg-chat-actions-btn-hovered hover:rounded-action-btn"
onClick={act.onClick}
>
{act.icon}
@@ -242,7 +242,7 @@ export function ChatActions(props: {
placement={ind === arr.length - 1 ? "rt" : "t"}
>
<div
className="h-[32px] w-[32px] flex items-center justify-center hover:bg-gray-200 hover:rounded-action-btn"
className="h-[32px] w-[32px] flex items-center justify-center hover:bg-chat-actions-btn-hovered hover:rounded-action-btn"
onClick={act.onClick}
>
{act.icon}

View File

@@ -44,11 +44,11 @@ export default function ChatHeader(props: ChatHeaderProps) {
return (
<div
className={`absolute w-[100%] backdrop-blur-[30px] z-20 flex flex-0 justify-between items-center px-6 py-4 gap-chat-header-gap border-b-[1px] border-gray-200 ${containerClassName}`}
className={`absolute w-[100%] backdrop-blur-[30px] z-20 flex flex-0 justify-between items-center px-6 py-4 gap-chat-header-gap sm:border-b sm:border-chat-header-bottom ${containerClassName}`}
data-tauri-drag-region
>
<div
className={`absolute z-[-1] top-0 left-0 w-[100%] h-[100%] opacity-85 backdrop-blur-[20px] bg-gray-50 flex flex-0 justify-between items-center gap-chat-header-gap`}
className={`absolute z-[-1] top-0 left-0 w-[100%] h-[100%] opacity-85 backdrop-blur-[20px] sm:bg-chat-panel-header-mask bg-chat-panel-header-mobile flex flex-0 justify-between items-center gap-chat-header-gap`}
>
{" "}
</div>
@@ -63,12 +63,14 @@ export default function ChatHeader(props: ChatHeaderProps) {
<div className={`flex-1 ${titleClassName}`}>
<div
className={`line-clamp-1 cursor-pointer text-black text-chat-header-title font-common ${mainTitleClassName}`}
className={`line-clamp-1 cursor-pointer text-text-chat-header-title text-chat-header-title font-common ${mainTitleClassName}`}
onClickCapture={() => setIsEditingMessage(true)}
>
{!session.topic ? DEFAULT_TOPIC : session.topic}
</div>
<div className={`text-gray-500 text-sm ${subTitleClassName}`}>
<div
className={`text-text-chat-header-subtitle text-sm ${subTitleClassName}`}
>
{isMobileScreen ? (
<div
className="flex items-center gap-1"

View File

@@ -203,13 +203,14 @@ export default forwardRef<ChatInputPanelInstance, ChatInputPanelProps>(
emitImages: setAttachImages,
setUploading,
});
let containerClassName = "border-t border-chat-input-top";
let inputClassName = " flex flex-col px-5 pb-5";
let actionsClassName = "py-2.5";
let labelClassName = "rounded-md p-4 gap-4";
let textarea = "min-h-chat-input";
if (isMobileScreen) {
containerClassName = "rounded-tl-md rounded-tr-md";
inputClassName = "flex flex-row-reverse items-center gap-2 p-3";
actionsClassName = "";
labelClassName = " rounded-chat-input p-3 gap-3 flex-1";
@@ -217,13 +218,11 @@ export default forwardRef<ChatInputPanelInstance, ChatInputPanelProps>(
}
return (
<div
className={`relative w-[100%] box-border border-gray-200 border-t-[1px]`}
>
<div className={`relative w-[100%] box-border ${containerClassName}`}>
<PromptHints
prompts={promptHints}
onPromptSelect={onPromptSelect}
className=" border-gray-200"
className=" border-chat-input-top"
/>
<div className={`${inputClassName}`}>
@@ -251,7 +250,7 @@ export default forwardRef<ChatInputPanelInstance, ChatInputPanelProps>(
isMobileScreen={isMobileScreen}
/>
<label
className={`cursor-text flex flex-col bg-white border-[1px] border-white focus-within:border-blue-300 focus-within:shadow-chat-input ${labelClassName}`}
className={`cursor-text flex flex-col bg-chat-panel-input-hood border border-chat-input-hood sm:focus-within:border-chat-input-hood-focus sm:focus-within:shadow-chat-input-hood-focus-shadow ${labelClassName}`}
htmlFor="chat-input"
>
{attachImages.length != 0 && (
@@ -295,14 +294,14 @@ export default forwardRef<ChatInputPanelInstance, ChatInputPanelProps>(
{!isMobileScreen && (
<div className="flex items-center justify-center text-sm gap-3">
<div className="flex-1">&nbsp;</div>
<div className="text-gray-500 text-time line-clamp-1">
<div className="text-text-chat-input-placeholder text-time line-clamp-1">
{Locale.Chat.Input(submitKey)}
</div>
<Btn
className="min-w-[77px]"
icon={<SendIcon />}
text={Locale.Chat.Send}
// className={styles["chat-input-send"]}
disabled={!userInput.length}
type="primary"
onClick={() => doSubmit(userInput)}
/>

View File

@@ -141,7 +141,7 @@ export default function ChatMessagePanel(props: ChatMessagePanelProps) {
return (
<div
className={`pt-[80px] relative flex-1 overscroll-y-none overflow-y-auto overflow-x-hidden px-3 pb-6`}
className={`pt-[80px] relative flex-1 overscroll-y-none overflow-y-auto overflow-x-hidden px-3 pb-6 md:bg-chat-panel-message bg-chat-panel-message-mobile`}
ref={scrollRef}
onScroll={(e) => onChatBodyScroll(e.currentTarget)}
onMouseDown={() => inputRef.current?.blur()}
@@ -189,7 +189,7 @@ export default function ChatMessagePanel(props: ChatMessagePanelProps) {
}`}
>
<div
className={` pointer-events-none text-gray-500 text-right text-time whitespace-nowrap transition-all duration-500 text-sm absolute z-1 ${
className={` pointer-events-none text-text-chat-message-date text-right text-time whitespace-nowrap transition-all duration-500 text-sm absolute z-1 ${
isUser ? "right-0" : "left-0"
} bottom-[100%] hidden group-hover:block`}
>
@@ -200,8 +200,8 @@ export default function ChatMessagePanel(props: ChatMessagePanelProps) {
<div
className={`transition-all duration-300 select-text break-words font-common text-sm-title ${
isUser
? "rounded-user-message bg-message-bg"
: "rounded-bot-message bg-white"
? "rounded-user-message bg-chat-panel-message-user"
: "rounded-bot-message bg-chat-panel-message-bot"
} box-border peer py-2 px-3`}
onPointerMoveCapture={(e) =>
getRelativePosition(e.currentTarget, message.id)
@@ -223,7 +223,9 @@ export default function ChatMessagePanel(props: ChatMessagePanelProps) {
parentRef={scrollRef}
defaultShow={i >= messages.length - 6}
className={`max-w-message-width ${
isUser ? " text-white" : "text-black"
isUser
? " text-text-chat-message-markdown-user"
: "text-text-chat-message-markdown-bot"
}`}
/>
<Imgs message={message} isMobileScreen={isMobileScreen} />

View File

@@ -256,10 +256,20 @@ function _Chat() {
const currentModel = chatStore.currentSession().mask.modelConfig.model;
const allModels = useAllModels();
const models = useMemo(
() => allModels.filter((m) => m.available),
[allModels],
);
const models = useMemo(() => {
const filteredModels = allModels.filter((m) => m.available);
const defaultModel = filteredModels.find((m) => m.isDefault);
if (defaultModel) {
const arr = [
defaultModel,
...filteredModels.filter((m) => m !== defaultModel),
];
return arr;
} else {
return filteredModels;
}
}, [allModels]);
return (
<div

View File

@@ -1,24 +1,45 @@
import { useChatStore } from "@/app/store/chat";
import Locale from "@/app/locales";
import styles from "./index.module.scss";
import { useAppConfig } from "@/app/store";
export default function ClearContextDivider() {
const chatStore = useChatStore();
const { isMobileScreen } = useAppConfig();
return (
<div
className={styles["clear-context"]}
onClick={() =>
className={`mt-6 mb-8 flex items-center justify-center gap-2.5`}
onClick={() => {
if (!isMobileScreen) {
return;
}
chatStore.updateCurrentSession(
(session) => (session.clearContextIndex = undefined),
)
}
);
}}
>
<div className={styles["clear-context-tips"]}>{Locale.Context.Clear}</div>
<div className={styles["clear-context-revert-btn"]}>
{Locale.Context.Revert}
<div className="bg-chat-panel-message-clear-divider h-[1px] w-10"> </div>
<div className="flex items-center justify-between gap-1 text-sm">
<div className={`text-text-chat-panel-message-clear`}>
{Locale.Context.Clear}
</div>
<div
className={`text-text-chat-panel-message-clear-revert underline font-common ${
!isMobileScreen ? " cursor-pointer" : ""
}`}
onClick={() => {
if (isMobileScreen) {
return;
}
chatStore.updateCurrentSession(
(session) => (session.clearContextIndex = undefined),
);
}}
>
{Locale.Context.Revert}
</div>
</div>
<div className="bg-chat-panel-message-clear-divider h-[1px] w-10"> </div>
</div>
);
}

View File

@@ -50,7 +50,8 @@ const genActionsShema = (
(message: RenderMessage) => void
>,
) => {
const className = " !p-1 hover:bg-gray-100 !rounded-actions-bar-btn ";
const className =
" !p-1 hover:bg-chat-message-actions-btn-hovered !rounded-actions-bar-btn ";
return [
{
id: "Edit",
@@ -267,9 +268,10 @@ export default function MessageActions(props: MessageActionsProps) {
pointer-events-none
group-hover:opacity-100
group-hover:pointer-events-auto
bg-white
bg-chat-message-actions
rounded-md
shadow-actions-bar
shadow-message-actions-bar
dark:bg-none
${className}
`}
>

View File

@@ -72,7 +72,7 @@ export default function PromptHints(props: {
${
notShowPrompt
? "max-h-[0vh] border-none"
: "border-b-[1px] pt-2.5 max-h-[50vh]"
: "border-b pt-2.5 max-h-[50vh]"
}
${props.className}
`}

View File

@@ -56,8 +56,8 @@ export function SessionItem(props: {
className={`group relative flex p-3 items-center gap-2 self-stretch rounded-md mb-2 ${
props.selected &&
(currentPath === Path.Chat || currentPath === Path.Home)
? `bg-blue-100 border-blue-200 border `
: `bg-gray-100 hover:bg-gray-200`
? `bg-chat-menu-session-selected border-chat-menu-session-selected border `
: `bg-chat-menu-session-unselected hover:bg-chat-menu-session-hovered`
}`}
onClick={props.onClick}
ref={(ele) => {
@@ -76,17 +76,17 @@ export function SessionItem(props: {
<div className="flex flex-col flex-1">
<div className={`flex justify-between items-center`}>
<div
className={` text-gray-900 text-sm-title line-clamp-1 flex-1`}
className={` text-text-chat-menu-item-title text-sm-title line-clamp-1 flex-1`}
>
{props.title}
</div>
<div
className={`text-gray-500 text-sm group-hover:opacity-0 pl-3`}
className={`text-text-chat-menu-item-time text-sm group-hover:opacity-0 pl-3`}
>
{getTime(props.time)}
</div>
</div>
<div className={`text-gray-500 text-sm`}>
<div className={`text-text-chat-menu-item-description text-sm`}>
{Locale.ChatItem.ChatItemCount(props.count)}
</div>
</div>
@@ -145,17 +145,19 @@ export default MenuLayout(function SessionList(props) {
moveSession(source.index, destination.index);
};
let layoutClassName = "flex flex-col py-7 px-0";
let layoutClassName = "flex flex-col px-0";
let titleClassName = "py-7";
if (isMobileScreen) {
layoutClassName = "flex flex-col py-6 pb-chat-panel-mobile ";
layoutClassName = "flex flex-col pb-chat-panel-mobile ";
titleClassName = "py-6 box-content h-0";
}
return (
<div className={`h-[100%] ${layoutClassName}`}>
<div data-tauri-drag-region>
<div
className={`flex items-center justify-between`}
className={`flex items-center justify-between ${titleClassName}`}
data-tauri-drag-region
>
<div className="">
@@ -175,7 +177,9 @@ export default MenuLayout(function SessionList(props) {
<AddIcon />
</div>
</div>
<div className={`pb-3 text-sm sm:text-sm-mobile text-blue-500`}>
<div
className={`pb-3 text-sm sm:text-sm-mobile text-text-chat-header-subtitle`}
>
Build your own AI assistant.
</div>
</div>