forked from XiaoMo/ChatGPT-Next-Web
fixup: ux improve
This commit is contained in:
parent
e8dd391ccf
commit
2647bdb4ed
@ -8,6 +8,7 @@ export function IconButton(props: {
|
||||
text?: string;
|
||||
bordered?: boolean;
|
||||
shadow?: boolean;
|
||||
noDark?: boolean;
|
||||
className?: string;
|
||||
title?: string;
|
||||
}) {
|
||||
@ -23,7 +24,11 @@ export function IconButton(props: {
|
||||
title={props.title}
|
||||
role="button"
|
||||
>
|
||||
<div className={styles["icon-button-icon"]}>{props.icon}</div>
|
||||
<div
|
||||
className={styles["icon-button-icon"] + ` ${props.noDark && "no-dark"}`}
|
||||
>
|
||||
{props.icon}
|
||||
</div>
|
||||
{props.text && (
|
||||
<div className={styles["icon-button-text"]}>{props.text}</div>
|
||||
)}
|
||||
|
@ -1,3 +1,5 @@
|
||||
@import "../styles/animation.scss";
|
||||
|
||||
.prompt-toast {
|
||||
position: absolute;
|
||||
bottom: -50px;
|
||||
@ -19,6 +21,8 @@
|
||||
padding: 10px 20px;
|
||||
border-radius: 100px;
|
||||
|
||||
animation: slide-in-from-top ease 0.3s;
|
||||
|
||||
.prompt-toast-content {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ const Emoji = dynamic(async () => (await import("emoji-picker-react")).Emoji, {
|
||||
export function Avatar(props: { role: Message["role"] }) {
|
||||
const config = useChatStore((state) => state.config);
|
||||
|
||||
if (props.role === "assistant") {
|
||||
if (props.role !== "user") {
|
||||
return <BotIcon className={styles["user-avtar"]} />;
|
||||
}
|
||||
|
||||
@ -99,7 +99,8 @@ function exportMessages(messages: Message[], topic: string) {
|
||||
}
|
||||
|
||||
function PromptToast(props: {
|
||||
showModal: boolean;
|
||||
showToast?: boolean;
|
||||
showModal?: boolean;
|
||||
setShowModal: (_: boolean) => void;
|
||||
}) {
|
||||
const chatStore = useChatStore();
|
||||
@ -126,16 +127,18 @@ function PromptToast(props: {
|
||||
|
||||
return (
|
||||
<div className={chatStyle["prompt-toast"]} key="prompt-toast">
|
||||
<div
|
||||
className={chatStyle["prompt-toast-inner"] + " clickable"}
|
||||
role="button"
|
||||
onClick={() => props.setShowModal(true)}
|
||||
>
|
||||
<BrainIcon />
|
||||
<span className={chatStyle["prompt-toast-content"]}>
|
||||
{Locale.Context.Toast(context.length)}
|
||||
</span>
|
||||
</div>
|
||||
{props.showToast && (
|
||||
<div
|
||||
className={chatStyle["prompt-toast-inner"] + " clickable"}
|
||||
role="button"
|
||||
onClick={() => props.setShowModal(true)}
|
||||
>
|
||||
<BrainIcon />
|
||||
<span className={chatStyle["prompt-toast-content"]}>
|
||||
{Locale.Context.Toast(context.length)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{props.showModal && (
|
||||
<div className="modal-mask">
|
||||
<Modal
|
||||
@ -187,6 +190,7 @@ function PromptToast(props: {
|
||||
icon={<DeleteIcon />}
|
||||
className={chatStyle["context-delete-button"]}
|
||||
onClick={() => removeContextPrompt(i)}
|
||||
bordered
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
@ -281,7 +285,7 @@ function useScrollToBottom() {
|
||||
useLayoutEffect(() => {
|
||||
const dom = scrollRef.current;
|
||||
if (dom && autoScroll) {
|
||||
setTimeout(() => (dom.scrollTop = dom.scrollHeight), 500);
|
||||
setTimeout(() => (dom.scrollTop = dom.scrollHeight), 1);
|
||||
}
|
||||
});
|
||||
|
||||
@ -310,6 +314,12 @@ export function Chat(props: {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { submitKey, shouldSubmit } = useSubmitHandler();
|
||||
const { scrollRef, setAutoScroll } = useScrollToBottom();
|
||||
const [hitBottom, setHitBottom] = useState(false);
|
||||
|
||||
const onChatBodyScroll = (e: HTMLElement) => {
|
||||
const isTouchBottom = e.scrollTop + e.clientHeight >= e.scrollHeight - 20;
|
||||
setHitBottom(isTouchBottom);
|
||||
};
|
||||
|
||||
// prompt hints
|
||||
const promptStore = usePromptStore();
|
||||
@ -505,12 +515,17 @@ export function Chat(props: {
|
||||
</div>
|
||||
|
||||
<PromptToast
|
||||
showToast={!hitBottom}
|
||||
showModal={showPromptModal}
|
||||
setShowModal={setShowPromptModal}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles["chat-body"]} ref={scrollRef}>
|
||||
<div
|
||||
className={styles["chat-body"]}
|
||||
ref={scrollRef}
|
||||
onScroll={(e) => onChatBodyScroll(e.currentTarget)}
|
||||
>
|
||||
{messages.map((message, i) => {
|
||||
const isUser = message.role === "user";
|
||||
|
||||
@ -612,7 +627,8 @@ export function Chat(props: {
|
||||
<IconButton
|
||||
icon={<SendWhiteIcon />}
|
||||
text={Locale.Chat.Send}
|
||||
className={styles["chat-input-send"] + " no-dark"}
|
||||
className={styles["chat-input-send"]}
|
||||
noDark
|
||||
onClick={onUserSubmit}
|
||||
/>
|
||||
</div>
|
||||
|
@ -1,4 +1,5 @@
|
||||
@import "./window.scss";
|
||||
@import "../styles/animation.scss";
|
||||
|
||||
@mixin container {
|
||||
background-color: var(--white);
|
||||
@ -73,7 +74,7 @@
|
||||
.sidebar {
|
||||
position: absolute;
|
||||
left: -100%;
|
||||
z-index: 999;
|
||||
z-index: 1000;
|
||||
height: var(--full-height);
|
||||
transition: all ease 0.3s;
|
||||
box-shadow: none;
|
||||
@ -132,18 +133,6 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@keyframes slide-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
}
|
||||
|
||||
.chat-item:hover {
|
||||
background-color: var(--hover-color);
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
@import "../styles/animation.scss";
|
||||
|
||||
.card {
|
||||
background-color: var(--white);
|
||||
border-radius: 10px;
|
||||
@ -24,18 +26,6 @@
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
@keyframes slide-in {
|
||||
from {
|
||||
transform: translateY(10px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -35,7 +35,7 @@ const cn = {
|
||||
Download: "下载文件",
|
||||
},
|
||||
Memory: {
|
||||
Title: "上下文记忆 Prompt",
|
||||
Title: "历史记忆",
|
||||
EmptyContent: "尚未记忆",
|
||||
Copy: "全部复制",
|
||||
},
|
||||
|
23
app/styles/animation.scss
Normal file
23
app/styles/animation.scss
Normal file
@ -0,0 +1,23 @@
|
||||
@keyframes slide-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-in-from-top {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user