aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcodetorso <[email protected]>2024-06-02 04:52:52 +0530
committercodetorso <[email protected]>2024-06-02 04:52:52 +0530
commitbfad1af6704338dc10b2d84c0379ecb7665fac04 (patch)
tree7fb84dd2d1bf144b84cefdde985f5c75bc56cdab
parentadded signin page (diff)
downloadsupermemory-bfad1af6704338dc10b2d84c0379ecb7665fac04.tar.xz
supermemory-bfad1af6704338dc10b2d84c0379ecb7665fac04.zip
Scroll Nav hide and Twitter Animated Border Implemented
-rw-r--r--apps/web/app/(landing)/Hero.tsx14
-rw-r--r--apps/web/app/(landing)/Navbar.tsx54
-rw-r--r--apps/web/app/(landing)/linkArrow.tsx3
-rw-r--r--apps/web/app/(landing)/page.tsx2
-rw-r--r--apps/web/app/(landing)/twitterLink.tsx124
-rw-r--r--apps/web/app/globals.css24
-rw-r--r--package.json3
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",