diff options
| author | codetorso <[email protected]> | 2024-06-02 04:52:52 +0530 |
|---|---|---|
| committer | codetorso <[email protected]> | 2024-06-02 04:52:52 +0530 |
| commit | bfad1af6704338dc10b2d84c0379ecb7665fac04 (patch) | |
| tree | 7fb84dd2d1bf144b84cefdde985f5c75bc56cdab | |
| parent | added signin page (diff) | |
| download | supermemory-bfad1af6704338dc10b2d84c0379ecb7665fac04.tar.xz supermemory-bfad1af6704338dc10b2d84c0379ecb7665fac04.zip | |
Scroll Nav hide and Twitter Animated Border Implemented
| -rw-r--r-- | apps/web/app/(landing)/Hero.tsx | 14 | ||||
| -rw-r--r-- | apps/web/app/(landing)/Navbar.tsx | 54 | ||||
| -rw-r--r-- | apps/web/app/(landing)/linkArrow.tsx | 3 | ||||
| -rw-r--r-- | apps/web/app/(landing)/page.tsx | 2 | ||||
| -rw-r--r-- | apps/web/app/(landing)/twitterLink.tsx | 124 | ||||
| -rw-r--r-- | apps/web/app/globals.css | 24 | ||||
| -rw-r--r-- | package.json | 3 |
7 files changed, 205 insertions, 19 deletions
diff --git a/apps/web/app/(landing)/Hero.tsx b/apps/web/app/(landing)/Hero.tsx index d571cc26..3fe3a3b7 100644 --- a/apps/web/app/(landing)/Hero.tsx +++ b/apps/web/app/(landing)/Hero.tsx @@ -4,6 +4,7 @@ import { motion } from "framer-motion"; import { Twitter } from "@repo/ui/src/components/icons"; import EmailInput from "./EmailInput"; import LinkArrow from "./linkArrow"; +import { TwitterBorder } from "./twitterLink"; const slap = { initial: { @@ -22,18 +23,7 @@ function Hero() { return ( <> <section className="mt-24 flex max-w-xl flex-col items-center justify-center gap-10 md:mt-56"> - <a - className="group/anchor flex items-center justify-center gap-4 rounded-full bg-white/10 py-2 pl-10 pr-6 text-sm text-white/80" - href="https://twitter.com/supermemoryai" - target="_blank" - > - <Twitter className="h-4 w-4" /> - <div className="flex items-center"> - {" "} - Follow us on Twitter{" "} - <LinkArrow classname="group-hover/anchor:opacity-100 opacity-0 transition" /> - </div> - </a> + <TwitterBorder /> <motion.h1 {...{ ...slap, diff --git a/apps/web/app/(landing)/Navbar.tsx b/apps/web/app/(landing)/Navbar.tsx index 1ad43436..6da09a4a 100644 --- a/apps/web/app/(landing)/Navbar.tsx +++ b/apps/web/app/(landing)/Navbar.tsx @@ -1,12 +1,21 @@ +"use client"; + import { ArrowRightIcon } from "@radix-ui/react-icons"; import Logo from "../../public/logo.svg"; import Image from "next/image"; import Link from "next/link"; import React from "react"; +import { useState } from "react"; +import { + motion, + AnimatePresence, + useScroll, + useMotionValueEvent, +} from "framer-motion"; + -function Navbar() { +function NavbarContent() { return ( - <nav className="fixed top-0 z-[99999] mt-12 hidden w-full px-24 text-sm md:flex"> <div className="flex w-full flex-row justify-between rounded-2xl bg-white/10 shadow-[0px_2px_3px_-1px_rgba(0,0,0,0.1),0px_1px_0px_0px_rgba(25,28,33,0.02),0px_0px_0px_1px_rgba(25,28,33,0.08)] backdrop-blur-lg backdrop-filter"> <Link href={"/"} className="flex items-center p-3 opacity-50"> <Image src={Logo} alt="Supermemory logo" width={40} height={40} /> @@ -30,8 +39,45 @@ function Navbar() { <ArrowRightIcon className="h-4 w-4 group-hover:translate-x-1 duration-100 ease-in-out" /> </Link> </div> - </nav> ); } -export default Navbar; +export const Navbar = () => { + const { scrollYProgress } = useScroll(); + + const [visible, setVisible] = useState(true); + + useMotionValueEvent(scrollYProgress, "change", (current) => { + // Check if current is not undefined and is a number + if (typeof current === "number") { + let direction = current! - scrollYProgress.getPrevious()!; + if (direction < 0) { + setVisible(true); + } else { + setVisible(false); + } + } + }); + + return ( + <AnimatePresence mode="wait"> + <motion.nav + initial={{ + y: -130, + opacity: 1, + }} + animate={{ + y: visible ? 0 : -100, + opacity: visible ? 1 : 0, + }} + transition={{ + duration: 0.2, + }} + className="fixed top-0 z-[99999] mt-12 hidden w-full px-24 text-sm md:flex" + > + <NavbarContent /> + </motion.nav> + </AnimatePresence> + ); +}; + diff --git a/apps/web/app/(landing)/linkArrow.tsx b/apps/web/app/(landing)/linkArrow.tsx index def37e91..01343231 100644 --- a/apps/web/app/(landing)/linkArrow.tsx +++ b/apps/web/app/(landing)/linkArrow.tsx @@ -1,9 +1,10 @@ import React from "react"; -function LinkArrow({ classname }: { classname?: string }) { +function LinkArrow({ classname, stroke }: { classname?: string, stroke? : string}) { return ( <svg className={classname} + stroke={stroke} width="24px" height="24px" viewBox="-2.4 -2.4 28.80 28.80" diff --git a/apps/web/app/(landing)/page.tsx b/apps/web/app/(landing)/page.tsx index e3201912..ccf51743 100644 --- a/apps/web/app/(landing)/page.tsx +++ b/apps/web/app/(landing)/page.tsx @@ -1,6 +1,6 @@ import RotatingIcons from "./RotatingIcons"; import Hero from "./Hero"; -import Navbar from "./Navbar"; +import {Navbar} from "./Navbar"; import Cta from "./Cta"; import { Toaster } from "@repo/ui/src/shadcn/toaster"; import Features from "./Features"; diff --git a/apps/web/app/(landing)/twitterLink.tsx b/apps/web/app/(landing)/twitterLink.tsx new file mode 100644 index 00000000..86a079f2 --- /dev/null +++ b/apps/web/app/(landing)/twitterLink.tsx @@ -0,0 +1,124 @@ +"use client"; +import React, { useState, useEffect, useRef } from "react"; + +import { motion } from "framer-motion"; +import { cn } from "@repo/ui/lib/utils"; +import { Twitter } from "@repo/ui/src/components/icons"; +import LinkArrow from "./linkArrow"; + +export function TwitterBorder() { + return ( + <a + href="https://twitter.com/supermemoryai" + target="_blank" + > + <HoverBorderGradient + containerClassName="rounded-full" + className="group/anchor pl-10 pr-6 flex items-center justify-center gap-4 rounded-full text-white/80 bg-white/5 py-2 text-sm" + > + <Twitter className="h-4 w-4" /> + <div className="flex"> + {" "} + Follow us on Twitter{" "} + <LinkArrow + classname="group-hover/anchor:opacity-100 opacity-0 transition" + stroke="#ffffff" + /> + </div> + </HoverBorderGradient> + </a> + ); +} + +type Direction = "TOP" | "LEFT" | "BOTTOM" | "RIGHT"; + +export function HoverBorderGradient({ + children, + containerClassName, + className, + as: Tag = "button", + duration = 1, + clockwise = true, + ...props +}: React.PropsWithChildren< + { + as?: React.ElementType; + containerClassName?: string; + className?: string; + duration?: number; + clockwise?: boolean; + } & React.HTMLAttributes<HTMLElement> +>) { + const [hovered, setHovered] = useState<boolean>(false); + const [direction, setDirection] = useState<Direction>("TOP"); + + const rotateDirection = (currentDirection: Direction): Direction => { + const directions: Direction[] = ["TOP", "LEFT", "BOTTOM", "RIGHT"]; + const currentIndex = directions.indexOf(currentDirection); + const nextIndex = clockwise + ? (currentIndex - 1 + directions.length) % directions.length + : (currentIndex + 1) % directions.length; + return directions[nextIndex]; + }; + + const movingMap: Record<Direction, string> = { + TOP: "radial-gradient(20.7% 50% at 50% 0%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)", + LEFT: "radial-gradient(16.6% 43.1% at 0% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)", + BOTTOM: + "radial-gradient(20.7% 50% at 50% 100%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)", + RIGHT: + "radial-gradient(16.2% 41.199999999999996% at 100% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)", + }; + + const highlight = + "radial-gradient(75% 181.15942028985506% at 50% 50%, #3275F8 0%, rgba(255, 255, 255, 0) 100%)"; + useEffect(() => { + if (!hovered) { + const interval = setInterval(() => { + setDirection((prevState) => rotateDirection(prevState)); + }, duration * 1000); + return () => clearInterval(interval); + } + }, [hovered]); + return ( + <Tag + onMouseEnter={(event: React.MouseEvent<HTMLDivElement>) => { + setHovered(true); + }} + onMouseLeave={() => setHovered(false)} + className={cn( + "relative h-min w-fit transition duration-500 group/anchor flex items-center justify-center gap-4 rounded-full text-white/80 bg-white/5 text-sm", + containerClassName, + )} + {...props} + > + <div + className={cn( + "z-10 w-auto rounded-[inherit] bg-white/5 px-4 py-2 text-white", + className, + )} + > + {children} + </div> + <motion.div + className={cn( + "absolute inset-0 z-0 flex-none overflow-hidden rounded-[inherit]", + )} + style={{ + filter: "blur(2px)", + position: "absolute", + width: "100%", + height: "100%", + }} + initial={{ background: movingMap[direction] }} + animate={{ + background: hovered + ? [movingMap[direction], highlight] + : movingMap[direction], + }} + transition={{ ease: "linear", duration: duration ?? 1 }} + /> + <div className="z-1 absolute inset-[2px] flex-none rounded-[100px] bg-[#121E2C]" /> + </Tag> + ); +} diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css index b1902464..429e17ba 100644 --- a/apps/web/app/globals.css +++ b/apps/web/app/globals.css @@ -2,6 +2,30 @@ @tailwind components; @tailwind utilities; +html { + scroll-behavior: smooth; +} + +/* width */ +::-webkit-scrollbar { + width: 8px; +} + +/* Track */ +::-webkit-scrollbar-track { + background: transparent; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: #131F2C; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #22303d; +} + /* :root { --foreground-rgb: 0, 0, 0; --background-start-rgb: 214, 219, 220; diff --git a/package.json b/package.json index d169b935..fd955db4 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "@cloudflare/next-on-pages": "1", "@cloudflare/workers-types": "^4.20240512.0", "@repo/eslint-config": "*", - "@repo/shared-types": "*", +"@repo/shared-types": "*", "@repo/tailwind-config": "*", "@repo/typescript-config": "*", "@repo/ui": "*", @@ -51,6 +51,7 @@ "@hookform/resolvers": "^3.4.2", "@iarna/toml": "^2.2.5", "@langchain/cloudflare": "^0.0.6", + "@million/lint": "^1.0.0-rc.18", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-progress": "^1.0.3", |