Skip to content

Commit 837230b

Browse files
committed
fix: animation
1 parent f726f78 commit 837230b

File tree

4 files changed

+92
-61
lines changed

4 files changed

+92
-61
lines changed

src/components/AIModal/AssistantMessage.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,14 @@ const AssistantMessage = props => {
3131
className="assistant-message"
3232
/>
3333
<Box sx={{ height: "2rem", marginTop: "-0.4rem", marginBottom: "1.6rem" }}>
34-
{allowOperation && (isLast || operationVisible) && (
35-
<Operation message={children as string} feedback={feedback} onThumbUp={onThumbUp} onThumbDown={onThumbDown} onRetry={onRetry}></Operation>
36-
)}
34+
<Operation
35+
visible={allowOperation && (isLast || operationVisible)}
36+
message={children as string}
37+
feedback={feedback}
38+
onThumbUp={onThumbUp}
39+
onThumbDown={onThumbDown}
40+
onRetry={onRetry}
41+
></Operation>
3742
</Box>
3843
</Box>
3944
</>

src/components/AIModal/MessagePanel.tsx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import UserMessage from "./UserMessage"
1313
const MessagePanel = props => {
1414
const { data, fetching, streaming, onRetry, onUpdateData } = props
1515

16-
const [feedbackAlertVisible, setFeedbackAlertVisible] = useState(false)
1716
// Reference to the bottom of the message panel for auto-scrolling
1817
const bottomRef = useRef<HTMLDivElement>(null)
1918

@@ -26,7 +25,6 @@ const MessagePanel = props => {
2625
}
2726

2827
const handleThumbUp = id => {
29-
setFeedbackAlertVisible(true)
3028
onUpdateData({ id, feedback: "good" })
3129

3230
const messageIndex = data.findIndex(message => message.id === id)
@@ -39,7 +37,6 @@ const MessagePanel = props => {
3937
}
4038

4139
const handleThumbDown = id => {
42-
setFeedbackAlertVisible(true)
4340
onUpdateData({ id, feedback: "bad" })
4441

4542
const messageIndex = data.findIndex(message => message.id === id)
@@ -83,12 +80,6 @@ const MessagePanel = props => {
8380
</Box>
8481
<SpinSvg className={clsx(fetching ? "visible mb-[1.6rem]" : "invisible")} />
8582
<div ref={bottomRef}></div>
86-
87-
<Box sx={{ position: "absolute", top: "2.4rem", left: "50%", transform: "translateX(-50%)" }}>
88-
<FeedbackAlert open={feedbackAlertVisible} duration={5e3} onClose={() => setFeedbackAlertVisible(false)}>
89-
Thanks for your feedback!
90-
</FeedbackAlert>
91-
</Box>
9283
</Box>
9384
)
9485
}

src/components/AIModal/Operation.tsx

Lines changed: 69 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { AnimatePresence, LayoutGroup, motion } from "motion/react"
12
import { useState } from "react"
23

34
import { Box, IconButton, Stack, Tooltip } from "@mui/material"
@@ -8,16 +9,22 @@ import ReSendSvg from "@/assets/svgs/header/re-send.svg"
89
import ThumbDownSvg from "@/assets/svgs/header/thumb-down.svg"
910
import ThumbUpSvg from "@/assets/svgs/header/thumb-up.svg"
1011

12+
const MotionBox = motion(Box)
13+
14+
const MotionStack = motion(Stack)
15+
16+
const MotionIconButton = motion(IconButton)
17+
1118
const Operation = props => {
12-
const { sx, feedback, message, onRetry, onThumbUp, onThumbDown } = props
19+
const { sx, visible, feedback, message, onRetry, onThumbUp, onThumbDown } = props
1320
const [tip, setTip] = useState<string>("")
1421

1522
const [copied, setCopied] = useState<boolean>(false)
1623

1724
const operations = [
1825
{
26+
key: "copy",
1927
icon: copied ? CheckedSvg : CopySvg,
20-
2128
tooltip: "Copy",
2229
onClick: () => {
2330
navigator.clipboard.writeText(message)
@@ -30,6 +37,7 @@ const Operation = props => {
3037
},
3138
},
3239
{
40+
key: "thumbUp",
3341
icon: ThumbUpSvg,
3442
hidden: feedback === "bad",
3543
tooltip: "Good Response",
@@ -39,6 +47,7 @@ const Operation = props => {
3947
},
4048
},
4149
{
50+
key: "thumbDown",
4251
icon: ThumbDownSvg,
4352
hidden: feedback === "good",
4453
tooltip: "Bad Response",
@@ -48,6 +57,7 @@ const Operation = props => {
4857
},
4958
},
5059
{
60+
key: "retry",
5161
icon: ReSendSvg,
5262
tooltip: "Try Again",
5363
onClick: () => {
@@ -57,52 +67,63 @@ const Operation = props => {
5767
]
5868

5969
return (
60-
<Box sx={{ position: "relative", ...sx }}>
61-
<Stack direction="row" gap="1.6rem">
62-
{operations
63-
.filter(({ hidden }) => !hidden)
64-
.map(({ icon: Icon, tooltip, disabled, onClick }, index) => (
65-
<Tooltip
66-
key={index}
67-
title={tip || tooltip}
68-
placement="bottom"
69-
arrow
70-
slotProps={{
71-
tooltip: {
72-
sx: {
73-
borderRadius: "0.4rem",
74-
fontSize: "1.2rem",
75-
lineHeight: "1.6rem",
76-
padding: "0.4rem 0.8rem",
77-
backgroundColor: "text.primary",
78-
marginTop: "0.8rem",
79-
"& .MuiTooltip-arrow": {
80-
color: "#101010",
81-
},
82-
},
83-
},
84-
}}
85-
>
86-
<IconButton
87-
sx={{
88-
p: 0,
89-
color: "#10101099",
90-
"&:hover": {
91-
color: "text.primary",
92-
backgroundColor: "unset",
93-
},
94-
height: "2rem",
95-
width: "2rem",
96-
}}
97-
disabled={disabled}
98-
onClick={onClick}
99-
>
100-
<Icon></Icon>
101-
</IconButton>
102-
</Tooltip>
103-
))}
104-
</Stack>
105-
</Box>
70+
<AnimatePresence>
71+
{visible && (
72+
<MotionBox sx={{ position: "relative", ...sx }} initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
73+
<MotionStack direction="row" gap="1.6rem">
74+
<AnimatePresence>
75+
{operations
76+
.filter(({ hidden }) => !hidden)
77+
.map(({ icon: Icon, key, tooltip, disabled, onClick }) => (
78+
<Tooltip
79+
key={key}
80+
title={tip || tooltip}
81+
placement="bottom"
82+
arrow
83+
slotProps={{
84+
tooltip: {
85+
sx: {
86+
borderRadius: "0.4rem",
87+
fontSize: "1.2rem",
88+
lineHeight: "1.6rem",
89+
padding: "0.4rem 0.8rem",
90+
backgroundColor: "text.primary",
91+
marginTop: "0.8rem",
92+
"& .MuiTooltip-arrow": {
93+
color: "#101010",
94+
},
95+
},
96+
},
97+
}}
98+
>
99+
<MotionIconButton
100+
key={key}
101+
layout
102+
initial={{ opacity: 0, x: 0, y: 0 }}
103+
animate={{ opacity: 1, x: 0, y: 0 }}
104+
exit={key === "thumbUp" ? { opacity: 0, x: 0, y: -10 } : { opacity: 0, x: -10, y: 0 }}
105+
sx={{
106+
p: 0,
107+
color: "#10101099",
108+
"&:hover": {
109+
color: "text.primary",
110+
backgroundColor: "unset",
111+
},
112+
height: "2rem",
113+
width: "2rem",
114+
}}
115+
disabled={disabled}
116+
onClick={onClick}
117+
>
118+
<Icon></Icon>
119+
</MotionIconButton>
120+
</Tooltip>
121+
))}
122+
</AnimatePresence>
123+
</MotionStack>
124+
</MotionBox>
125+
)}
126+
</AnimatePresence>
106127
)
107128
}
108129

src/components/AIModal/index.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import useGlobalStore from "@/stores/globalStore"
1414
import { lockBodyScroll } from "@/utils"
1515

1616
import AIInput from "./AIInput"
17+
import FeedbackAlert from "./FeedbackAlert"
1718
import InitialPanel from "./InitialPanel"
1819
import MessagePanel from "./MessagePanel"
1920
import { chatWithAI } from "./actions"
@@ -35,6 +36,7 @@ const AIModal = () => {
3536
const { isMobile } = useCheckViewport()
3637

3738
const [searchText, setSearchText] = useState("")
39+
const [feedbackAlertVisible, setFeedbackAlertVisible] = useState(false)
3840

3941
const [messages, setMessages] = useState<Message[]>([])
4042

@@ -169,6 +171,8 @@ const AIModal = () => {
169171
}
170172

171173
const handleUpdateData = ({ id, feedback }) => {
174+
// only feedback update the messages
175+
setFeedbackAlertVisible(true)
172176
setMessages(preValue => {
173177
return preValue.map(message => {
174178
if (message.id === id) {
@@ -245,7 +249,17 @@ const AIModal = () => {
245249
<InitialPanel onChat={handleSendMessage}></InitialPanel>
246250
)}
247251
<Box sx={{ p: ["0 2rem 2.4rem", "0 1.6rem 2.4rem"] }}>
248-
<AIInput value={searchText} disabled={loadingStatus !== "none"} onChange={handleChangeSearchText} onChat={handleSendMessage}></AIInput>
252+
<AIInput
253+
value={searchText}
254+
disabled={loadingStatus !== "none" || !searchText.trim()}
255+
onChange={handleChangeSearchText}
256+
onChat={handleSendMessage}
257+
></AIInput>
258+
</Box>
259+
<Box sx={{ position: "absolute", top: "8rem", left: "50%", transform: "translateX(-50%)" }}>
260+
<FeedbackAlert open={feedbackAlertVisible} duration={5e3} onClose={() => setFeedbackAlertVisible(false)}>
261+
Thanks for your feedback!
262+
</FeedbackAlert>
249263
</Box>
250264
</MotionCard>
251265
) : null}

0 commit comments

Comments
 (0)