Skip to content

Conversation

@fx
Copy link
Owner

@fx fx commented Jul 29, 2025

Summary

  • Implemented a custom Drawer component built on Radix Dialog primitives with CSS animations
  • Replaced FullscreenModal with Drawer in EntityBrowser as requested
  • Solution works seamlessly in both development and test environments without external dependencies

Related Issues

Closes #143 (Find alternative drawer solution for EntityBrowser)
Addresses #136 (Fullscreen modal should only be used for CameraCard)

Context

This PR replaces the failed Vaul-based implementation (PR #142) with a custom drawer solution. The Vaul library had significant test environment compatibility issues that made it unsuitable for our needs.

Implementation Details

Custom Drawer Component (src/components/ui/Drawer.tsx)

  • Built directly on Radix Dialog primitives for proper accessibility
  • CSS-based animations for smooth slide-in effects from any edge
  • Supports all four directions: left, right, top, bottom
  • Configurable size, close behavior, and styling options
  • No external dependencies beyond Radix UI

Key Features

  • Test Compatibility: Works perfectly in jsdom environment without any mocking
  • Accessibility: Includes proper ARIA attributes, focus management, and keyboard navigation
  • Animations: Smooth CSS transitions with reduced-motion support
  • Portal Rendering: Escapes shadow DOM constraints
  • Touch Optimized: Responsive design with mobile-friendly sizing

EntityBrowser Updates

  • Replaced FullscreenModal with Drawer using right-side slide-in
  • Removed the close button from the header (ESC key still works)
  • Optimized layout for drawer presentation with full-height card
  • Maintained all existing functionality

Testing

  • ✅ All tests pass locally (npm test)
  • ✅ Linting passes (npm run lint)
  • ✅ TypeScript checks pass (npm run typecheck)
  • ✅ Tested in development environment
  • ✅ Tested drawer animations and interactions
  • ✅ Verified accessibility features work correctly
  • ✅ CameraCard continues to use FullscreenModal (unchanged)

Test Evidence

Test Files  39 passed (39)
     Tests  465 passed | 2 skipped (467)
  Start at  02:32:16
  Duration  13.03s

All tests pass without any failures. The drawer component works seamlessly in both development and test environments, completely avoiding the jsdom compatibility issues we encountered with the Vaul library in PR #142.

Breaking Changes

None - This is an internal UI component change that maintains the same external API.

Implementation Notes

  • The Drawer component is now available for reuse in other parts of the application
  • CSS animations are used instead of JavaScript for better performance and test compatibility
  • The component follows Radix UI's styling best practices without custom z-index values
  • Includes proper TypeScript types and JSDoc documentation

@fx fx force-pushed the feat/143-drawer-component branch from 3f39200 to f971df3 Compare December 4, 2025 00:16
Copilot AI review requested due to automatic review settings December 4, 2025 00:16
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements a custom Drawer component to replace FullscreenModal in EntityBrowser, addressing the need for a slide-in panel UI pattern. The implementation uses Radix Dialog primitives with CSS animations, providing better test compatibility than the previously attempted Vaul library solution.

Key Changes:

  • Created a new reusable Drawer component with support for four slide-in directions and comprehensive accessibility features
  • Migrated EntityBrowser from FullscreenModal to the new Drawer component with right-side slide-in
  • Updated EntityBrowser tests to verify ESC key functionality instead of close button interaction

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/components/ui/Drawer.tsx New drawer component built on Radix Dialog with accessibility, animation support, and configurable behavior
src/components/ui/drawer.css CSS animations and styles for drawer transitions, responsive design, and reduced-motion support
src/components/ui/index.ts Added Drawer to public UI component exports
src/components/EntityBrowser.tsx Replaced FullscreenModal with Drawer, removed close button, adjusted styling for drawer layout
src/components/__tests__/EntityBrowser.test.tsx Updated test to verify ESC key closing behavior instead of close button click

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

<Dialog.Portal>
<Dialog.Overlay
className="drawer-overlay"
onClick={closeOnBackdropClick ? () => onOpenChange(false) : undefined}
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The onClick handler on the overlay (line 94) conflicts with the onPointerDownOutside and onInteractOutside handlers on the Dialog.Content (lines 109-110). When closeOnBackdropClick is true, clicking the overlay will trigger both the overlay's onClick (calling onOpenChange(false)) and the Dialog's built-in outside click handlers. This creates redundant close calls.

Remove the onClick handler from the overlay and let Radix UI's built-in outside interaction handlers manage this behavior. They already handle backdrop clicks correctly when onPointerDownOutside and onInteractOutside are not prevented.

Suggested change
onClick={closeOnBackdropClick ? () => onOpenChange(false) : undefined}

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

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.

Find alternative drawer solution for EntityBrowser

2 participants