Skip to content

Commit 7086259

Browse files
committed
feat: add motion library and enhance UI components
- Integrated the motion library for improved animations and transitions. - Added a new StripedPattern component for background effects on the homepage. - Updated homepage layout to utilize the StripedPattern for enhanced visual appeal. - Included registries for @MagicUI in components.json for both web and fumadocs applications.
1 parent 05406f3 commit 7086259

File tree

7 files changed

+217
-13
lines changed

7 files changed

+217
-13
lines changed

apps/fumadocs/components.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,7 @@
1818
"lib": "@/lib",
1919
"hooks": "@/hooks"
2020
},
21-
"registries": {}
21+
"registries": {
22+
"@magicui": "https://magicui.design/r/{name}"
23+
}
2224
}

apps/fumadocs/src/app/(home)/page.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
import { ArrowRight, Github } from "lucide-react";
22
import Link from "next/link";
3+
import { StripedPattern } from "@/components/ui/striped-pattern";
34

45
export default function HomePage() {
56
return (
67
<main className="relative flex flex-1 flex-col items-center justify-center overflow-hidden px-4 py-20">
7-
<div
8-
className="pointer-events-none absolute inset-0"
9-
style={{
10-
backgroundImage:
11-
"radial-gradient(circle at 1px 1px, var(--muted-foreground) 1px, transparent 0)",
12-
backgroundSize: "24px 24px",
13-
opacity: 0.15,
14-
maskImage:
15-
"radial-gradient(ellipse 70% 60% at 50% 40%, black 30%, transparent 100%)",
16-
}}
17-
/>
8+
<StripedPattern className="text-muted-foreground/20 [mask-image:radial-gradient(350px_circle_at_center,white,transparent)]" />
189

1910
<div className="relative flex max-w-3xl flex-col items-center gap-6 text-center">
2011
<h1 className="font-bold font-mono text-7xl tracking-tighter sm:text-8xl">
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type React from "react";
2+
import { useId } from "react";
3+
4+
import { cn } from "@/lib/utils";
5+
6+
interface StripedPatternProps extends React.SVGProps<SVGSVGElement> {
7+
direction?: "left" | "right";
8+
}
9+
10+
export function StripedPattern({
11+
direction = "left",
12+
className,
13+
width = 10,
14+
height = 10,
15+
...props
16+
}: StripedPatternProps) {
17+
const id = useId();
18+
const w = Number(width);
19+
const h = Number(height);
20+
21+
return (
22+
<svg
23+
aria-hidden="true"
24+
className={cn(
25+
"pointer-events-none absolute inset-0 z-10 h-full w-full stroke-[0.5]",
26+
className
27+
)}
28+
xmlns="http://www.w3.org/2000/svg"
29+
{...props}
30+
>
31+
<defs>
32+
<pattern height={h} id={id} patternUnits="userSpaceOnUse" width={w}>
33+
{direction === "left" ? (
34+
<>
35+
<line stroke="currentColor" x1="0" x2={w} y1={h} y2="0" />
36+
<line stroke="currentColor" x1={-w} x2="0" y1={h} y2="0" />
37+
<line stroke="currentColor" x1={w} x2={w * 2} y1={h} y2="0" />
38+
</>
39+
) : (
40+
<>
41+
<line stroke="currentColor" x1="0" x2={w} y1="0" y2={h} />
42+
<line stroke="currentColor" x1={-w} x2="0" y1="0" y2={h} />
43+
<line stroke="currentColor" x1={w} x2={w * 2} y1="0" y2={h} />
44+
</>
45+
)}
46+
</pattern>
47+
</defs>
48+
<rect fill={`url(#${id})`} height="100%" width="100%" />
49+
</svg>
50+
);
51+
}

apps/web/components.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,8 @@
1717
"lib": "@/lib",
1818
"hooks": "@/hooks"
1919
},
20-
"iconLibrary": "lucide"
20+
"iconLibrary": "lucide",
21+
"registries": {
22+
"@magicui": "https://magicui.design/r/{name}"
23+
}
2124
}

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"class-variance-authority": "^0.7.1",
2020
"clsx": "^2.1.1",
2121
"lucide-react": "^0.546.0",
22+
"motion": "^12.23.24",
2223
"next": "16.0.0",
2324
"next-themes": "^0.4.6",
2425
"radix-ui": "^1.4.3",
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import { motion } from "motion/react";
2+
import { type CSSProperties, useEffect, useState } from "react";
3+
4+
import { cn } from "@/lib/utils";
5+
6+
interface LightRaysProps extends React.HTMLAttributes<HTMLDivElement> {
7+
ref?: React.Ref<HTMLDivElement>;
8+
count?: number;
9+
color?: string;
10+
blur?: number;
11+
speed?: number;
12+
length?: string;
13+
}
14+
15+
type LightRay = {
16+
id: string;
17+
left: number;
18+
rotate: number;
19+
width: number;
20+
swing: number;
21+
delay: number;
22+
duration: number;
23+
intensity: number;
24+
};
25+
26+
const createRays = (count: number, cycle: number): LightRay[] => {
27+
if (count <= 0) {
28+
return [];
29+
}
30+
31+
return Array.from({ length: count }, (_, index) => {
32+
const left = 8 + Math.random() * 84;
33+
const rotate = -28 + Math.random() * 56;
34+
const width = 160 + Math.random() * 160;
35+
const swing = 0.8 + Math.random() * 1.8;
36+
const delay = Math.random() * cycle;
37+
const duration = cycle * (0.75 + Math.random() * 0.5);
38+
const intensity = 0.6 + Math.random() * 0.5;
39+
40+
return {
41+
id: `${index}-${Math.round(left * 10)}`,
42+
left,
43+
rotate,
44+
width,
45+
swing,
46+
delay,
47+
duration,
48+
intensity,
49+
};
50+
});
51+
};
52+
53+
const Ray = ({
54+
left,
55+
rotate,
56+
width,
57+
swing,
58+
delay,
59+
duration,
60+
intensity,
61+
}: LightRay) => (
62+
<motion.div
63+
animate={{
64+
opacity: [0, intensity, 0],
65+
rotate: [rotate - swing, rotate + swing, rotate - swing],
66+
}}
67+
className="-top-[12%] -translate-x-1/2 pointer-events-none absolute left-(--ray-left) h-(--light-rays-length) w-(--ray-width) origin-top rounded-full bg-linear-to-b from-[color-mix(in_srgb,var(--light-rays-color)_70%,transparent)] to-transparent opacity-0 mix-blend-screen blur-(--light-rays-blur)"
68+
initial={{ rotate }}
69+
style={
70+
{
71+
"--ray-left": `${left}%`,
72+
"--ray-width": `${width}px`,
73+
} as CSSProperties
74+
}
75+
transition={{
76+
duration,
77+
repeat: Number.POSITIVE_INFINITY,
78+
ease: "easeInOut",
79+
delay,
80+
repeatDelay: duration * 0.1,
81+
}}
82+
/>
83+
);
84+
85+
export function LightRays({
86+
className,
87+
style,
88+
count = 7,
89+
color = "rgba(160, 210, 255, 0.2)",
90+
blur = 36,
91+
speed = 14,
92+
length = "70vh",
93+
ref,
94+
...props
95+
}: LightRaysProps) {
96+
const [rays, setRays] = useState<LightRay[]>([]);
97+
const cycleDuration = Math.max(speed, 0.1);
98+
99+
useEffect(() => {
100+
setRays(createRays(count, cycleDuration));
101+
}, [count, cycleDuration]);
102+
103+
return (
104+
<div
105+
className={cn(
106+
"pointer-events-none absolute inset-0 isolate overflow-hidden rounded-[inherit]",
107+
className
108+
)}
109+
ref={ref}
110+
style={
111+
{
112+
"--light-rays-color": color,
113+
"--light-rays-blur": `${blur}px`,
114+
"--light-rays-length": length,
115+
...style,
116+
} as CSSProperties
117+
}
118+
{...props}
119+
>
120+
<div className="absolute inset-0 overflow-hidden">
121+
<div
122+
aria-hidden
123+
className="absolute inset-0 opacity-60"
124+
style={
125+
{
126+
background:
127+
"radial-gradient(circle at 20% 15%, color-mix(in srgb, var(--light-rays-color) 45%, transparent), transparent 70%)",
128+
} as CSSProperties
129+
}
130+
/>
131+
<div
132+
aria-hidden
133+
className="absolute inset-0 opacity-60"
134+
style={
135+
{
136+
background:
137+
"radial-gradient(circle at 80% 10%, color-mix(in srgb, var(--light-rays-color) 35%, transparent), transparent 75%)",
138+
} as CSSProperties
139+
}
140+
/>
141+
{rays.map((ray) => (
142+
<Ray key={ray.id} {...ray} />
143+
))}
144+
</div>
145+
</div>
146+
);
147+
}

bun.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)