From d7b56dd1a45a1145317d7787c1aa6e6b7ce0c145 Mon Sep 17 00:00:00 2001
From: jaimin
Date: Sun, 21 Sep 2025 13:48:37 +0530
Subject: [PATCH] hero section improved with modern look
---
package-lock.json | 65 +++++++++++++++++++++++++++
package.json | 1 +
src/components/home/hero.tsx | 16 +++----
src/components/ui/texts/gradient.tsx | 58 ++++++++++++++++++++++++
src/components/ui/texts/highlight.tsx | 65 +++++++++++++++++++++++++++
src/components/ui/texts/writing.tsx | 62 +++++++++++++++++++++++++
6 files changed, 257 insertions(+), 10 deletions(-)
create mode 100644 src/components/ui/texts/gradient.tsx
create mode 100644 src/components/ui/texts/highlight.tsx
create mode 100644 src/components/ui/texts/writing.tsx
diff --git a/package-lock.json b/package-lock.json
index e688a22..38c68e3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,6 +16,7 @@
"clsx": "^2.1.1",
"geist": "^1.4.2",
"lucide-react": "^0.513.0",
+ "motion": "^12.23.16",
"next": "15.3.3",
"next-sitemap": "^4.2.3",
"next-themes": "^0.4.6",
@@ -3713,6 +3714,32 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/framer-motion": {
+ "version": "12.23.16",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.16.tgz",
+ "integrity": "sha512-N81A8hiHqVsexOzI3wzkibyLURW1nEJsZaRuctPhG4AdbbciYu+bKJq9I2lQFzAO4Bx3h4swI6pBbF/Hu7f7BA==",
+ "dependencies": {
+ "motion-dom": "^12.23.12",
+ "motion-utils": "^12.23.6",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -4995,6 +5022,44 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/motion": {
+ "version": "12.23.16",
+ "resolved": "https://registry.npmjs.org/motion/-/motion-12.23.16.tgz",
+ "integrity": "sha512-8vVuxZgcfGZm4kgSqFgGrhQ+6034y4UuEsqCX8s7UYeoQ+NO3R9LV5AyDlVr2Mb7xvS7ZM5s/XkTurWbWQ+UHA==",
+ "dependencies": {
+ "framer-motion": "^12.23.16",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/motion-dom": {
+ "version": "12.23.12",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.12.tgz",
+ "integrity": "sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==",
+ "dependencies": {
+ "motion-utils": "^12.23.6"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "12.23.6",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz",
+ "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="
+ },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
diff --git a/package.json b/package.json
index 7bbe2e0..8527266 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"clsx": "^2.1.1",
"geist": "^1.4.2",
"lucide-react": "^0.513.0",
+ "motion": "^12.23.16",
"next": "15.3.3",
"next-sitemap": "^4.2.3",
"next-themes": "^0.4.6",
diff --git a/src/components/home/hero.tsx b/src/components/home/hero.tsx
index 82fb23a..ac09009 100644
--- a/src/components/home/hero.tsx
+++ b/src/components/home/hero.tsx
@@ -4,6 +4,9 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { ArrowRight, Github, Copy, Eye, Code2, Zap } from "lucide-react";
import { APP_CONFIG } from "@/lib/constants";
+import { WritingText } from "../ui/texts/writing";
+import { HighlightText } from "../ui/texts/highlight";
+import { GradientText } from "../ui/texts/gradient";
interface HeroProps {
activePattern?: string | null;
@@ -59,18 +62,11 @@ export default function Hero({ theme }: HeroProps) {
className={`font-medium transition-colors duration-300 ${isPatternDark ? "text-white" : "text-gray-900 dark:text-gray-50"
}`}
>
- Craft Beautiful
+
-
- Patterns Backgrounds
-
+
@@ -81,7 +77,7 @@ export default function Hero({ theme }: HeroProps) {
>
Professional-grade background patterns and gradients. Easily copy the
code and seamlessly integrate it into your projects.
- Crafted with modern CSS and Tailwind
+
{/* Feature highlights */}
diff --git a/src/components/ui/texts/gradient.tsx b/src/components/ui/texts/gradient.tsx
new file mode 100644
index 0000000..80a874c
--- /dev/null
+++ b/src/components/ui/texts/gradient.tsx
@@ -0,0 +1,58 @@
+'use client';
+
+import * as React from 'react';
+import { motion, type Transition } from 'motion/react';
+
+import { cn } from '@/lib/utils';
+
+type GradientTextProps = React.ComponentProps<'span'> & {
+ text: string;
+ gradient?: string;
+ neon?: boolean;
+ transition?: Transition;
+};
+
+function GradientText({
+ text,
+ className,
+ gradient = 'linear-gradient(90deg, #3b82f6 0%, #a855f7 20%, #ec4899 50%, #a855f7 80%, #3b82f6 100%)',
+ neon = false,
+ transition = { duration: 50, repeat: Infinity, ease: 'linear' },
+ ...props
+}: GradientTextProps) {
+ const baseStyle: React.CSSProperties = {
+ backgroundImage: gradient,
+ };
+
+ return (
+
+
+ {text}
+
+
+ {neon && (
+
+ {text}
+
+ )}
+
+ );
+}
+
+export { GradientText, type GradientTextProps };
\ No newline at end of file
diff --git a/src/components/ui/texts/highlight.tsx b/src/components/ui/texts/highlight.tsx
new file mode 100644
index 0000000..9ef8c84
--- /dev/null
+++ b/src/components/ui/texts/highlight.tsx
@@ -0,0 +1,65 @@
+'use client';
+
+import * as React from 'react';
+import {
+ motion,
+ useInView,
+ type HTMLMotionProps,
+ type Transition,
+ type UseInViewOptions,
+} from 'motion/react';
+
+import { cn } from '@/lib/utils';
+
+type HighlightTextProps = HTMLMotionProps<'span'> & {
+ text: string;
+ inView?: boolean;
+ inViewMargin?: UseInViewOptions['margin'];
+ inViewOnce?: boolean;
+ transition?: Transition;
+};
+
+function HighlightText({
+ ref,
+ text,
+ className,
+ inView = false,
+ inViewMargin = '0px',
+ transition = { duration: 2, ease: 'easeInOut' },
+ ...props
+}: HighlightTextProps) {
+ const localRef = React.useRef(null);
+ React.useImperativeHandle(ref, () => localRef.current as HTMLSpanElement);
+
+ const inViewResult = useInView(localRef, {
+ once: true,
+ margin: inViewMargin,
+ });
+ const isInView = !inView || inViewResult;
+
+ return (
+
+ {text}
+
+ );
+}
+
+export { HighlightText, type HighlightTextProps };
\ No newline at end of file
diff --git a/src/components/ui/texts/writing.tsx b/src/components/ui/texts/writing.tsx
new file mode 100644
index 0000000..5265e88
--- /dev/null
+++ b/src/components/ui/texts/writing.tsx
@@ -0,0 +1,62 @@
+'use client';
+
+import * as React from 'react';
+import {
+ motion,
+ useInView,
+ type Transition,
+ type UseInViewOptions,
+} from 'motion/react';
+
+type WritingTextProps = Omit, 'children'> & {
+ transition?: Transition;
+ inView?: boolean;
+ inViewMargin?: UseInViewOptions['margin'];
+ inViewOnce?: boolean;
+ spacing?: number | string;
+ text: string;
+};
+
+function WritingText({
+ ref,
+ inView = false,
+ inViewMargin = '0px',
+ inViewOnce = true,
+ spacing = 5,
+ text,
+ transition = { type: 'spring', bounce: 0, duration: 2, delay: 0.3 },
+ ...props
+}: WritingTextProps) {
+ const localRef = React.useRef(null);
+ React.useImperativeHandle(ref, () => localRef.current as HTMLSpanElement);
+
+ const inViewResult = useInView(localRef, {
+ once: inViewOnce,
+ margin: inViewMargin,
+ });
+ const isInView = !inView || inViewResult;
+
+ const words = React.useMemo(() => text.split(' '), [text]);
+
+ return (
+
+ {words.map((word, index) => (
+
+ {word}{' '}
+
+ ))}
+
+ );
+}
+
+export { WritingText, type WritingTextProps };
\ No newline at end of file