Skip to content

Commit ac3d076

Browse files
committed
Add some animations
1 parent dda440a commit ac3d076

6 files changed

Lines changed: 305 additions & 16 deletions

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"clsx": "^2.0.0",
5656
"cmdk": "^0.2.0",
5757
"eventsource-parser": "^1.0.0",
58+
"framer-motion": "^10.16.0",
5859
"fuse.js": "^6.6.2",
5960
"github-markdown-css": "^5.2.0",
6061
"gpt3-tokenizer": "^1.1.5",
@@ -73,6 +74,7 @@
7374
"plausible-tracker": "^0.3.8",
7475
"react": "^18.2.0",
7576
"react-color": "^2.19.3",
77+
"react-confetti-explosion": "^2.1.2",
7678
"react-copy-to-clipboard": "^5.1.0",
7779
"react-dom": "^18.2.0",
7880
"react-hot-toast": "^2.4.1",

src/app/components/Chat/ConversationPanel.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { cx } from '~/utils'
1+
import { motion } from 'framer-motion'
22
import { FC, ReactNode, useCallback, useMemo, useState } from 'react'
33
import { useTranslation } from 'react-i18next'
44
import clearIcon from '~/assets/icons/clear.svg'
55
import historyIcon from '~/assets/icons/history.svg'
66
import shareIcon from '~/assets/icons/share.svg'
7+
import { cx } from '~/utils'
78
import { CHATBOTS } from '~app/consts'
89
import { ConversationContext, ConversationContextValue } from '~app/context'
910
import { trackEvent } from '~app/plausible'
@@ -90,7 +91,11 @@ const ConversationPanel: FC<Props> = (props) => {
9091
)}
9192
>
9293
<div className="flex flex-row items-center">
93-
<img src={botInfo.avatar} className="w-[18px] h-[18px] object-contain rounded-full" />
94+
<motion.img
95+
src={botInfo.avatar}
96+
className="w-[18px] h-[18px] object-contain rounded-full"
97+
whileHover={{ rotate: 180 }}
98+
/>
9499
<Tooltip content={props.bot.name || botInfo.name}>
95100
<span className="font-semibold text-primary-text text-sm cursor-default ml-2 mr-1">{botInfo.name}</span>
96101
</Tooltip>

src/app/components/Sidebar/PremiumEntry.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
1+
import { motion } from 'framer-motion'
2+
import { Link } from '@tanstack/react-router'
13
import { FC } from 'react'
24
import premiumIcon from '~assets/icons/premium.svg'
3-
import { Link } from '@tanstack/react-router'
45

56
const PremiumEntry: FC<{ text: string }> = ({ text }) => {
67
return (
78
<Link to="/premium">
8-
<div
9+
<motion.div
910
className="flex flex-row items-center gap-[10px] rounded-[10px] px-4 py-[6px] cursor-pointer"
1011
style={{
1112
background:
12-
'linear-gradient(275deg, rgb(var(--color-primary-purple)) 1.65%, rgb(var(--color-primary-blue)) 100%)',
13+
'linear-gradient(to left, rgb(var(--color-primary-purple)) 1.65%, rgb(var(--color-primary-blue)) 100%)',
1314
}}
15+
whileHover="hover"
1416
>
15-
<img src={premiumIcon} className="w-8 h-8" />
17+
<motion.img
18+
src={premiumIcon}
19+
className="w-8 h-8"
20+
variants={{
21+
hover: { rotate: [0, 10, -10, 10, -10, 0] },
22+
}}
23+
transition={{ duration: 1 }}
24+
/>
1625
{!!text && <span className="text-white font-semibold text-base">{text}</span>}
17-
</div>
26+
</motion.div>
1827
</Link>
1928
)
2029
}

src/app/components/Sidebar/index.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Link } from '@tanstack/react-router'
2+
import { motion } from 'framer-motion'
23
import { cx } from '~/utils'
34
import { useAtom } from 'jotai'
45
import { useState } from 'react'
@@ -37,15 +38,18 @@ function Sidebar() {
3738
const [themeSettingModalOpen, setThemeSettingModalOpen] = useState(false)
3839
const enabledBots = useEnabledBots()
3940
return (
40-
<aside
41+
<motion.aside
4142
className={cx(
4243
'flex flex-col bg-primary-background bg-opacity-40 overflow-hidden',
4344
collapsed ? 'items-center px-[15px]' : 'w-[230px] px-4',
4445
)}
4546
>
46-
<img
47+
<motion.img
4748
src={collapseIcon}
48-
className={cx('w-6 h-6 cursor-pointer my-5', collapsed ? 'rotate-180' : 'self-end')}
49+
className={cx('w-6 h-6 cursor-pointer my-5', !collapsed && 'self-end')}
50+
animate={{
51+
rotate: collapsed ? 180 : 0,
52+
}}
4953
onClick={() => setCollapsed((c) => !c)}
5054
/>
5155
{collapsed ? <img src={minimalLogo} className="w-[30px]" /> : <img src={logo} className="w-[79px]" />}
@@ -101,7 +105,7 @@ function Sidebar() {
101105
<CommandBar />
102106
<GuideModal />
103107
{themeSettingModalOpen && <ThemeSettingModal open={true} onClose={() => setThemeSettingModalOpen(false)} />}
104-
</aside>
108+
</motion.aside>
105109
)
106110
}
107111

src/app/pages/PremiumPage.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useSearch } from '@tanstack/react-router'
2+
import ConfettiExplosion from 'react-confetti-explosion'
23
import { useAtom } from 'jotai'
34
import { useCallback, useState } from 'react'
45
import { Toaster } from 'react-hot-toast'
@@ -19,6 +20,7 @@ function PremiumPage() {
1920
const premiumState = usePremium()
2021
const [deactivating, setDeactivating] = useState(false)
2122
const { source } = useSearch({ from: premiumRoute.id })
23+
const [isExploding, setIsExploding] = useState(false)
2224

2325
const activateLicense = useCallback(() => {
2426
const key = window.prompt('Enter your license key', '')
@@ -55,7 +57,12 @@ function PremiumPage() {
5557
<div className="flex flex-row items-center gap-3 mt-10">
5658
{premiumState.activated ? (
5759
<>
58-
<Button text={t('🎉 License activated')} color="primary" className="w-fit !py-2" />
60+
<Button
61+
text={t('🎉 License activated')}
62+
color="primary"
63+
className="w-fit !py-2"
64+
onClick={() => setIsExploding(true)}
65+
/>
5966
<Button
6067
text={t('Deactivate')}
6168
className="w-fit !py-2"
@@ -93,6 +100,7 @@ function PremiumPage() {
93100
</div>
94101
{!!premiumState.error && <span className="mt-3 text-red-500 font-medium">{premiumState.error}</span>}
95102
<Toaster position="top-right" />
103+
{isExploding && <ConfettiExplosion duration={3000} onComplete={() => setIsExploding(false)} />}
96104
</div>
97105
)
98106
}

0 commit comments

Comments
 (0)