Skip to content

Conversation

@ComputelessComputer
Copy link
Collaborator

@ComputelessComputer ComputelessComputer commented Dec 5, 2025

Summary

Adds click-outside-to-dismiss behavior for the mobile docs and company handbook navigation drawers. When the drawer is open, a transparent backdrop overlay appears behind it. Clicking on this backdrop dismisses the drawer.

The implementation adds an invisible overlay at z-40 (below the drawer at z-50) that covers the viewport below the header. Both MobileDocsDrawer and MobileHandbookDrawer components receive the same treatment.

Updates since last revision

  • Made the backdrop fully transparent (removed bg-black/20) per user request - the overlay is now invisible but still captures clicks to dismiss the drawer

Review & Testing Checklist for Human

  • Test on mobile viewport (or Chrome DevTools mobile emulation) that clicking outside the drawer dismisses it for both /docs/* and /company-handbook/* pages
  • Verify the backdrop doesn't cover or interfere with the header navigation
  • Confirm drawer navigation links still work correctly after this change

Recommended test plan: Open the site on a mobile viewport, navigate to /docs or /company-handbook, open the sidebar drawer via the hamburger menu, then tap anywhere outside the drawer panel to verify it closes.

Notes

@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@netlify
Copy link

netlify bot commented Dec 5, 2025

Deploy Preview for hyprnote-storybook ready!

Name Link
🔨 Latest commit 0264cde
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/6932968e74047d000885e778
😎 Deploy Preview https://deploy-preview-2133--hyprnote-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Dec 5, 2025

Deploy Preview for hyprnote ready!

Name Link
🔨 Latest commit 0264cde
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/6932968e475bda00088bdea2
😎 Deploy Preview https://deploy-preview-2133--hyprnote.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

📝 Walkthrough

Walkthrough

Replaced the outer drawer container with a fragment and added a conditionally rendered backdrop behind MobileDocsDrawer and MobileHandbookDrawer that calls onClose when clicked; moved drawer inner content into a dedicated scroll wrapper while preserving SidebarNavigation rendering and animations.

Changes

Cohort / File(s) Summary
Mobile drawer backdrop & inner scroll wrapper
apps/web/src/routes/_view/route.tsx
Replaced single outer drawer container with a fragment and conditional full-screen backdrop that closes the drawer on click. Moved drawer inner content into a new wrapper (receives ref, padding, preserves scroll behavior). Updated MobileDocsDrawer and MobileHandbookDrawer to use the backdrop + inner scroll wrapper pattern while keeping SidebarNavigation props and slide animations unchanged.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Verify backdrop click triggers the provided onClose callback.
  • Confirm existing translate-x slide animations and transitions remain functional.
  • Validate scroll behavior and padding on the inner scroll wrapper (ref, overflow, padding-left env variable).
  • Ensure SidebarNavigation links still call onLinkClick/onClose as before.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
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.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding click-outside-to-dismiss behavior for mobile drawers.
Description check ✅ Passed The description is well-related to the changeset, providing clear context about the feature, implementation details, testing guidance, and the specific change about making the backdrop transparent.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1764919728-mobile-drawer-dismiss

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.

Copy link
Contributor

@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: 0

🧹 Nitpick comments (2)
apps/web/src/routes/_view/route.tsx (2)

92-120: Backdrop and scroll container wiring look solid; consider minor cleanup.

The backdrop and drawer container structure achieve the desired behavior: click-outside closes the drawer, the z-index layering is correct (backdrop under drawer), and the scroll container + scrollContainerRef integration with SidebarNavigation preserves the existing auto-scroll behavior.

Two small, optional refinements you might consider:

  1. Use cn for the long conditional className
    To align with the codebase guideline and improve readability of the conditional translate-x classes:
+import { cn } from "@hypr/utils";
...
-      <div
-        className={`fixed top-[69px] left-0 h-[calc(100vh-69px)] w-72 bg-white/80 backdrop-blur-sm border-r border-neutral-100 shadow-2xl shadow-neutral-900/20 z-50 md:hidden transition-transform duration-300 ease-in-out ${
-          isOpen ? "translate-x-0" : "-translate-x-full"
-        }`}
+      <div
+        className={cn(
+          "fixed top-[69px] left-0 h-[calc(100vh-69px)] w-72 bg-white/80 backdrop-blur-sm border-r border-neutral-100 shadow-2xl shadow-neutral-900/20 z-50 md:hidden transition-transform duration-300 ease-in-out",
+          isOpen ? "translate-x-0" : "-translate-x-full",
+        )}
  1. Optional a11y nit for the backdrop
    If you want to be explicit for assistive tech, you could mark the backdrop as presentational:
-      {isOpen && (
-        <div
-          className="fixed inset-0 top-[69px] bg-black/20 z-40 md:hidden"
-          onClick={onClose}
-        />
-      )}
+      {isOpen && (
+        <div
+          className="fixed inset-0 top-[69px] bg-black/20 z-40 md:hidden"
+          onClick={onClose}
+          aria-hidden="true"
+        />
+      )}

These are non-blocking; behavior is already correct.


179-207: Handbook drawer implementation mirrors docs drawer; consider deduping the shared shell.

The handbook drawer’s backdrop + container + scroll wrapper mirror the docs drawer and correctly hook up SidebarNavigation with its own scrollContainerRef. Functionally this looks good and matches the intended behavior.

Given how similar the two drawer shells now are, you might reduce duplication by extracting a small shared mobile drawer shell component that takes isOpen, onClose, and children (or a navigation prop), e.g.:

function MobileDrawerShell({
  isOpen,
  onClose,
  children,
}: {
  isOpen: boolean;
  onClose: () => void;
  children: React.ReactNode;
}) {
  return (
    <>
      {isOpen && (
        <div
          className="fixed inset-0 top-[69px] bg-black/20 z-40 md:hidden"
          onClick={onClose}
          aria-hidden="true"
        />
      )}
      <div
        className={cn(
          "fixed top-[69px] left-0 h-[calc(100vh-69px)] w-72 bg-white/80 backdrop-blur-sm border-r border-neutral-100 shadow-2xl shadow-neutral-900/20 z-50 md:hidden transition-transform duration-300 ease-in-out",
          isOpen ? "translate-x-0" : "-translate-x-full",
        )}
        style={{ paddingLeft: "env(safe-area-inset-left)" }}
      >
        {children}
      </div>
    </>
  );
}

Then both MobileDocsDrawer and MobileHandbookDrawer can just supply their respective SidebarNavigation content inside this shell. Not required for correctness, but it will make future tweaks to the drawer behavior/layout easier to apply in one place.

📜 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 5f898bb and a1a5f97.

📒 Files selected for processing (1)
  • apps/web/src/routes/_view/route.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid creating a bunch of types/interfaces if they are not shared. Especially for function props, just inline them instead.
Never do manual state management for form/mutation. Use useForm (from tanstack-form) and useQuery/useMutation (from tanstack-query) instead for 99% of cases. Avoid patterns like setError.
If there are many classNames with conditional logic, use cn (import from @hypr/utils). It is similar to clsx. Always pass an array and split by logical grouping.
Use motion/react instead of framer-motion.

Files:

  • apps/web/src/routes/_view/route.tsx
🧬 Code graph analysis (1)
apps/web/src/routes/_view/route.tsx (1)
apps/web/src/components/sidebar-navigation.tsx (1)
  • SidebarNavigation (4-71)
⏰ 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). (6)
  • GitHub Check: Redirect rules - hyprnote
  • GitHub Check: Header rules - hyprnote
  • GitHub Check: Pages changed - hyprnote
  • GitHub Check: fmt
  • GitHub Check: ci
  • GitHub Check: Devin

Copy link
Contributor

@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

🧹 Nitpick comments (2)
apps/web/src/routes/_view/route.tsx (2)

107-118: Optional: Consider simplifying the DOM structure.

The additional inner wrapper div adds an extra DOM node. The ref and scroll behavior could potentially be applied directly to the drawer container (lines 99-106) by moving the scroll-related classes there.

However, if the separation is intentional for layout/styling purposes, the current structure is acceptable.


74-122: Recommended: Extract shared drawer logic.

Both MobileDocsDrawer and MobileHandbookDrawer have nearly identical backdrop and drawer structure. Consider extracting a shared MobileDrawer component that accepts the content as children to reduce duplication and improve maintainability.

Example structure:

function MobileDrawer({ 
  isOpen, 
  onClose, 
  ariaLabel, 
  children 
}: { 
  isOpen: boolean; 
  onClose: () => void; 
  ariaLabel: string;
  children: React.ReactNode;
}) {
  // Shared backdrop + drawer structure
}

This would eliminate ~40 lines of duplicated code.

Also applies to: 124-209

📜 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 a1a5f97 and 0264cde.

📒 Files selected for processing (1)
  • apps/web/src/routes/_view/route.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid creating a bunch of types/interfaces if they are not shared. Especially for function props, just inline them instead.
Never do manual state management for form/mutation. Use useForm (from tanstack-form) and useQuery/useMutation (from tanstack-query) instead for 99% of cases. Avoid patterns like setError.
If there are many classNames with conditional logic, use cn (import from @hypr/utils). It is similar to clsx. Always pass an array and split by logical grouping.
Use motion/react instead of framer-motion.

Files:

  • apps/web/src/routes/_view/route.tsx
🧬 Code graph analysis (1)
apps/web/src/routes/_view/route.tsx (1)
apps/web/src/components/sidebar-navigation.tsx (1)
  • SidebarNavigation (4-71)
⏰ 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). (6)
  • GitHub Check: Redirect rules - hyprnote
  • GitHub Check: Header rules - hyprnote
  • GitHub Check: Pages changed - hyprnote
  • GitHub Check: fmt
  • GitHub Check: ci
  • GitHub Check: Devin

@ComputelessComputer ComputelessComputer merged commit a1b9dc8 into main Dec 6, 2025
13 of 14 checks passed
@ComputelessComputer ComputelessComputer deleted the devin/1764919728-mobile-drawer-dismiss branch December 6, 2025 02:31
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.

2 participants