Skip to content

Commit 3970e81

Browse files
committed
feat: add ModeToggle and Volume components, update Map component with new animations
1 parent c4c22a2 commit 3970e81

File tree

6 files changed

+162
-20
lines changed

6 files changed

+162
-20
lines changed

src/components/animations/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,13 @@ import DynamicStatusButton from "./dynamic-status-button";
4545
import FluidButton from "./fluid-button";
4646
import IslandMode from "./island-mode";
4747
import Map from "./map";
48+
import ModeToggle from "./mode-toggle";
4849
import Plan from "./plan";
4950
import StackClick from "./stacked-click";
5051
import StatusButton from "./status-button";
5152
import TodoList from "./todo-list";
53+
import View from "./view";
54+
import Volume from "./volume";
5255

5356
export {
5457
AmieAction,
@@ -79,6 +82,7 @@ export {
7982
LiveBlogs,
8083
MagneticLines,
8184
Map,
85+
ModeToggle,
8286
MovieGallery,
8387
MusicSheet,
8488
NewHero,
@@ -98,8 +102,10 @@ export {
98102
Uploader,
99103
UserSearch,
100104
UserStacked,
105+
View,
101106
Wants,
102107
Wheel,
103108
WordRoll,
104109
YearsTabs,
110+
Volume,
105111
};

src/components/animations/map.tsx

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { cn } from "@/lib/utils";
2-
import { motion } from "motion/react";
2+
import { AnimatePresence, motion, Variants } from "motion/react";
33
import { useEffect, useRef, useState } from "react";
4-
import { buttonVariants } from "../ui/button";
4+
import { Pause, Play } from "lucide-react";
5+
6+
const playingVariants: Variants = {
7+
hidden: { opacity: 0, scale: 0.3, filter: "blur(4px)" },
8+
visible: { opacity: 1, scale: 1, filter: "blur(0px)" },
9+
};
510

611
const Map = () => {
712
const containerRef = useRef<HTMLDivElement>(null);
@@ -134,25 +139,41 @@ const Map = () => {
134139
initial={{ opacity: 0, y: 20 }}
135140
animate={{ opacity: 1, y: 0 }}
136141
transition={{ duration: 0.5 }}
137-
className="flex items-center bg-muted/10 p-4 rounded-lg mt-10 gap-10 border border-muted-foreground/20"
142+
className="flex gap-10"
138143
>
139144
<motion.button
140145
onClick={handlePlayPause}
141-
className={cn(buttonVariants({ variant: "outline" }))}
142-
initial={{ width: 80 }}
143-
animate={{
144-
width: isPlaying ? 90 : 80,
145-
}}
146-
transition={{
147-
duration: 0.3,
148-
type: "spring",
149-
bounce: 0,
150-
}}
146+
className="center h-10 max-w-10 w-10 min-w-10 border rounded-full"
151147
>
152-
{isPlaying ? "Pause" : "Play"}
148+
<AnimatePresence mode="wait" initial={false}>
149+
{isPlaying ? (
150+
<motion.span
151+
variants={playingVariants}
152+
initial="hidden"
153+
animate="visible"
154+
exit="hidden"
155+
key="pause"
156+
className="center size-full rounded-full"
157+
>
158+
<Pause className="size-4" />
159+
</motion.span>
160+
) : (
161+
<motion.span
162+
variants={playingVariants}
163+
initial="hidden"
164+
animate="visible"
165+
exit="hidden"
166+
key="play"
167+
className="center rounded-full"
168+
>
169+
<Play className="size-4" />
170+
</motion.span>
171+
)}
172+
</AnimatePresence>
173+
<span className="sr-only">{isPlaying ? "Pause" : "Play"}</span>
153174
</motion.button>
154175
<div className="flex items-center gap-2">
155-
<span className="text-zinc-400">Volume</span>
176+
<span className="text-zinc-400 sr-only">Volume</span>
156177
<input
157178
type="range"
158179
min="0"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import {
2+
AnimatePresence,
3+
motion as m,
4+
MotionConfig,
5+
Variants,
6+
} from "motion/react";
7+
import { useState } from "react";
8+
const modeVariants: Variants = {
9+
initial: {
10+
y: -40,
11+
opacity: 0,
12+
},
13+
visible: {
14+
y: 0,
15+
opacity: 1,
16+
},
17+
hidden: {
18+
y: 40,
19+
opacity: 0,
20+
},
21+
};
22+
23+
const ModeToggle = () => {
24+
const [mode, setMode] = useState<"light" | "dark">("light");
25+
26+
return (
27+
<MotionConfig transition={{ duration: 0.3, ease: "easeInOut" }}>
28+
<div className="full center">
29+
<m.button
30+
animate={{ width: "auto" }}
31+
whileTap={{ scale: 0.95 }}
32+
className="rounded-full bg-muted flex items-center justify-center gap-1 py-2 px-4 overflow-hidden "
33+
onClick={() => setMode(mode === "light" ? "dark" : "light")}
34+
>
35+
<div className="size-5 rounded bg-muted-foreground"></div>
36+
<AnimatePresence mode="wait">
37+
{mode === "light" ? (
38+
<m.span
39+
variants={modeVariants}
40+
initial="initial"
41+
animate="visible"
42+
exit="hidden"
43+
key="light"
44+
>
45+
Light
46+
</m.span>
47+
) : (
48+
<m.span
49+
variants={modeVariants}
50+
initial="initial"
51+
animate="visible"
52+
exit="hidden"
53+
key="dark"
54+
>
55+
Dark
56+
</m.span>
57+
)}
58+
</AnimatePresence>
59+
<span>Mode</span>
60+
</m.button>
61+
</div>
62+
</MotionConfig>
63+
);
64+
};
65+
66+
export default ModeToggle;

src/components/animations/volume.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const Volume = () => {
2+
return <div className="center full">Volume</div>;
3+
};
4+
5+
export default Volume;

src/components/shared/icons.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,4 +224,41 @@ export const Icons = {
224224
</defs>
225225
</svg>
226226
),
227+
dark: (props: IconProps) => (
228+
<svg
229+
xmlns="http://www.w3.org/2000/svg"
230+
width="100"
231+
height="100"
232+
viewBox="0 0 100 100"
233+
fill="none"
234+
{...props}
235+
>
236+
<rect width="100" height="100"></rect>
237+
<path
238+
d="M50 18C58.4869 18 66.6262 21.3714 72.6274 27.3726C78.6286 33.3737 82 41.513 82 50C82 58.4869 78.6286 66.6262 72.6275 72.6274C66.6263 78.6286 58.487 82 50.0001 82L50 50L50 18Z"
239+
className="will-change-transform"
240+
fill="currentColor"
241+
></path>
242+
<circle
243+
cx="50"
244+
cy="50"
245+
r="30"
246+
className="will-change-transform"
247+
strokeWidth="4"
248+
stroke="currentColor"
249+
></circle>
250+
<circle
251+
cx="50"
252+
cy="50"
253+
r="12"
254+
className="will-change-transform"
255+
fill="currentColor"
256+
></circle>
257+
<path
258+
d="M50 62C53.1826 62 56.2348 60.7357 58.4853 58.4853C60.7357 56.2348 62 53.1826 62 50C62 46.8174 60.7357 43.7652 58.4853 41.5147C56.2348 39.2643 53.1826 38 50 38L50 50L50 62Z"
259+
className="will-change-transform"
260+
fill="currentColor"
261+
></path>
262+
</svg>
263+
),
227264
};

src/pages/home.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
LiveBlogs,
3030
MagneticLines,
3131
Map,
32+
ModeToggle,
3233
MovieGallery,
3334
MusicSheet,
3435
NewHero,
@@ -51,8 +52,9 @@ import {
5152
Wheel,
5253
WordRoll,
5354
YearsTabs,
55+
View,
56+
Volume,
5457
} from "@/components/animations";
55-
import View from "@/components/animations/view";
5658

5759
const Home = () => {
5860
const [isHidden, setIsHidden] = useState(false);
@@ -73,6 +75,15 @@ const Home = () => {
7375
<div className="h-screen fixed top-0 max-w-screen-lg inset-x-0 w-full mx-auto border-x border -z-10 candy-bg hidden md:block" />
7476
<Hero hidden={isHidden} />
7577
<Feedback hidden={isHidden} />
78+
<ComponentPreview notReady>
79+
<Volume />
80+
</ComponentPreview>
81+
<ComponentPreview>
82+
<Map />
83+
</ComponentPreview>
84+
<ComponentPreview notReady>
85+
<ModeToggle />
86+
</ComponentPreview>
7687
<ComponentPreview>
7788
<View />
7889
</ComponentPreview>
@@ -89,10 +100,6 @@ const Home = () => {
89100
<ComponentPreview>
90101
<FluidButton />
91102
</ComponentPreview>
92-
<ComponentPreview notReady>
93-
<Map />
94-
</ComponentPreview>
95-
96103
<ComponentPreview>
97104
<DotMatrixClock />
98105
</ComponentPreview>

0 commit comments

Comments
 (0)