From 94b0c68703205a26f051c47943bde166ea70aa0d Mon Sep 17 00:00:00 2001 From: Adem Date: Tue, 17 Feb 2026 00:14:38 +0100 Subject: [PATCH] Finished Landing Page --- app/globals.css | 4 +- app/layout.tsx | 13 +- app/provider.tsx | 7 +- components.json | 4 +- components/ui/background-beams.tsx | 141 ++++++++ components/ui/bento-grid.tsx | 54 +++ components/ui/glowing-effect.tsx | 190 ++++++++++ components/ui/mode-toggle.tsx | 50 +++ components/ui/spotlight-new.tsx | 128 +++++++ components/views/Home/Features.tsx | 427 ++++++++++++----------- components/views/Home/Footer.tsx | 229 +++--------- components/views/Home/Hero.tsx | 304 ++++++++++++++-- components/views/Home/HomePage.tsx | 9 +- components/views/Home/HowItWorks.tsx | 499 ++++++++++++--------------- components/views/Home/Navbar.tsx | 122 ++++--- components/views/Home/Stats.tsx | 342 +++++++++--------- hooks/useTheme.ts | 22 -- package-lock.json | 69 ++++ package.json | 1 + public/LexiChain.png | Bin 0 -> 47137 bytes 20 files changed, 1662 insertions(+), 953 deletions(-) create mode 100644 components/ui/background-beams.tsx create mode 100644 components/ui/bento-grid.tsx create mode 100644 components/ui/glowing-effect.tsx create mode 100644 components/ui/mode-toggle.tsx create mode 100644 components/ui/spotlight-new.tsx delete mode 100644 hooks/useTheme.ts create mode 100644 public/LexiChain.png diff --git a/app/globals.css b/app/globals.css index aace076..b2c5819 100644 --- a/app/globals.css +++ b/app/globals.css @@ -4,8 +4,9 @@ @layer base { :root { + color-scheme: light; /* Light Mode - Smart-Admin Copilot Palette */ - --background: 0 0% 100%; + --background: 210 40% 98%; --foreground: 222 47% 11%; --card: 210 40% 98%; --card-foreground: 222 47% 11%; @@ -41,6 +42,7 @@ } .dark { + color-scheme: dark; /* Dark Mode - Smart-Admin Copilot Palette */ --background: 222 47% 5%; --foreground: 210 40% 98%; diff --git a/app/layout.tsx b/app/layout.tsx index ba3b658..a91ec1e 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,16 +1,19 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import { Poppins, Geist_Mono } from "next/font/google"; import "./globals.css"; import { Providers } from "./provider"; -const geistSans = Geist({ - variable: "--font-geist-sans", +const poppins = Poppins({ subsets: ["latin"], + weight: ["400", "500", "600", "700", "800", "900"], + variable: "--font-poppins", + display: "swap", }); const geistMono = Geist_Mono({ - variable: "--font-geist-mono", subsets: ["latin"], + variable: "--font-geist-mono", + display: "swap", }); export const metadata: Metadata = { @@ -26,7 +29,7 @@ export default function RootLayout({ return ( {children} diff --git a/app/provider.tsx b/app/provider.tsx index 82d3d90..0da5e24 100644 --- a/app/provider.tsx +++ b/app/provider.tsx @@ -4,7 +4,12 @@ import { ReactNode } from "react"; export function Providers({ children }: { children: ReactNode }) { return ( - + {children} ); diff --git a/components.json b/components.json index 7b3464b..6e2117a 100644 --- a/components.json +++ b/components.json @@ -19,5 +19,7 @@ "lib": "@/lib", "hooks": "@/hooks" }, - "registries": {} + "registries": { + "@aceternity": "https://ui.aceternity.com/registry/{name}.json" + } } diff --git a/components/ui/background-beams.tsx b/components/ui/background-beams.tsx new file mode 100644 index 0000000..b2281ca --- /dev/null +++ b/components/ui/background-beams.tsx @@ -0,0 +1,141 @@ +"use client"; +import React from "react"; +import { motion } from "motion/react"; +import { cn } from "@/lib/utils"; + +export const BackgroundBeams = React.memo( + ({ className }: { className?: string }) => { + const paths = [ + "M-380 -189C-380 -189 -312 216 152 343C616 470 684 875 684 875", + "M-373 -197C-373 -197 -305 208 159 335C623 462 691 867 691 867", + "M-366 -205C-366 -205 -298 200 166 327C630 454 698 859 698 859", + "M-359 -213C-359 -213 -291 192 173 319C637 446 705 851 705 851", + "M-352 -221C-352 -221 -284 184 180 311C644 438 712 843 712 843", + "M-345 -229C-345 -229 -277 176 187 303C651 430 719 835 719 835", + "M-338 -237C-338 -237 -270 168 194 295C658 422 726 827 726 827", + "M-331 -245C-331 -245 -263 160 201 287C665 414 733 819 733 819", + "M-324 -253C-324 -253 -256 152 208 279C672 406 740 811 740 811", + "M-317 -261C-317 -261 -249 144 215 271C679 398 747 803 747 803", + "M-310 -269C-310 -269 -242 136 222 263C686 390 754 795 754 795", + "M-303 -277C-303 -277 -235 128 229 255C693 382 761 787 761 787", + "M-296 -285C-296 -285 -228 120 236 247C700 374 768 779 768 779", + "M-289 -293C-289 -293 -221 112 243 239C707 366 775 771 775 771", + "M-282 -301C-282 -301 -214 104 250 231C714 358 782 763 782 763", + "M-275 -309C-275 -309 -207 96 257 223C721 350 789 755 789 755", + "M-268 -317C-268 -317 -200 88 264 215C728 342 796 747 796 747", + "M-261 -325C-261 -325 -193 80 271 207C735 334 803 739 803 739", + "M-254 -333C-254 -333 -186 72 278 199C742 326 810 731 810 731", + "M-247 -341C-247 -341 -179 64 285 191C749 318 817 723 817 723", + "M-240 -349C-240 -349 -172 56 292 183C756 310 824 715 824 715", + "M-233 -357C-233 -357 -165 48 299 175C763 302 831 707 831 707", + "M-226 -365C-226 -365 -158 40 306 167C770 294 838 699 838 699", + "M-219 -373C-219 -373 -151 32 313 159C777 286 845 691 845 691", + "M-212 -381C-212 -381 -144 24 320 151C784 278 852 683 852 683", + "M-205 -389C-205 -389 -137 16 327 143C791 270 859 675 859 675", + "M-198 -397C-198 -397 -130 8 334 135C798 262 866 667 866 667", + "M-191 -405C-191 -405 -123 0 341 127C805 254 873 659 873 659", + "M-184 -413C-184 -413 -116 -8 348 119C812 246 880 651 880 651", + "M-177 -421C-177 -421 -109 -16 355 111C819 238 887 643 887 643", + "M-170 -429C-170 -429 -102 -24 362 103C826 230 894 635 894 635", + "M-163 -437C-163 -437 -95 -32 369 95C833 222 901 627 901 627", + "M-156 -445C-156 -445 -88 -40 376 87C840 214 908 619 908 619", + "M-149 -453C-149 -453 -81 -48 383 79C847 206 915 611 915 611", + "M-142 -461C-142 -461 -74 -56 390 71C854 198 922 603 922 603", + "M-135 -469C-135 -469 -67 -64 397 63C861 190 929 595 929 595", + "M-128 -477C-128 -477 -60 -72 404 55C868 182 936 587 936 587", + "M-121 -485C-121 -485 -53 -80 411 47C875 174 943 579 943 579", + "M-114 -493C-114 -493 -46 -88 418 39C882 166 950 571 950 571", + "M-107 -501C-107 -501 -39 -96 425 31C889 158 957 563 957 563", + "M-100 -509C-100 -509 -32 -104 432 23C896 150 964 555 964 555", + "M-93 -517C-93 -517 -25 -112 439 15C903 142 971 547 971 547", + "M-86 -525C-86 -525 -18 -120 446 7C910 134 978 539 978 539", + "M-79 -533C-79 -533 -11 -128 453 -1C917 126 985 531 985 531", + "M-72 -541C-72 -541 -4 -136 460 -9C924 118 992 523 992 523", + "M-65 -549C-65 -549 3 -144 467 -17C931 110 999 515 999 515", + "M-58 -557C-58 -557 10 -152 474 -25C938 102 1006 507 1006 507", + "M-51 -565C-51 -565 17 -160 481 -33C945 94 1013 499 1013 499", + "M-44 -573C-44 -573 24 -168 488 -41C952 86 1020 491 1020 491", + "M-37 -581C-37 -581 31 -176 495 -49C959 78 1027 483 1027 483", + ]; + return ( +
+ + + + {paths.map((path, index) => ( + + ))} + + {paths.map((path, index) => ( + + + + + + + ))} + + + + + + + + +
+ ); + }, +); + +BackgroundBeams.displayName = "BackgroundBeams"; diff --git a/components/ui/bento-grid.tsx b/components/ui/bento-grid.tsx new file mode 100644 index 0000000..cf6866b --- /dev/null +++ b/components/ui/bento-grid.tsx @@ -0,0 +1,54 @@ +import { cn } from "@/lib/utils"; + +export const BentoGrid = ({ + className, + children, +}: { + className?: string; + children?: React.ReactNode; +}) => { + return ( +
+ {children} +
+ ); +}; + +export const BentoGridItem = ({ + className, + title, + description, + header, + icon, +}: { + className?: string; + title?: string | React.ReactNode; + description?: string | React.ReactNode; + header?: React.ReactNode; + icon?: React.ReactNode; +}) => { + return ( +
+ {header} +
+ {icon} +
+ {title} +
+
+ {description} +
+
+
+ ); +}; diff --git a/components/ui/glowing-effect.tsx b/components/ui/glowing-effect.tsx new file mode 100644 index 0000000..9321271 --- /dev/null +++ b/components/ui/glowing-effect.tsx @@ -0,0 +1,190 @@ +"use client"; + +import { memo, useCallback, useEffect, useRef } from "react"; +import { cn } from "@/lib/utils"; +import { animate } from "motion/react"; + +interface GlowingEffectProps { + blur?: number; + inactiveZone?: number; + proximity?: number; + spread?: number; + variant?: "default" | "white"; + glow?: boolean; + className?: string; + disabled?: boolean; + movementDuration?: number; + borderWidth?: number; +} +const GlowingEffect = memo( + ({ + blur = 0, + inactiveZone = 0.7, + proximity = 0, + spread = 20, + variant = "default", + glow = false, + className, + movementDuration = 2, + borderWidth = 1, + disabled = true, + }: GlowingEffectProps) => { + const containerRef = useRef(null); + const lastPosition = useRef({ x: 0, y: 0 }); + const animationFrameRef = useRef(0); + + const handleMove = useCallback( + (e?: MouseEvent | { x: number; y: number }) => { + if (!containerRef.current) return; + + if (animationFrameRef.current) { + cancelAnimationFrame(animationFrameRef.current); + } + + animationFrameRef.current = requestAnimationFrame(() => { + const element = containerRef.current; + if (!element) return; + + const { left, top, width, height } = element.getBoundingClientRect(); + const mouseX = e?.x ?? lastPosition.current.x; + const mouseY = e?.y ?? lastPosition.current.y; + + if (e) { + lastPosition.current = { x: mouseX, y: mouseY }; + } + + const center = [left + width * 0.5, top + height * 0.5]; + const distanceFromCenter = Math.hypot( + mouseX - center[0], + mouseY - center[1] + ); + const inactiveRadius = 0.5 * Math.min(width, height) * inactiveZone; + + if (distanceFromCenter < inactiveRadius) { + element.style.setProperty("--active", "0"); + return; + } + + const isActive = + mouseX > left - proximity && + mouseX < left + width + proximity && + mouseY > top - proximity && + mouseY < top + height + proximity; + + element.style.setProperty("--active", isActive ? "1" : "0"); + + if (!isActive) return; + + const currentAngle = + parseFloat(element.style.getPropertyValue("--start")) || 0; + let targetAngle = + (180 * Math.atan2(mouseY - center[1], mouseX - center[0])) / + Math.PI + + 90; + + const angleDiff = ((targetAngle - currentAngle + 180) % 360) - 180; + const newAngle = currentAngle + angleDiff; + + animate(currentAngle, newAngle, { + duration: movementDuration, + ease: [0.16, 1, 0.3, 1], + onUpdate: (value) => { + element.style.setProperty("--start", String(value)); + }, + }); + }); + }, + [inactiveZone, proximity, movementDuration] + ); + + useEffect(() => { + if (disabled) return; + + const handleScroll = () => handleMove(); + const handlePointerMove = (e: PointerEvent) => handleMove(e); + + window.addEventListener("scroll", handleScroll, { passive: true }); + document.body.addEventListener("pointermove", handlePointerMove, { + passive: true, + }); + + return () => { + if (animationFrameRef.current) { + cancelAnimationFrame(animationFrameRef.current); + } + window.removeEventListener("scroll", handleScroll); + document.body.removeEventListener("pointermove", handlePointerMove); + }; + }, [handleMove, disabled]); + + return ( + <> +