Thanks to visit codestin.com
Credit goes to github.com

Skip to content

added navbar#12

Merged
azkriven16 merged 2 commits intomainfrom
feature/navbar
Nov 7, 2025
Merged

added navbar#12
azkriven16 merged 2 commits intomainfrom
feature/navbar

Conversation

@azkriven16
Copy link
Owner

@azkriven16 azkriven16 commented Nov 7, 2025

Summary by CodeRabbit

  • New Features

    • Adds animated card-based navigation, a navbar, and a client-side dark/light theme toggle.
    • Replaces previous homepage with a simplified home layout.
  • Style

    • Overhauled global theming with an expanded, customizable color palette and improved theme-aware utilities.
    • Improved transitions and responsive layout behavior.
  • Chores

    • Added UI scaffolding configuration for component tooling.

@korbit-ai
Copy link

korbit-ai bot commented Nov 7, 2025

You've used up your 5 PR reviews for this month under the Korbit Starter Plan. You'll get 5 more reviews on November 11th, 2025 or you can upgrade to Pro for unlimited PR reviews and enhanced features in your Korbit Console.

@vercel
Copy link

vercel bot commented Nov 7, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
euger Error Error Nov 7, 2025 0:50am

@coderabbitai
Copy link

coderabbitai bot commented Nov 7, 2025

Walkthrough

Replaces the previous landing page with a component-driven layout: adds a new home page under app/(pages), global theming and CSS variables, a ThemeProvider and ModeToggle, animated CardNav and Navbar components, utility cn, a components.json scaffold, and updates dependencies and CI env vars.

Changes

Cohort / File(s) Summary
App pages & layout
app/page.tsx, app/(pages)/page.tsx, app/layout.tsx
Removes old app/page.tsx; adds new app/(pages)/page.tsx default Home component; replaces inline Clerk UI in app/layout.tsx with ThemeProvider wrapper, Navbar rendering, and suppressHydrationWarning on html.
Global styles
app/globals.css
Replaces media-query dark block with Tailwind @layer base approach, adds extensive CSS variables for light/dark tokens, applies global utilities, and adds view-transition disable selectors.
Navigation & header UI
components/ui/card-nav.tsx, components/shared/navbar.tsx
Adds CardNav (exported types + default) — animated, GSAP-driven expandable card navigation with default items; adds Navbar component that integrates CardNav.
Theme components
components/shared/theme-provider.tsx, components/shared/mode-toggle.tsx
Adds ThemeProvider wrapper around next-themes provider; adds client-side ModeToggle component with hydration-safety and View Transitions circular reveal animation.
Utilities & scaffolding
lib/utils.ts, components.json
Adds cn(...inputs) util (clsx + twMerge) and a root components.json ShadCN UI scaffold with Tailwind and aliases.
Dependencies & CI
package.json, .github/workflows/deploy.yml
Adds dependencies: class-variance-authority, clsx, gsap, lucide-react, next-themes, react-icons, tailwind-merge; devDependency tw-animate-css; adds NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY env vars to deploy workflow.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant Browser
    participant App as app/layout.tsx
    participant ThemeProv as ThemeProvider
    participant Navbar as Navbar
    participant CardNav as CardNav
    participant Toggle as ModeToggle

    Browser->>App: Request page
    App->>ThemeProv: Wrap children
    ThemeProv-->>App: Theme context provided
    App->>Navbar: Render header
    Navbar->>CardNav: Mount default items
    Navbar->>Toggle: Mount mode toggle

    User->>Toggle: Click
    rect rgb(215,230,255)
    Note over Toggle: View Transition circular reveal
    Toggle->>ThemeProv: setTheme('dark'/'light')
    ThemeProv->>App: Apply CSS variables
    end

    User->>CardNav: Click hamburger
    rect rgb(235,245,220)
    Note over CardNav: GSAP timeline animates height + cards
    CardNav->>CardNav: Play timeline (staggered entrance)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay special attention to:
    • components/ui/card-nav.tsx — GSAP timeline, height calculations, resize handling, event cleanup.
    • components/shared/mode-toggle.tsx — View Transitions geometry math, hydration-safe mount, and accessibility.
    • app/globals.css — CSS variable mappings and Tailwind layer integration for dark/light theming.
    • Dependency additions in package.json and their correct usage/imports across new files.

Possibly related PRs

  • added preloader #3 — Adds ShadCN scaffolding, components.json, and cn utility; strongly overlaps scaffolding and utilities.
  • added clerk #11 — Modifies app/layout.tsx and app-level auth UI similar to this PR; related to layout/auth integration.
  • #6 — Appears to add ThemeProvider/ModeToggle and Navbar integration; likely to overlap or conflict with this change set.

Poem

🐰 I hopped in with a theme and a spring,

Cards that unfold and a gentle moon swing.
GSAP makes them dance, view-transitions gleam,
A tiny rabbit cheers — the UI's a dream! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'added navbar' is overly vague and does not accurately represent the scope of changes, which include extensive theming infrastructure, components, styling, and workflow configuration beyond just the navbar. Consider a more descriptive title that reflects the primary changes, such as 'Implement theme system with navbar and animated navigation' or 'Add theming infrastructure and navbar component'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/navbar

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2de08a2 and c629787.

📒 Files selected for processing (1)
  • .github/workflows/deploy.yml (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Workers Builds: portfolio
  • GitHub Check: deploy
🔇 Additional comments (2)
.github/workflows/deploy.yml (2)

56-63: Environment variables correctly applied to both deployment steps.

Both the Preview (PR) and Production deployments include the Clerk authentication secrets, ensuring that the application will have access to authentication keys in all deployment scenarios.


50-54: Verify that the Clerk secrets are configured in the GitHub repository.

The environment variables are correctly referenced from GitHub secrets using the standard ${{ secrets.VARIABLE_NAME }} syntax, which prevents credential exposure in workflow logs. Automated verification of secret configuration is not possible due to access restrictions.

Ensure that both NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY are set up in your GitHub repository's Secrets settings before merging. The public key can be exposed to the client (hence the NEXT_PUBLIC_ prefix), while the secret key must never be committed to source control. You can verify this in your repository's Settings > Secrets and variables > Actions section.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Nov 7, 2025

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
portfolio c629787 Commit Preview URL

Branch Preview URL
Nov 07 2025, 01:27 AM

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/layout.tsx (1)

27-28: Remove the stray template literal
Line 28 contains ``````;`` which makes the layout fail to compile. Drop the extra literal so the file parses again.

-export const metadata: Metadata = {
-  title: "Clerk Next.js Quickstart",
-  description: "Generated by create next app",
-};
-``;
+export const metadata: Metadata = {
+  title: "Clerk Next.js Quickstart",
+  description: "Generated by create next app",
+};
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5902bb8 and 2de08a2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • app/(pages)/page.tsx (1 hunks)
  • app/globals.css (1 hunks)
  • app/layout.tsx (2 hunks)
  • app/page.tsx (0 hunks)
  • components.json (1 hunks)
  • components/shared/mode-toggle.tsx (1 hunks)
  • components/shared/navbar.tsx (1 hunks)
  • components/shared/theme-provider.tsx (1 hunks)
  • components/ui/card-nav.tsx (1 hunks)
  • lib/utils.ts (1 hunks)
  • package.json (2 hunks)
💤 Files with no reviewable changes (1)
  • app/page.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
components/shared/mode-toggle.tsx (1)
lib/utils.ts (1)
  • cn (4-6)
components/ui/card-nav.tsx (2)
lib/utils.ts (1)
  • cn (4-6)
components/shared/mode-toggle.tsx (1)
  • ModeToggle (15-114)
app/layout.tsx (2)
components/shared/theme-provider.tsx (1)
  • ThemeProvider (6-11)
components/shared/navbar.tsx (1)
  • Navbar (10-16)
🪛 Biome (2.1.2)
app/globals.css

[error] 126-126: Unknown type selector is not allowed.

See MDN web docs for more details.
Consider replacing the unknown type selector with valid one.

(lint/correctness/noUnknownTypeSelector)


[error] 127-127: Unknown type selector is not allowed.

See MDN web docs for more details.
Consider replacing the unknown type selector with valid one.

(lint/correctness/noUnknownTypeSelector)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: deploy
  • GitHub Check: Workers Builds: portfolio
🔇 Additional comments (1)
lib/utils.ts (1)

4-6: Utility helper aligns with Tailwind merging.

Implementation matches the established clsx + twMerge pattern and looks good to ship.

Comment on lines +126 to 130
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Address Biome lint errors on view transition selectors.

Biome 2.1.2 flags both ::view-transition-old(root) and ::view-transition-new(root) as unknown type selectors, which will keep the lint step red. Split the rule and add targeted biome-ignore comments (or configure the rule) so the pipeline passes while retaining the transition override.

Apply this diff to silence the rule without changing behavior:

-/* Disable transition blending between views */
-::view-transition-old(root),
-::view-transition-new(root) {
-  animation: none;
-  mix-blend-mode: normal;
-}
+/* Disable transition blending between views */
+/* biome-ignore lint/correctness/noUnknownTypeSelector: View transition pseudo-element */
+::view-transition-old(root) {
+  animation: none;
+  mix-blend-mode: normal;
+}
+
+/* biome-ignore lint/correctness/noUnknownTypeSelector: View transition pseudo-element */
+::view-transition-new(root) {
+  animation: none;
+  mix-blend-mode: normal;
+}
🧰 Tools
🪛 Biome (2.1.2)

[error] 126-126: Unknown type selector is not allowed.

See MDN web docs for more details.
Consider replacing the unknown type selector with valid one.

(lint/correctness/noUnknownTypeSelector)


[error] 127-127: Unknown type selector is not allowed.

See MDN web docs for more details.
Consider replacing the unknown type selector with valid one.

(lint/correctness/noUnknownTypeSelector)

🤖 Prompt for AI Agents
In app/globals.css around lines 126 to 130, Biome flags the combined selectors
::view-transition-old(root) and ::view-transition-new(root) as unknown type
selectors; split the combined rule into two separate rules (one for each
pseudo-element) and add a targeted biome-ignore comment above each selector
(e.g., /* biome-ignore-next-line no-unknown-type-selector */) so linting is
silenced while keeping animation:none and mix-blend-mode:normal for both; ensure
no behavioral changes by preserving the same declarations in each rule.

Comment on lines +43 to +73
const transition = document.startViewTransition(() => {
flushSync(() => {
stableSetTheme.current(newTheme);
});
});

await transition.ready;

const { top, left, width, height } =
buttonRef.current.getBoundingClientRect();
const x = left + width / 2;
const y = top + height / 2;
const endRadius = Math.hypot(
Math.max(x, window.innerWidth - x),
Math.max(y, window.innerHeight - y)
);

document.documentElement.animate(
{
clipPath: [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
],
},
{
duration,
easing: "cubic-bezier(0.4, 0, 0.2, 1)",
pseudoElement: "::view-transition-new(root)",
}
);
}, [resolvedTheme, duration, mounted]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard document.startViewTransition for unsupported browsers.

document.startViewTransition only ships in Chromium today; on Safari/Firefox this click handler throws, so the theme toggle never completes. Add a feature check and fall back to a simple setTheme when the API isn’t present.

Apply this diff to handle browsers without the View Transition API:

-    const transition = document.startViewTransition(() => {
-      flushSync(() => {
-        stableSetTheme.current(newTheme);
-      });
-    });
-
-    await transition.ready;
+    const startViewTransition = (document as Document & {
+      startViewTransition?: (
+        updateCallback: () => void
+      ) => { ready: Promise<unknown> };
+    }).startViewTransition;
+
+    if (!startViewTransition) {
+      stableSetTheme.current(newTheme);
+      return;
+    }
+
+    const transition = startViewTransition(() => {
+      flushSync(() => {
+        stableSetTheme.current(newTheme);
+      });
+    });
+
+    await transition.ready;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const transition = document.startViewTransition(() => {
flushSync(() => {
stableSetTheme.current(newTheme);
});
});
await transition.ready;
const { top, left, width, height } =
buttonRef.current.getBoundingClientRect();
const x = left + width / 2;
const y = top + height / 2;
const endRadius = Math.hypot(
Math.max(x, window.innerWidth - x),
Math.max(y, window.innerHeight - y)
);
document.documentElement.animate(
{
clipPath: [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
],
},
{
duration,
easing: "cubic-bezier(0.4, 0, 0.2, 1)",
pseudoElement: "::view-transition-new(root)",
}
);
}, [resolvedTheme, duration, mounted]);
const startViewTransition = (document as Document & {
startViewTransition?: (
updateCallback: () => void
) => { ready: Promise<unknown> };
}).startViewTransition;
if (!startViewTransition) {
stableSetTheme.current(newTheme);
return;
}
const transition = startViewTransition(() => {
flushSync(() => {
stableSetTheme.current(newTheme);
});
});
await transition.ready;
const { top, left, width, height } =
buttonRef.current.getBoundingClientRect();
const x = left + width / 2;
const y = top + height / 2;
const endRadius = Math.hypot(
Math.max(x, window.innerWidth - x),
Math.max(y, window.innerHeight - y)
);
document.documentElement.animate(
{
clipPath: [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
],
},
{
duration,
easing: "cubic-bezier(0.4, 0, 0.2, 1)",
pseudoElement: "::view-transition-new(root)",
}
);
}, [resolvedTheme, duration, mounted]);
🤖 Prompt for AI Agents
In components/shared/mode-toggle.tsx around lines 43 to 73, the handler calls
document.startViewTransition which throws on browsers that don't support the
View Transition API; add a feature check and fallback so the toggle still
completes: detect if document.startViewTransition is a function and, if not,
call flushSync(() => stableSetTheme.current(newTheme)) (or setTheme directly)
and return early; if it exists, run the existing startViewTransition block and
await transition.ready as before, and only run the
document.documentElement.animate call when the API was used.

Comment on lines +158 to +160
const setCardRef = (i: number) => (el: HTMLDivElement | null) => {
if (el) cardsRef.current[i] = el;
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Clear stale card refs when items unmount
When a card unmounts, React calls the ref callback with null, but Line 159 exits early so the old DOM node stays in cardsRef.current. GSAP still tries to animate that stale element on the next open, which can throw or at least desync the animation once consumers pass dynamic items. Please clear the entry when el is null.

-  const setCardRef = (i: number) => (el: HTMLDivElement | null) => {
-    if (el) cardsRef.current[i] = el;
-  };
+  const setCardRef = (i: number) => (el: HTMLDivElement | null) => {
+    if (el) {
+      cardsRef.current[i] = el;
+    } else {
+      cardsRef.current.splice(i, 1);
+    }
+  };

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In components/ui/card-nav.tsx around lines 158 to 160, the ref callback only
assigns the element when el is truthy so stale DOM nodes remain in
cardsRef.current when a card unmounts; change the callback so it clears the slot
when el is null (e.g., set cardsRef.current[i] = null or delete
cardsRef.current[i]) instead of returning early, ensuring the stale ref is
removed so GSAP won't try to animate an unmounted element.

Comment on lines +179 to +202
<div
className={cn(
"hamburger-menu group h-full flex flex-col items-center justify-center cursor-pointer gap-1.5 order-2 md:order-0 transition-colors",
isHamburgerOpen ? "open" : ""
)}
onClick={toggleMenu}
onKeyDown={(e) => e.key === "Enter" && toggleMenu()}
role="button"
aria-label={isExpanded ? "Close menu" : "Open menu"}
tabIndex={0}
>
<div
className={cn(
"hamburger-line w-[30px] h-0.5 bg-foreground transition-[transform,opacity,margin] duration-300 ease-linear origin-[50%_50%] group-hover:opacity-75",
isHamburgerOpen && "translate-y-1 rotate-45"
)}
/>
<div
className={cn(
"hamburger-line w-[30px] h-0.5 bg-foreground transition-[transform,opacity,margin] duration-300 ease-linear origin-[50%_50%] group-hover:opacity-75",
isHamburgerOpen && "-translate-y-1 -rotate-45"
)}
/>
</div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use a real <button> and expose state for screen readers
The hamburger trigger on Line 179 is a div with role="button", but it only listens for Enter and omits Space and aria-expanded, so keyboard and assistive tech users in the United States cannot reliably operate it. Swap to a native <button> and surface the open state.

-          <div
+          <button
             className={cn(
               "hamburger-menu group h-full flex flex-col items-center justify-center cursor-pointer gap-1.5 order-2 md:order-0 transition-colors",
               isHamburgerOpen ? "open" : ""
             )}
-            onClick={toggleMenu}
-            onKeyDown={(e) => e.key === "Enter" && toggleMenu()}
-            role="button"
+            type="button"
+            onClick={toggleMenu}
             aria-label={isExpanded ? "Close menu" : "Open menu"}
-            tabIndex={0}
+            aria-expanded={isExpanded}
           >
             <div
               className={cn(
                 "hamburger-line w-[30px] h-0.5 bg-foreground transition-[transform,opacity,margin] duration-300 ease-linear origin-[50%_50%] group-hover:opacity-75",
                 isHamburgerOpen && "translate-y-1 rotate-45"
               )}
             />
             <div
               className={cn(
                 "hamburger-line w-[30px] h-0.5 bg-foreground transition-[transform,opacity,margin] duration-300 ease-linear origin-[50%_50%] group-hover:opacity-75",
                 isHamburgerOpen && "-translate-y-1 -rotate-45"
               )}
             />
-          </div>
+          </button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
className={cn(
"hamburger-menu group h-full flex flex-col items-center justify-center cursor-pointer gap-1.5 order-2 md:order-0 transition-colors",
isHamburgerOpen ? "open" : ""
)}
onClick={toggleMenu}
onKeyDown={(e) => e.key === "Enter" && toggleMenu()}
role="button"
aria-label={isExpanded ? "Close menu" : "Open menu"}
tabIndex={0}
>
<div
className={cn(
"hamburger-line w-[30px] h-0.5 bg-foreground transition-[transform,opacity,margin] duration-300 ease-linear origin-[50%_50%] group-hover:opacity-75",
isHamburgerOpen && "translate-y-1 rotate-45"
)}
/>
<div
className={cn(
"hamburger-line w-[30px] h-0.5 bg-foreground transition-[transform,opacity,margin] duration-300 ease-linear origin-[50%_50%] group-hover:opacity-75",
isHamburgerOpen && "-translate-y-1 -rotate-45"
)}
/>
</div>
<button
className={cn(
"hamburger-menu group h-full flex flex-col items-center justify-center cursor-pointer gap-1.5 order-2 md:order-0 transition-colors",
isHamburgerOpen ? "open" : ""
)}
type="button"
onClick={toggleMenu}
aria-label={isExpanded ? "Close menu" : "Open menu"}
aria-expanded={isExpanded}
>
<div
className={cn(
"hamburger-line w-[30px] h-0.5 bg-foreground transition-[transform,opacity,margin] duration-300 ease-linear origin-[50%_50%] group-hover:opacity-75",
isHamburgerOpen && "translate-y-1 rotate-45"
)}
/>
<div
className={cn(
"hamburger-line w-[30px] h-0.5 bg-foreground transition-[transform,opacity,margin] duration-300 ease-linear origin-[50%_50%] group-hover:opacity-75",
isHamburgerOpen && "-translate-y-1 -rotate-45"
)}
/>
</button>
🤖 Prompt for AI Agents
In components/ui/card-nav.tsx around lines 179 to 202, replace the div acting as
a button with a native <button type="button">: move the className and onClick to
the button, remove role and tabIndex and the manual onKeyDown (native buttons
handle Enter/Space), and add aria-expanded={isHamburgerOpen} (use the actual
open state) and keep aria-label (update it if necessary). Also ensure any
styling or focus styles still apply to the button element and preserve the two
inner divs for the hamburger lines.

@azkriven16 azkriven16 merged commit 17e7ab1 into main Nov 7, 2025
4 checks passed
@azkriven16 azkriven16 deleted the feature/navbar branch November 20, 2025 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant