Skip to content

feat(navigation): upgrade mobile navigation menu into accessible Radix UI slide drawer - #820

Closed
utkarshsingh3011 wants to merge 4 commits into
PRODHOSH:mainfrom
utkarshsingh3011:feature/mobile-nav-drawer
Closed

feat(navigation): upgrade mobile navigation menu into accessible Radix UI slide drawer#820
utkarshsingh3011 wants to merge 4 commits into
PRODHOSH:mainfrom
utkarshsingh3011:feature/mobile-nav-drawer

Conversation

@utkarshsingh3011

@utkarshsingh3011 utkarshsingh3011 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Refactors the mobile navigation menu in Navbar.tsx from a basic absolute DOM overlay into an accessible, touch-friendly slide drawer powered by Radix UI Dialog primitives.

Related Issue

Closes #569

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Refactor
  • Chore / dependency update

Changes Made

  • Replaced basic conditional overlay with @radix-ui/react-dialog (Root, Portal, Overlay, Content, Title, Close).
  • Implemented automatic focus trapping, accessibility attributes, and Escape key dismissal.
  • Added a dark backdrop overlay featuring backdrop-filter: blur(4px) matching modern dark-mode aesthetics.
  • Structured drawer content as a touch-friendly slide sheet displaying all navigation links, auth actions, and language switcher.

Summary by CodeRabbit

  • New Features

    • Added an accessible mobile navigation drawer with backdrop, title, close control, navigation links, authentication actions, and language switching.
    • Improved the mobile menu experience across responsive layouts.
  • Style

    • Standardized navigation component formatting without changing desktop navigation behavior.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Welcome to OSSfolio, @utkarshsingh3011! 🎉

Thank you for opening this pull request and contributing to the open-source community! 🚀

To ensure a smooth review process, please make sure you have:

  • Checked that your changes work locally and compile cleanly.
  • Followed the guidelines outlined in CONTRIBUTING.md.
  • Linked your PR to an open issue (e.g. Closes #ISSUE_NUMBER).

We will review your PR as soon as possible. Happy coding! 💻✨

@github-actions github-actions Bot added frontend Related to UI / Next.js UI Visual / design changes labels Aug 5, 2026
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Too many files!

This PR contains 274 files, which is 174 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 77a53a73-9328-457e-a72c-436e857dea7b

📥 Commits

Reviewing files that changed from the base of the PR and between 7f678d8 and 2d370f7.

📒 Files selected for processing (274)
  • .all-contributorsrc
  • .github/ISSUE_TEMPLATE/bug_report.md
  • .github/ISSUE_TEMPLATE/documentation.md
  • .github/ISSUE_TEMPLATE/feature_request.md
  • .github/ISSUE_TEMPLATE/good_first_issue.md
  • .github/labeler.yml
  • .github/labels.yml
  • .github/workflows/bundle-size-comment.yml
  • .github/workflows/bundle-size.yml
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/e2e.yml
  • .github/workflows/prettier.yml
  • .github/workflows/seed-actions-issues.yml
  • .github/workflows/sql-lint.yml
  • .github/workflows/stale.yml
  • .prettierrc
  • ARCHITECTURE.md
  • CODE_OF_CONDUCT.md
  • README.md
  • e2e/critical-paths.spec.ts
  • e2e/error-handling.spec.ts
  • e2e/mock-supabase.mjs
  • e2e/settings-resilience.spec.ts
  • eslint.config.mjs
  • lint-staged.config.mjs
  • next.config.ts
  • open-next.config.ts
  • playwright.config.ts
  • postcss.config.mjs
  • public/sw.js
  • scripts/__tests__/bundle-size.test.ts
  • scripts/__tests__/sql-lint.test.ts
  • scripts/bundle-size.mjs
  • scripts/sql-lint.mjs
  • src/app/[username]/error.tsx
  • src/app/[username]/loading.tsx
  • src/app/[username]/not-found.tsx
  • src/app/[username]/opengraph-image.tsx
  • src/app/[username]/page.tsx
  • src/app/[username]/rss.xml/route.ts
  • src/app/[username]/twitter-image.tsx
  • src/app/api/[username]/contributions/route.ts
  • src/app/api/[username]/digest/feed/route.ts
  • src/app/api/[username]/digest/route.ts
  • src/app/api/[username]/gists/route.ts
  • src/app/api/[username]/refresh/route.ts
  • src/app/api/[username]/story/route.ts
  • src/app/api/[username]/view/route.ts
  • src/app/api/analytics/[username]/route.ts
  • src/app/api/auth/[...nextauth]/route.ts
  • src/app/api/badge/[username]/route.ts
  • src/app/api/developer-insights/route.ts
  • src/app/api/discover/route.ts
  • src/app/api/export/[username]/route.ts
  • src/app/api/good-first-issues/route.ts
  • src/app/api/milestones/[id]/share/route.ts
  • src/app/api/org/[organization]/claim/route.ts
  • src/app/api/org/[organization]/refresh/route.ts
  • src/app/api/profile/endorse/route.ts
  • src/app/api/profile/providers/route.ts
  • src/app/api/profile/sync/route.ts
  • src/app/api/settings/route.ts
  • src/app/api/sponsors/[username]/route.ts
  • src/app/api/trending-projects/route.ts
  • src/app/api/v1/users/[username]/route.ts
  • src/app/api/webhooks/github/retry/route.ts
  • src/app/auth/callback/page.tsx
  • src/app/compare/error.tsx
  • src/app/compare/loading.tsx
  • src/app/digest/[username]/error.tsx
  • src/app/digest/[username]/loading.tsx
  • src/app/digest/[username]/page.tsx
  • src/app/discover/content.tsx
  • src/app/discover/error.tsx
  • src/app/discover/loading.tsx
  • src/app/discover/page.tsx
  • src/app/embed/[username]/page.tsx
  • src/app/embed/docs/page.tsx
  • src/app/error.tsx
  • src/app/explore/error.tsx
  • src/app/explore/loading.tsx
  • src/app/explore/page.tsx
  • src/app/globals.css
  • src/app/layout.tsx
  • src/app/not-found.tsx
  • src/app/offline/page.tsx
  • src/app/org/[organization]/error.tsx
  • src/app/org/[organization]/loading.tsx
  • src/app/org/[organization]/page.tsx
  • src/app/page.tsx
  • src/app/privacy/page.tsx
  • src/app/robots.ts
  • src/app/score-explained/page.tsx
  • src/app/settings/client.tsx
  • src/app/settings/error.tsx
  • src/app/settings/loading.tsx
  • src/app/settings/page.tsx
  • src/app/sitemap.ts
  • src/app/terms/page.tsx
  • src/components/EmptyMergedPRs.tsx
  • src/components/auth/AuthModal.tsx
  • src/components/digest/ContributionDigest.tsx
  • src/components/discover/DiscoverPagination.tsx
  • src/components/discover/GoodFirstIssueFinder.tsx
  • src/components/discover/ProfileCard.tsx
  • src/components/discover/ProjectsToWatch.tsx
  • src/components/discover/SearchAccessibilityAnnouncer.tsx
  • src/components/discover/SearchFilters.tsx
  • src/components/home/CTABanner.tsx
  • src/components/home/Features.tsx
  • src/components/home/Hero.tsx
  • src/components/home/HowItWorks.tsx
  • src/components/home/Testimonials.tsx
  • src/components/layout/Footer.tsx
  • src/components/layout/LanguageSwitcher.tsx
  • src/components/layout/SkipToContent.tsx
  • src/components/layout/TemporaryUnavailableFallback.tsx
  • src/components/layout/__tests__/LanguageSwitcher.test.tsx
  • src/components/profile/AchievementsGrid.tsx
  • src/components/profile/CompareCharts.tsx
  • src/components/profile/CompareChartsSkeleton.tsx
  • src/components/profile/CompareForm.tsx
  • src/components/profile/CompareLoading.tsx
  • src/components/profile/CompareRadarChart.tsx
  • src/components/profile/CompareRadarChartSkeleton.tsx
  • src/components/profile/ContributionHeatmap.tsx
  • src/components/profile/ContributionTimeline.tsx
  • src/components/profile/DeveloperInsightsCard.tsx
  • src/components/profile/EmbedModal.tsx
  • src/components/profile/ExportMenu.tsx
  • src/components/profile/GistList.tsx
  • src/components/profile/HeatmapWithYearNav.tsx
  • src/components/profile/ImpactNetwork.tsx
  • src/components/profile/ImpactNetworkGraph.tsx
  • src/components/profile/ImpactNetworkSkeleton.tsx
  • src/components/profile/LanguageTreemap.tsx
  • src/components/profile/LatestMergedPRs.tsx
  • src/components/profile/MilestoneCard.tsx
  • src/components/profile/MilestoneCelebration.tsx
  • src/components/profile/MilestoneTimeline.tsx
  • src/components/profile/OrgDashboard.tsx
  • src/components/profile/OrganizationSection.tsx
  • src/components/profile/ProfileActions.tsx
  • src/components/profile/ProfileAnalyticsChartSkeleton.tsx
  • src/components/profile/ProfileAnalyticsModal.tsx
  • src/components/profile/ProfileBadgeModal.tsx
  • src/components/profile/ProfileHeaderSkeleton.tsx
  • src/components/profile/ProfileReposSection.tsx
  • src/components/profile/ProfileSkeleton.tsx
  • src/components/profile/ProfileSyncing.tsx
  • src/components/profile/ProfileView.tsx
  • src/components/profile/ProfileViewCounter.tsx
  • src/components/profile/ProviderIntegrations.tsx
  • src/components/profile/QRCodeModal.tsx
  • src/components/profile/ScoreCalculator.tsx
  • src/components/profile/ScoreSimulator.tsx
  • src/components/profile/SkillEndorsements.tsx
  • src/components/profile/SponsorshipSection.tsx
  • src/components/profile/StatsGridSkeleton.tsx
  • src/components/profile/StoryModal.tsx
  • src/components/profile/TopReposSkeleton.tsx
  • src/components/profile/__tests__/CompareRadarChart.test.tsx
  • src/components/profile/__tests__/ContributionTimeline.test.tsx
  • src/components/profile/__tests__/HeatmapCustomization.test.tsx
  • src/components/profile/__tests__/LanguageTreemap.test.tsx
  • src/components/profile/__tests__/ProfileActions.test.tsx
  • src/components/ui/CommandPalette.tsx
  • src/components/ui/EnvValidationBanner.tsx
  • src/components/ui/PwaInitializer.tsx
  • src/components/ui/__tests__/CommandPalette.test.tsx
  • src/components/ui/__tests__/cva-components.test.tsx
  • src/components/ui/badge.tsx
  • src/components/ui/card.tsx
  • src/components/ui/contributor-badge.tsx
  • src/components/ui/error-boundary.tsx
  • src/components/ui/json-ld.tsx
  • src/components/ui/skeleton-card.tsx
  • src/components/ui/status-pill.tsx
  • src/context/CommandPaletteContext.tsx
  • src/context/ThemeContext.tsx
  • src/hooks/useBroadcastChannel.ts
  • src/hooks/useDebounce.ts
  • src/hooks/useKeyboardShortcuts.ts
  • src/hooks/useMounted.ts
  • src/hooks/usePrefersDark.ts
  • src/hooks/useVisibility.ts
  • src/i18n/__tests__/messages-schema.test.ts
  • src/i18n/config.ts
  • src/i18n/locale.ts
  • src/i18n/request.ts
  • src/lib/__tests__/analytics-tracker.test.ts
  • src/lib/__tests__/anomaly.test.ts
  • src/lib/__tests__/badges.test.ts
  • src/lib/__tests__/digest.test.ts
  • src/lib/__tests__/endorsements.test.ts
  • src/lib/__tests__/explore-filters.test.ts
  • src/lib/__tests__/gists.test.ts
  • src/lib/__tests__/good-first-issues.test.ts
  • src/lib/__tests__/http-cache.test.ts
  • src/lib/__tests__/impact-network.test.ts
  • src/lib/__tests__/multi-provider.test.ts
  • src/lib/__tests__/open-source-story.test.ts
  • src/lib/__tests__/opengraph-image.test.ts
  • src/lib/__tests__/org-data.test.ts
  • src/lib/__tests__/org-stats.test.ts
  • src/lib/__tests__/profile-export.test.ts
  • src/lib/__tests__/profile-lock.test.ts
  • src/lib/__tests__/profile-views.test.ts
  • src/lib/__tests__/qr-code.test.ts
  • src/lib/__tests__/radar-metrics.test.ts
  • src/lib/__tests__/rate-limit.test.ts
  • src/lib/__tests__/score.test.ts
  • src/lib/__tests__/sponsors.test.ts
  • src/lib/__tests__/supabase-lazy.test.ts
  • src/lib/__tests__/trending-projects.test.ts
  • src/lib/__tests__/v1-users-caching.test.ts
  • src/lib/__tests__/webhook-dead-letter.test.ts
  • src/lib/achievements.ts
  • src/lib/analytics-tracker.ts
  • src/lib/anomaly.ts
  • src/lib/badges-config.ts
  • src/lib/badges.config.ts
  • src/lib/constants.ts
  • src/lib/db.ts
  • src/lib/developer-insights.ts
  • src/lib/digest.ts
  • src/lib/endorsements.ts
  • src/lib/env.ts
  • src/lib/errors.ts
  • src/lib/explore-filters.ts
  • src/lib/fetch-with-timeout.ts
  • src/lib/gists.ts
  • src/lib/github.ts
  • src/lib/good-first-issues.ts
  • src/lib/http-cache.ts
  • src/lib/impact-network.ts
  • src/lib/language-treemap.ts
  • src/lib/languages.ts
  • src/lib/milestones.ts
  • src/lib/mock.ts
  • src/lib/open-source-story.ts
  • src/lib/org-data.ts
  • src/lib/org-stats.ts
  • src/lib/profile-data.ts
  • src/lib/profile-export.ts
  • src/lib/profile-snapshot.ts
  • src/lib/profile-views.ts
  • src/lib/providers/aggregator.ts
  • src/lib/providers/bitbucket.ts
  • src/lib/providers/gitlab.ts
  • src/lib/pwa.ts
  • src/lib/qr-code.ts
  • src/lib/radar-metrics.ts
  • src/lib/rate-limit.ts
  • src/lib/redis.ts
  • src/lib/refresh-profile.ts
  • src/lib/sanitizer.ts
  • src/lib/score.ts
  • src/lib/sectionEyebrowStyle.ts
  • src/lib/sponsors.ts
  • src/lib/supabase.ts
  • src/lib/trending-projects.ts
  • src/lib/utils.test.ts
  • src/lib/utils.ts
  • src/lib/validators/api.ts
  • src/lib/webhook-dead-letter.ts
  • src/middleware.ts
  • src/types/global.d.ts
  • src/types/index.ts
  • supabase/functions/refresh-profile/index.ts
  • supabase/functions/scheduled-refresh/index.ts
  • vitest.config.ts
  • vitest.setup.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing
📝 Walkthrough

Walkthrough

Navbar.tsx now uses single-quote formatting and a Radix Dialog mobile drawer. The drawer includes accessible controls, navigation links, authentication actions, language switching, and dismissal after actions. Desktop behavior remains unchanged.

Changes

Navbar navigation

Layer / File(s) Summary
Preserve existing navbar controls
src/components/layout/Navbar.tsx
Standardizes literals and preserves avatar, desktop navigation, theme, command palette, profile, and authentication behavior.
Add Radix mobile drawer
src/components/layout/Navbar.tsx
Replaces the mobile overlay with a Radix Dialog drawer that includes navigation, authentication actions, language switching, overlay dismissal, and an accessible title and close control.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Navbar
  participant RadixDialog
  User->>Navbar: Open mobile menu
  Navbar->>RadixDialog: Open drawer
  RadixDialog-->>User: Show navigation and controls
  User->>Navbar: Select an action
  Navbar->>RadixDialog: Close drawer
Loading

Possibly related PRs

  • PRODHOSH/ossfolio#481: Both changes modify src/components/layout/Navbar.tsx navigation UI and behavior.

Suggested labels: ELUSOC, ADVENTURER

Suggested reviewers: prodhosh, aditya8369, sakethsumanbathini, kgfch2, abhilasha2101

Poem

I’m a rabbit at the drawer,
Hopping through the links with care.
Radix guards the focus tight,
Backdrops soften mobile night.
Tap an action, then I flee—
A tidy menu, swift and free!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The mobile navigation work matches #569, but the file-wide quote-style conversion is unrelated to the linked issue. Revert the unrelated quote-style changes or move them into a separate pull request.
Linked Issues check ❓ Inconclusive The PR implements the Radix Dialog drawer, accessible controls, responsive content, and blurred backdrop, but the summary does not confirm edge-swipe support required by #569. Confirm that the drawer supports edge-swipe interaction; add it or document why the requirement is not applicable.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: replacing the mobile navigation overlay with an accessible Radix UI slide drawer.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/layout/Navbar.tsx`:
- Around line 638-639: Update the drawer “Get started” button styling in Navbar
to stop using the hardcoded brand palette values via tokens.primary and
tokens.ink, and switch that inline style to the CSS variable design tokens
instead. Keep the existing button styling logic intact, but replace the color
sources in the Navbar component with the corresponding var(--color-primary) and
var(--color-on-primary) symbols so the design-token migration is fully applied.
- Around line 566-580: Update the drawer portfolio Link in Navbar to reuse the
existing profileHref value instead of interpolating username directly, so the
mobile and desktop navigation paths stay consistent and the link never resolves
to /undefined when user_metadata.user_name is missing. Keep the onClick close
behavior and the existing myPortfolio label unchanged.
- Around line 652-660: Keep LanguageSwitcher out of the scrollable
Dialog.Content area in Navbar so its dropdown is not clipped by overflowY:
'auto'. Update the layout around the LanguageSwitcher block to place it above
the scroll boundary or otherwise render its menu upward within the drawer, and
remove the marginTop: 'auto' placement that keeps it pinned to the bottom of the
scrollable content.
- Around line 581-586: Update the mobile logout button’s onClick handler to
await the async handleLogout call and remove its redundant setMobileOpen(false)
invocation, relying on handleLogout’s existing state update. Add error handling
inside handleLogout so sign-out failures are handled appropriately rather than
becoming unhandled promise rejections.
- Around line 486-504: Update the Dialog.Content element in the Navbar dialog to
explicitly set aria-describedby={undefined} because no Dialog.Description is
provided. Keep the existing dialog styling and structure unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6fe72a19-598f-41bd-8666-966416251d1c

📥 Commits

Reviewing files that changed from the base of the PR and between 87724b8 and 7f678d8.

📒 Files selected for processing (1)
  • src/components/layout/Navbar.tsx

Comment thread src/components/layout/Navbar.tsx
Comment thread src/components/layout/Navbar.tsx
Comment thread src/components/layout/Navbar.tsx
Comment thread src/components/layout/Navbar.tsx
Comment thread src/components/layout/Navbar.tsx
@github-actions github-actions Bot added documentation Additions to docs backend API / Database / Server labels Aug 5, 2026
@PRODHOSH PRODHOSH closed this Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend API / Database / Server documentation Additions to docs frontend Related to UI / Next.js UI Visual / design changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] Upgrade mobile navigation menu into an accessible touch-friendly slide drawer with focus trapping

2 participants