From 00e69d8e2e85123f1c5954b3a6712b5336cbdbfc Mon Sep 17 00:00:00 2001 From: arash-jj Date: Fri, 12 Jun 2026 10:50:16 +0330 Subject: [PATCH 1/7] feat: add navbar constants --- lib/constants.ts | 15 +++++++++++++++ types/types.ts | 4 ++++ 2 files changed, 19 insertions(+) create mode 100644 types/types.ts diff --git a/lib/constants.ts b/lib/constants.ts index a0047ed..056eee0 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -101,3 +101,18 @@ export const PLANS_BY_ID = PLANS.reduce( export const getPlanById = (id: string): Plan | undefined => { return PLANS_BY_ID[id as PlanId]; }; + +export const NAVBAR_ITEMS: NavItemsTypes[] = [ + { + name: "Pricing", + link: "/pricing", + }, + { + name: "About", + link: "/#", + }, + { + name: "Contact", + link: "/#", + }, +]; diff --git a/types/types.ts b/types/types.ts new file mode 100644 index 0000000..b87df70 --- /dev/null +++ b/types/types.ts @@ -0,0 +1,4 @@ +interface NavItemsTypes { + name: string; + link: string; +} From a4a5a8fc0471937b744429d1c9b0e51deaa00cbe Mon Sep 17 00:00:00 2001 From: arash-jj Date: Fri, 12 Jun 2026 10:51:19 +0330 Subject: [PATCH 2/7] feat: move main page.tsx to (root) --- app/(root)/layout.tsx | 14 ++++++++++++++ app/{ => (root)}/page.tsx | 0 app/globals.css | 12 +++++++++++- components/Navbar.tsx | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 app/(root)/layout.tsx rename app/{ => (root)}/page.tsx (100%) create mode 100644 components/Navbar.tsx diff --git a/app/(root)/layout.tsx b/app/(root)/layout.tsx new file mode 100644 index 0000000..519e827 --- /dev/null +++ b/app/(root)/layout.tsx @@ -0,0 +1,14 @@ +import Navbar from "@/components/Navbar"; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + <> + + {children} + + ); +} diff --git a/app/page.tsx b/app/(root)/page.tsx similarity index 100% rename from app/page.tsx rename to app/(root)/page.tsx diff --git a/app/globals.css b/app/globals.css index 21b3e8a..c5e85a9 100644 --- a/app/globals.css +++ b/app/globals.css @@ -194,4 +194,14 @@ *::-webkit-scrollbar-thumb:hover { background-color: var(--color-border-heavy); } -} \ No newline at end of file +} + +@layer utilities { + .nav-hover-btn { + @apply relative ms-10 text-xs uppercase text-blue-50 after:absolute after:-bottom-0.5 after:left-0 after:h-[2px] after:w-full after:origin-bottom-right after:scale-x-0 after:bg-neutral-800 after:transition-transform after:duration-300 after:ease-[cubic-bezier(0.65_0.05_0.36_1)] hover:after:origin-bottom-left hover:after:scale-x-100 dark:after:bg-white cursor-pointer; + } + + .floating-nav { + @apply bg-black rounded-lg border; + } +} diff --git a/components/Navbar.tsx b/components/Navbar.tsx new file mode 100644 index 0000000..35729a0 --- /dev/null +++ b/components/Navbar.tsx @@ -0,0 +1,38 @@ +"use client" + +import { useAuth } from "@/hooks/useAuth"; +import { NAVBAR_ITEMS } from "@/lib/constants"; +import Link from "next/link"; + +const Navbar = () => { + const { user } = useAuth() + return ( +
+
+ +
+
+ ); +} + +export default Navbar \ No newline at end of file From 2bd60de2999c58a7e165d01c4364849812429aa8 Mon Sep 17 00:00:00 2001 From: arash-jj Date: Fri, 12 Jun 2026 11:14:58 +0330 Subject: [PATCH 3/7] feat: add gsap and react-use --- package.json | 3 + pnpm-lock.yaml | 238 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+) diff --git a/package.json b/package.json index a30e28c..e4831cd 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,10 @@ "seed": "bun run scripts/seed.ts" }, "dependencies": { + "@gsap/react": "^2.1.2", "@hookform/resolvers": "^5.4.0", "dotenv": "^17.4.2", + "gsap": "^3.15.0", "jsonwebtoken": "^9.0.3", "lucide-react": "^1.17.0", "mongodb": "^7.2.0", @@ -30,6 +32,7 @@ "react": "19.2.4", "react-dom": "19.2.4", "react-hook-form": "^7.77.0", + "react-use": "^17.6.1", "zod": "^4.4.3" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4eb7432..a3a12f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,12 +8,18 @@ importers: .: dependencies: + '@gsap/react': + specifier: ^2.1.2 + version: 2.1.2(gsap@3.15.0)(react@19.2.4) '@hookform/resolvers': specifier: ^5.4.0 version: 5.4.0(react-hook-form@7.77.0(react@19.2.4)) dotenv: specifier: ^17.4.2 version: 17.4.2 + gsap: + specifier: ^3.15.0 + version: 3.15.0 jsonwebtoken: specifier: ^9.0.3 version: 9.0.3 @@ -44,6 +50,9 @@ importers: react-hook-form: specifier: ^7.77.0 version: 7.77.0(react@19.2.4) + react-use: + specifier: ^17.6.1 + version: 17.6.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) zod: specifier: ^4.4.3 version: 4.4.3 @@ -301,6 +310,12 @@ packages: '@noble/hashes': optional: true + '@gsap/react@2.1.2': + resolution: {integrity: sha512-JqliybO1837UcgH2hVOM4VO+38APk3ECNrsuSM4MuXp+rbf+/2IG2K1YJiqfTcXQHH7XlA0m3ykniFYstfq0Iw==} + peerDependencies: + gsap: ^3.12.5 + react: '>=17' + '@hookform/resolvers@5.4.0': resolution: {integrity: sha512-EIsqr/t/qbinPIhGjMdtvutIN1Kk4uwbROE9/UQ93CAVGR7GkA7Y92+fX80OzXi/OB67jVFYwKGO1WzkxmkFZw==} peerDependencies: @@ -833,6 +848,9 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/js-cookie@3.0.6': + resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -1097,6 +1115,9 @@ packages: '@vitest/utils@4.1.7': resolution: {integrity: sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==} + '@xobotyi/scrollbar-width@1.9.5': + resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1282,10 +1303,20 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + copy-to-clipboard@3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-in-js-utils@3.1.0: + resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + css-tree@3.2.1: resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -1395,6 +1426,9 @@ packages: resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} engines: {node: '>=20.19.0'} + error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + es-abstract@1.24.2: resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} engines: {node: '>= 0.4'} @@ -1584,6 +1618,12 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + fast-shallow-equal@1.0.0: + resolution: {integrity: sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==} + + fastest-stable-stringify@2.0.2: + resolution: {integrity: sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==} + fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -1690,6 +1730,9 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + gsap@3.15.0: + resolution: {integrity: sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==} + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -1733,6 +1776,9 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + hyphenate-style-name@1.1.0: + resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1753,6 +1799,9 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} + inline-style-prefixer@7.0.1: + resolution: {integrity: sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==} + internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} @@ -1893,6 +1942,9 @@ packages: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} + js-cookie@3.0.8: + resolution: {integrity: sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==} + js-tokens@10.0.0: resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} @@ -2103,6 +2155,9 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} @@ -2181,6 +2236,12 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nano-css@5.6.2: + resolution: {integrity: sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==} + peerDependencies: + react: '*' + react-dom: '*' + nanoid@3.3.12: resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2383,6 +2444,18 @@ packages: react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-universal-interface@0.6.2: + resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} + peerDependencies: + react: '*' + tslib: '*' + + react-use@17.6.1: + resolution: {integrity: sha512-uibb3pgzV4LFsYPHyXYGu7dD2+pyk/ZJlPH+AizBR3zolqPWyCleKcWWbUQaKSKfydwgnQ3ymGm1Ab3/saGHCA==} + peerDependencies: + react: '*' + react-dom: '*' + react@19.2.4: resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} engines: {node: '>=0.10.0'} @@ -2410,6 +2483,9 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + resize-observer-polyfill@1.5.1: + resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -2431,6 +2507,9 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rtl-css-js@1.16.1: + resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -2460,6 +2539,10 @@ packages: scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + screenfull@5.2.0: + resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} + engines: {node: '>=0.10.0'} + secure-json-parse@4.1.0: resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} @@ -2480,6 +2563,10 @@ packages: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} + set-harmonic-interval@1.0.1: + resolution: {integrity: sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==} + engines: {node: '>=6.9'} + set-proto@1.0.0: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} @@ -2529,6 +2616,14 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map@0.5.6: + resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + sparse-bitfield@3.0.3: resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} @@ -2539,9 +2634,21 @@ packages: stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} + stack-generator@2.0.10: + resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + + stacktrace-gps@3.1.2: + resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==} + + stacktrace-js@2.0.2: + resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} + std-env@4.1.0: resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} @@ -2601,6 +2708,9 @@ packages: babel-plugin-macros: optional: true + stylis@4.4.0: + resolution: {integrity: sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -2623,6 +2733,10 @@ packages: resolution: {integrity: sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==} engines: {node: '>=20'} + throttle-debounce@3.0.1: + resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} + engines: {node: '>=10'} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -2649,6 +2763,9 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toggle-selection@1.0.6: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -2671,6 +2788,9 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-easing@0.2.0: + resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} + tsconfck@3.1.6: resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} engines: {node: ^18 || >=20} @@ -3133,6 +3253,11 @@ snapshots: '@exodus/bytes@1.15.1': {} + '@gsap/react@2.1.2(gsap@3.15.0)(react@19.2.4)': + dependencies: + gsap: 3.15.0 + react: 19.2.4 + '@hookform/resolvers@5.4.0(react-hook-form@7.77.0(react@19.2.4))': dependencies: '@standard-schema/utils': 0.3.0 @@ -3511,6 +3636,8 @@ snapshots: '@types/estree@1.0.9': {} + '@types/js-cookie@3.0.6': {} + '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} @@ -3772,6 +3899,8 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 + '@xobotyi/scrollbar-width@1.9.5': {} + acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 @@ -3969,12 +4098,25 @@ snapshots: convert-source-map@2.0.0: {} + copy-to-clipboard@3.3.3: + dependencies: + toggle-selection: 1.0.6 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 + css-in-js-utils@3.1.0: + dependencies: + hyphenate-style-name: 1.1.0 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + css-tree@3.2.1: dependencies: mdn-data: 2.27.1 @@ -4076,6 +4218,10 @@ snapshots: entities@8.0.0: {} + error-stack-parser@2.1.4: + dependencies: + stackframe: 1.3.4 + es-abstract@1.24.2: dependencies: array-buffer-byte-length: 1.0.2 @@ -4412,6 +4558,10 @@ snapshots: fast-safe-stringify@2.1.1: {} + fast-shallow-equal@1.0.0: {} + + fastest-stable-stringify@2.0.2: {} + fastq@1.20.1: dependencies: reusify: 1.1.0 @@ -4517,6 +4667,8 @@ snapshots: graceful-fs@4.2.11: {} + gsap@3.15.0: {} + has-bigints@1.1.0: {} has-flag@4.0.0: {} @@ -4555,6 +4707,8 @@ snapshots: html-escaper@2.0.2: {} + hyphenate-style-name@1.1.0: {} + ignore@5.3.2: {} ignore@7.0.5: {} @@ -4568,6 +4722,10 @@ snapshots: indent-string@4.0.0: {} + inline-style-prefixer@7.0.1: + dependencies: + css-in-js-utils: 3.1.0 + internal-slot@1.1.0: dependencies: es-errors: 1.3.0 @@ -4718,6 +4876,8 @@ snapshots: joycon@3.1.1: {} + js-cookie@3.0.8: {} + js-tokens@10.0.0: {} js-tokens@4.0.0: {} @@ -4915,6 +5075,8 @@ snapshots: math-intrinsics@1.1.0: {} + mdn-data@2.0.14: {} + mdn-data@2.27.1: {} memory-pager@1.5.0: {} @@ -4974,6 +5136,19 @@ snapshots: ms@2.1.3: {} + nano-css@5.6.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + css-tree: 1.1.3 + csstype: 3.2.3 + fastest-stable-stringify: 2.0.2 + inline-style-prefixer: 7.0.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + rtl-css-js: 1.16.1 + stacktrace-js: 2.0.2 + stylis: 4.4.0 + nanoid@3.3.12: {} napi-postinstall@0.3.4: {} @@ -5198,6 +5373,30 @@ snapshots: react-is@17.0.2: {} + react-universal-interface@0.6.2(react@19.2.4)(tslib@2.8.1): + dependencies: + react: 19.2.4 + tslib: 2.8.1 + + react-use@17.6.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + '@types/js-cookie': 3.0.6 + '@xobotyi/scrollbar-width': 1.9.5 + copy-to-clipboard: 3.3.3 + fast-deep-equal: 3.1.3 + fast-shallow-equal: 1.0.0 + js-cookie: 3.0.8 + nano-css: 5.6.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-universal-interface: 0.6.2(react@19.2.4)(tslib@2.8.1) + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + set-harmonic-interval: 1.0.1 + throttle-debounce: 3.0.1 + ts-easing: 0.2.0 + tslib: 2.8.1 + react@19.2.4: {} real-require@0.2.0: {} @@ -5231,6 +5430,8 @@ snapshots: require-from-string@2.0.2: {} + resize-observer-polyfill@1.5.1: {} + resolve-from@4.0.0: {} resolve-pkg-maps@1.0.0: {} @@ -5267,6 +5468,10 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.2 '@rolldown/binding-win32-x64-msvc': 1.0.2 + rtl-css-js@1.16.1: + dependencies: + '@babel/runtime': 7.29.7 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -5300,6 +5505,8 @@ snapshots: scheduler@0.27.0: {} + screenfull@5.2.0: {} + secure-json-parse@4.1.0: {} semver@6.3.1: {} @@ -5322,6 +5529,8 @@ snapshots: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 + set-harmonic-interval@1.0.1: {} + set-proto@1.0.0: dependencies: dunder-proto: 1.0.1 @@ -5410,6 +5619,10 @@ snapshots: source-map-js@1.2.1: {} + source-map@0.5.6: {} + + source-map@0.6.1: {} + sparse-bitfield@3.0.3: dependencies: memory-pager: 1.5.0 @@ -5418,8 +5631,25 @@ snapshots: stable-hash@0.0.5: {} + stack-generator@2.0.10: + dependencies: + stackframe: 1.3.4 + stackback@0.0.2: {} + stackframe@1.3.4: {} + + stacktrace-gps@3.1.2: + dependencies: + source-map: 0.5.6 + stackframe: 1.3.4 + + stacktrace-js@2.0.2: + dependencies: + error-stack-parser: 2.1.4 + stack-generator: 2.0.10 + stacktrace-gps: 3.1.2 + std-env@4.1.0: {} stop-iteration-iterator@1.1.0: @@ -5494,6 +5724,8 @@ snapshots: optionalDependencies: '@babel/core': 7.29.7 + stylis@4.4.0: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -5510,6 +5742,8 @@ snapshots: dependencies: real-require: 1.0.0 + throttle-debounce@3.0.1: {} + tinybench@2.9.0: {} tinyexec@1.2.4: {} @@ -5531,6 +5765,8 @@ snapshots: dependencies: is-number: 7.0.0 + toggle-selection@1.0.6: {} + totalist@3.0.1: {} tough-cookie@6.0.1: @@ -5549,6 +5785,8 @@ snapshots: dependencies: typescript: 5.9.3 + ts-easing@0.2.0: {} + tsconfck@3.1.6(typescript@5.9.3): optionalDependencies: typescript: 5.9.3 From 143f532dc963bd96e52da5b0a0358618e927a561 Mon Sep 17 00:00:00 2001 From: arash-jj Date: Sat, 13 Jun 2026 10:40:25 +0330 Subject: [PATCH 4/7] style: update styles and dark mode support --- app/globals.css | 29 +++++++++++++++++++++++++++-- app/layout.tsx | 4 +++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/app/globals.css b/app/globals.css index c5e85a9..93ba888 100644 --- a/app/globals.css +++ b/app/globals.css @@ -198,10 +198,35 @@ @layer utilities { .nav-hover-btn { - @apply relative ms-10 text-xs uppercase text-blue-50 after:absolute after:-bottom-0.5 after:left-0 after:h-[2px] after:w-full after:origin-bottom-right after:scale-x-0 after:bg-neutral-800 after:transition-transform after:duration-300 after:ease-[cubic-bezier(0.65_0.05_0.36_1)] hover:after:origin-bottom-left hover:after:scale-x-100 dark:after:bg-white cursor-pointer; + @apply relative cursor-pointer; + @apply after:absolute after:-bottom-0.5 after:left-0 after:h-0.5 after:w-full; + @apply after:origin-bottom-right after:scale-x-0; + @apply after:transition-transform after:duration-300 after:ease-[cubic-bezier(0.65_0.05_0.36_1)]; + @apply hover:after:origin-bottom-left hover:after:scale-x-100; + @apply after:bg-primary-500; + } + + .dark .nav-hover-btn::after { + @apply after:bg-primary-400; } .floating-nav { - @apply bg-black rounded-lg border; + @apply rounded-xl border border-border-light bg-surface/80 backdrop-blur-md shadow-lg transition-all duration-300; + } + + .dark .floating-nav { + @apply bg-surface/95 border-border-default shadow-xl backdrop-blur-lg; + } + + .nav-hover-btn:focus-visible { + @apply outline-none ring-2 ring-primary-500 ring-offset-2 ring-offset-surface rounded-sm; + } + + /* Reduced motion support */ + @media (prefers-reduced-motion: reduce) { + .nav-hover-btn::after, + .floating-nav { + @apply transition-none; + } } } diff --git a/app/layout.tsx b/app/layout.tsx index 4d828b2..7345400 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -20,7 +20,9 @@ export default function RootLayout({ }>) { return ( - {children} + + {children} + ); } From 438b3f030db741e1de300f1c13486af0bd1fac08 Mon Sep 17 00:00:00 2001 From: arash-jj Date: Sat, 13 Jun 2026 10:40:44 +0330 Subject: [PATCH 5/7] feat: implement navbar --- components/Navbar.tsx | 109 +++++++++++++++++++++++++++++++++++------- 1 file changed, 92 insertions(+), 17 deletions(-) diff --git a/components/Navbar.tsx b/components/Navbar.tsx index 35729a0..5e6c2d4 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -1,38 +1,113 @@ -"use client" +"use client"; import { useAuth } from "@/hooks/useAuth"; import { NAVBAR_ITEMS } from "@/lib/constants"; import Link from "next/link"; +import { useEffect, useRef, useState } from "react"; +import { useWindowScroll } from "react-use"; +import gsap from "gsap"; const Navbar = () => { - const { user } = useAuth() + const { user } = useAuth(); + const [isNavVisible, setIsNavVisible] = useState(true); + const { y: currentScrollY } = useWindowScroll(); + const [lastScrollY, setLastScrollY] = useState(0); + const navContainerRef = useRef(null); + const [prefersReducedMotion, setPrefersReducedMotion] = useState(false); + + // Check for reduced motion preference + useEffect(() => { + const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)"); + setPrefersReducedMotion(mediaQuery.matches); + + const handler = (e: MediaQueryListEvent) => + setPrefersReducedMotion(e.matches); + mediaQuery.addEventListener("change", handler); + return () => mediaQuery.removeEventListener("change", handler); + }, []); + + useEffect(() => { + const SCROLL_THRESHOLD = 10; + const HIDE_DELAY_PX = 50; + + if (currentScrollY === 0) { + setIsNavVisible(true); + navContainerRef.current?.classList.remove("floating-nav"); + } else if (currentScrollY > lastScrollY && currentScrollY > HIDE_DELAY_PX) { + setIsNavVisible(false); + navContainerRef.current?.classList.add("floating-nav"); + } else if ( + currentScrollY < lastScrollY && + Math.abs(currentScrollY - lastScrollY) > SCROLL_THRESHOLD + ) { + setIsNavVisible(true); + navContainerRef.current?.classList.add("floating-nav"); + } + + setLastScrollY(currentScrollY); + }, [currentScrollY, lastScrollY]); + + useEffect(() => { + if (!navContainerRef.current) return; + + gsap.to(navContainerRef.current, { + y: isNavVisible ? 0 : 100, + opacity: isNavVisible ? 1 : 0, + visibility: isNavVisible ? "visible" : "hidden", + duration: prefersReducedMotion ? 0 : 0.2, + pointerEvents: isNavVisible ? "auto" : "none", + }); + }, [isNavVisible, prefersReducedMotion]); + return ( -
+
-
); -} +}; -export default Navbar \ No newline at end of file +export default Navbar; From a6104188d0c5a6ecb8c477bed38137fdf832902c Mon Sep 17 00:00:00 2001 From: arash-jj Date: Sat, 13 Jun 2026 10:41:08 +0330 Subject: [PATCH 6/7] chore: add /pricing to the public routes --- proxy.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/proxy.ts b/proxy.ts index baaf7a0..a2d76ac 100644 --- a/proxy.ts +++ b/proxy.ts @@ -7,6 +7,7 @@ const publicRoutes = [ "/sign-up", "/api/sign-in", "/api/sign-up", + "/pricing", ]; const protectedRoutes = ["/dashboard", "/workspaces", "/api/protected"]; From 49e1c40410dd0a237ac60ba8518366289acedac4 Mon Sep 17 00:00:00 2001 From: arash-jj Date: Sat, 13 Jun 2026 10:56:26 +0330 Subject: [PATCH 7/7] fix: potential issues --- components/Navbar.tsx | 2 +- lib/constants.ts | 2 ++ types/types.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/components/Navbar.tsx b/components/Navbar.tsx index 5e6c2d4..04a197d 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -97,7 +97,7 @@ const Navbar = () => {
) : ( Login diff --git a/lib/constants.ts b/lib/constants.ts index 056eee0..6ee45a3 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -1,3 +1,5 @@ +import { NavItemsTypes } from "@/types/types"; + export const PLANS = [ { id: "free", diff --git a/types/types.ts b/types/types.ts index b87df70..67760f6 100644 --- a/types/types.ts +++ b/types/types.ts @@ -1,4 +1,4 @@ -interface NavItemsTypes { +export interface NavItemsTypes { name: string; link: string; }