Skip to content

🎨 Enhanced Responsive Navbar with Animations, Cropping Fixes & Smooth Transitions.#69

Merged
idanlodzki merged 4 commits intoOpsiMate:mainfrom
Anas2604-web:enhance-navbar
Oct 30, 2025
Merged

🎨 Enhanced Responsive Navbar with Animations, Cropping Fixes & Smooth Transitions.#69
idanlodzki merged 4 commits intoOpsiMate:mainfrom
Anas2604-web:enhance-navbar

Conversation

@Anas2604-web
Copy link
Contributor

@Anas2604-web Anas2604-web commented Oct 30, 2025

Closes #68
This PR refines the existing Navbar by introducing smoother interactions and visual improvements for a more polished user experience.

🔧 Key Enhancements

✨ Smooth scrolling & subtle animations for better navigation flow

🧩 Fixed cropping issue where section headers were partially hidden on scroll

📱 Improved responsiveness across mobile and desktop views

🎨 Enhanced hover effects and consistent color transitions

  • Result :

A visually refined, accessible, and user-friendly Navbar that elevates the overall experience and aligns with the project’s modern design standards.

image

💬 Note: Hope you like the updates! ✨
I’ve focused on enhancing both functionality and UX to make navigation feel smoother and more modern.

Summary by CodeRabbit

  • New Features

    • Navigation items auto-highlight as page sections enter view
    • Prominent "Contact Us" CTA added; external Slack link preserved
    • GitHub star button added to header
    • Mobile menu: improved toggle behavior and active-state styling
  • Style

    • Navbar applies blur/shadow background when scrolled
    • Navigation links have animated underline and active color treatments
    • Global scroll padding adjusted for improved top-of-page spacing

@vercel
Copy link

vercel bot commented Oct 30, 2025

@Anas2604-web is attempting to deploy a commit to the idan lodzki's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions
Copy link

Thanks for your contribution! Join our Slack: https://join.slack.com/t/opsimate/shared_invite/zt-39bq3x6et-NrVCZzH7xuBGIXmOjJM7gA Please make sure to include an image with your PR — it really helps us review and understand the changes better. Only in rare cases will we accept a PR without one. Also, take a moment to review your code to ensure it’s clear, readable, and easy to follow. PRs from contributors who haven’t joined our Slack community or starred the repository won’t be reviewed — we’d love to see you join and be part of the project!

@coderabbitai
Copy link

coderabbitai bot commented Oct 30, 2025

Walkthrough

Adds a client-side Navbar with IntersectionObserver-based active-section tracking, scroll-triggered blur styling, mobile menu toggle and active-link classes, plus corresponding global CSS for nav visuals and scroll padding.

Changes

Cohort / File(s) Change Summary
Navigation component
components/Navbar.tsx
New client-side navbar: adds use client, activeSection and scrolled state, IntersectionObserver to track visible sections, scroll listener for blur, desktop/mobile rendering with active-link classes, Contact/GitHub/Slack links, and mobile menu toggle/behavior.
Global styles
styles/globals.css
Adds scroll-padding-top: 80px; introduces .nav-link, .nav-link::after underline indicator, .nav-link-active (light/dark variants), and .navbar-blur backdrop blur/translucent background rules.

Assessment against linked issues

Objective (issue) Addressed Explanation
Add navigation menu to jump between homepage sections; sticky/floating placement; highlight active section (#68)

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

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: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad2e60e and 3f2a036.

📒 Files selected for processing (2)
  • components/Navbar.tsx (8 hunks)
  • styles/globals.css (2 hunks)

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: 1

🧹 Nitpick comments (2)
components/Navbar.tsx (2)

95-99: Consider more robust href parsing for active state.

The current logic item.href.replace("/#", "") works for the current navigation items but is fragile. It assumes all internal links follow the /#section pattern and will silently fail for other formats like /section or #section.

Apply this diff for more robust matching:

-                className={`nav-link text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 font-medium ${
-                  activeSection === item.href.replace("/#", "")
-                    ? "nav-link-active"
-                    : ""
-                }`}
+                className={`nav-link text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 font-medium ${
+                  activeSection === item.href.split("#").pop()
+                    ? "nav-link-active"
+                    : ""
+                }`}

This handles /#features, /page#features, #features, and https://example.com/#features consistently by extracting everything after the last #. External links without hashes will safely not match any section.


154-158: Apply the same robust href parsing here.

The mobile navigation uses the same fragile item.href.replace("/#", "") logic as the desktop version.

Apply this diff to match the improved desktop logic:

-                  className={`text-gray-700 hover:text-blue-600 font-medium transition-colors duration-200 px-2 py-1 ${
-                    activeSection === item.href.replace("/#", "")
-                      ? "text-primary-600 dark:text-primary-400"
-                      : ""
-                  }`}
+                  className={`text-gray-700 hover:text-blue-600 font-medium transition-colors duration-200 px-2 py-1 ${
+                    activeSection === item.href.split("#").pop()
+                      ? "text-primary-600 dark:text-primary-400"
+                      : ""
+                  }`}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f2a036 and 5bb91d2.

📒 Files selected for processing (1)
  • components/Navbar.tsx (8 hunks)
🔇 Additional comments (7)
components/Navbar.tsx (7)

1-3: LGTM! Proper client component setup.

The "use client" directive and useEffect import are correctly configured for Next.js 14's app router with client-side interactivity.


22-23: LGTM! State variables properly initialized.

Both activeSection and scrolled states are appropriately typed and initialized for their intended use cases.


48-64: LGTM! Proper IntersectionObserver implementation.

The active section tracking is correctly implemented with appropriate rootMargin to highlight sections when they're centered in the viewport, and cleanup is properly handled.


66-72: LGTM! Scroll state properly initialized.

The scroll blur effect is correctly implemented, and the immediate invocation of handleScroll() on line 69 ensures the navbar has the correct style on mount, even for deep-linked pages. This addresses the previous review concern.


75-81: LGTM! Conditional styling properly applied.

The scroll-based navbar styling toggles correctly between states, providing the intended visual feedback.


124-131: LGTM! Contact CTA properly implemented.

The Contact Us button is correctly implemented as a prominent call-to-action with appropriate mailto link handling.


169-176: LGTM! Mobile contact link properly implemented.

The mobile Contact Us link is correctly styled and includes the menu close handler for good UX.

Comment on lines 10 to 12
// constants/contact.ts
export const CONTACT_EMAIL = 'idan.lut@gmail.com';
export const CONTACT_EMAIL = "idan.lut@gmail.com";
export const CONTACT_MAILTO = `mailto:${CONTACT_EMAIL}`;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Import the constant instead of duplicating it.

The comment indicates this constant lives in constants/contact.ts, but it's defined inline here. This creates duplication and maintenance burden.

Apply this diff to import the constant:

+import { CONTACT_EMAIL, CONTACT_MAILTO } from "@/constants/contact";
+
-// constants/contact.ts
-export const CONTACT_EMAIL = "idan.lut@gmail.com";
-export const CONTACT_MAILTO = `mailto:${CONTACT_EMAIL}`;

Then update the contactLink definition:

 const contactLink: NavigationItem = {
   name: "Contact Us",
   href: CONTACT_MAILTO,
   external: true,
 };

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

🤖 Prompt for AI Agents
In components/Navbar.tsx around lines 10 to 12, the mailto constant is
duplicated locally; remove the inline CONTACT_EMAIL/CONTACT_MAILTO definitions
and instead import CONTACT_MAILTO from constants/contact.ts, then update the
contactLink definition to use the imported CONTACT_MAILTO; ensure the import is
added at the top of the file and unused local constants are deleted.

@Anas2604-web
Copy link
Contributor Author

Anas2604-web commented Oct 30, 2025

Hi @idanlodzki 👋
I’ve fixed and followed all the feedback - the constants were already present in the original repo when I forked it. Everything’s now updated and good to go as per the issue #68
Kindly review and merge when possible. Thanks a lot! 🙏

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: 2

Caution

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

⚠️ Outside diff range comments (2)
components/Navbar.tsx (2)

139-143: Use theme-aware color classes for consistency.

The mobile menu button uses hardcoded colors (text-gray-700 hover:text-blue-600) instead of the theme-aware classes used throughout the rest of the component.

Apply this diff to maintain theme consistency:

             <button
               onClick={() => setIsMenuOpen(!isMenuOpen)}
-              className="text-gray-700 hover:text-blue-600 transition-colors duration-200"
+              className="text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 transition-colors duration-200"
             >

148-148: Use theme-aware border color for consistency.

The mobile navigation container uses a hardcoded border color (border-gray-100) that doesn't adapt to dark mode, unlike the main navbar which uses border-surface-200 dark:border-surface-800.

Apply this diff:

-          <div className="md:hidden py-4 border-t border-gray-100">
+          <div className="md:hidden py-4 border-t border-surface-200 dark:border-surface-800">
♻️ Duplicate comments (1)
components/Navbar.tsx (1)

10-12: Remove duplicate constants and import from the correct location.

These constants are duplicated from constants/contact.ts. Additionally, the quote style here (single quotes on line 11) is inconsistent with the double quotes used in constants/contact.ts per the AI summary.

Apply this diff to import the constants instead:

+import { CONTACT_EMAIL, CONTACT_MAILTO } from "@/constants/contact";
+
-// constants/contact.ts
-export const CONTACT_EMAIL = 'idan.lut@gmail.com';
-export const CONTACT_MAILTO = `mailto:${CONTACT_EMAIL}`;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5bb91d2 and 4ab3b4a.

📒 Files selected for processing (1)
  • components/Navbar.tsx (8 hunks)
🔇 Additional comments (8)
components/Navbar.tsx (8)

1-1: LGTM!

The "use client" directive is correctly placed and necessary for the client-side interactivity (hooks and DOM APIs) introduced in this component.


3-3: LGTM!

The expanded React imports are necessary for the state management and side effects introduced in this component.


22-23: LGTM!

The state variables are properly typed and initialized, supporting the active section tracking and scroll-based blur effect.


48-64: LGTM!

The IntersectionObserver correctly tracks visible sections and updates the active state. The cleanup properly unobserves all sections on unmount.


66-72: LGTM!

The scroll handler correctly initializes state on mount (addressing the previous review feedback) and properly manages the event listener lifecycle.


75-81: LGTM!

The dynamic navbar styling correctly applies theme-aware classes and transitions based on scroll state.


124-131: LGTM!

The Contact Us button is properly implemented with appropriate primary button styling and correct mailto link.


169-176: LGTM!

The mobile Contact Us link is properly implemented with theme-aware styling and correct menu-closing behavior.

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: 1

♻️ Duplicate comments (2)
components/Navbar.tsx (2)

10-12: Import the constant instead of duplicating it.

The inline constant definitions create duplication, as indicated by the comment. Import CONTACT_EMAIL and CONTACT_MAILTO from constants/contact.ts instead.


154-154: Use theme-aware color classes for consistency.

Line 154 still uses hardcoded colors (text-gray-700 hover:text-blue-600) instead of theme-aware classes, which is inconsistent with the desktop navigation and doesn't properly support dark mode.

Apply this diff:

-                  className={`text-gray-700 hover:text-blue-600 font-medium transition-colors duration-200 px-2 py-1 ${
+                  className={`text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 font-medium transition-colors duration-200 px-2 py-1 ${
                    !item.external && activeSection === item.href.split("#").pop()
                      ? "text-primary-600 dark:text-primary-400"
                      : ""
                  }`}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ab3b4a and 94502c2.

📒 Files selected for processing (1)
  • components/Navbar.tsx (8 hunks)
🔇 Additional comments (1)
components/Navbar.tsx (1)

48-72: Well-implemented active section tracking and scroll effects.

The IntersectionObserver with centered rootMargin provides smooth active section detection, and initializing the scroll handler on mount (line 69) correctly addresses the previous deep-link issue. Both effects include proper cleanup.

Comment on lines 137 to 142
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="text-gray-700 hover:text-blue-600 transition-colors duration-200"
className="text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 transition-colors duration-200"
>
{isMenuOpen ? <X size={24} /> : <Menu size={24} />}
</button>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add accessibility attributes to the mobile menu button.

The mobile menu toggle button lacks aria-label and aria-expanded attributes, which are essential for screen reader users to understand its purpose and state.

Apply this diff to add the missing attributes:

 <button
   onClick={() => setIsMenuOpen(!isMenuOpen)}
   className="text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 transition-colors duration-200"
+  aria-label="Toggle navigation menu"
+  aria-expanded={isMenuOpen}
 >
   {isMenuOpen ? <X size={24} /> : <Menu size={24} />}
 </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
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="text-gray-700 hover:text-blue-600 transition-colors duration-200"
className="text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 transition-colors duration-200"
>
{isMenuOpen ? <X size={24} /> : <Menu size={24} />}
</button>
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 transition-colors duration-200"
aria-label="Toggle navigation menu"
aria-expanded={isMenuOpen}
>
{isMenuOpen ? <X size={24} /> : <Menu size={24} />}
</button>
🤖 Prompt for AI Agents
In components/Navbar.tsx around lines 137 to 142, the mobile menu toggle button
is missing accessibility attributes; update the button to include an appropriate
aria-label (e.g., "Open menu" / "Close menu" or a neutral "Toggle menu") and add
aria-expanded set to the boolean isMenuOpen so screen readers know its state;
optionally include aria-controls pointing to the mobile menu element's id if
present to associate the button with the menu.

@idanlodzki idanlodzki merged commit 951a1ef into OpsiMate:main Oct 30, 2025
1 of 2 checks passed
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.

[UI] Add Navigation Menu to Jump Between Sections on

2 participants