Skip to content

Conversation

@damacus
Copy link
Owner

@damacus damacus commented Feb 9, 2026

Summary

Redesigns the mobile hamburger menu from a centered full-screen dialog to a proper left-side slide-out drawer.

Closes med-tracker-9fr9

Changes

SheetContent component

  • Replace centered dialog with side-positioned drawer
  • Drawer width: 80vw with max-w-[300px] (~75-80% of mobile viewport)
  • Add data-testid for testability, aria-modal and aria-label for accessibility
  • CSS transform-based slide animation (300ms ease-in-out)

Sheet Stimulus controllers

  • sheet_controller.js: Proper wrapper with fixed positioning for correct stacking
  • sheet_content_controller.js: Escape key handler, close animation with delay

Tests (7 new system specs)

  • Left positioning, backdrop, dismiss on click/Escape, width ratio, aria attrs, WCAG touch targets

Test Results

  • 533 non-browser tests: 0 failures
  • 325 browser tests: 0 failures (1 pre-existing OTEL failure)
  • RuboCop: 0 offenses on changed files

- Replace centered dialog with left-side slide-out drawer (80vw, max 300px)
- Add semi-transparent backdrop with click-to-dismiss
- Add Escape key dismissal via Stimulus controller
- Add proper aria-modal and aria-label for accessibility
- Add CSS transform-based slide animation (300ms ease-in-out)
- Touch targets meet WCAG 2.2 SC 2.5.8 minimum (24px)
- Add 7 new system specs covering drawer behavior
- Closes med-tracker-9fr9
- Add hamburgers CSS (Spring variant, compiled to plain CSS)
- Replace ghost icon button with animated hamburger--spring toggle
- Hamburger animates to X when drawer opens, reverses on close
- Sheet controller toggles is-active class and aria-expanded
- Sheet content controller calls back via Stimulus outlet to reset hamburger
- Backdrop click and Escape key both dismiss drawer and reset icon
- Prevents double-open with wrapper guard
- Use isConnected guard to allow re-opening after wrapper is removed from DOM
- Reset hamburger via direct DOM query instead of broken Stimulus outlet
- Call sheetController.close() via getControllerForElementAndIdentifier
- Add regression test for open-close-open flow
- Add screenshots showing all 4 drawer states
@damacus
Copy link
Owner Author

damacus commented Feb 9, 2026

Screenshots — Mobile Drawer (375×667 viewport)

1. Closed state — Hamburger icon (Spring variant)

01-mobile-nav-closed

2. Drawer open — Slides from left with backdrop

02-mobile-drawer-open

3. After dismiss — Hamburger resets to three lines

03-mobile-drawer-dismissed

4. Reopened — Drawer opens again after dismiss

04-mobile-drawer-reopened


Verified behaviors:

  • Hamburger Spring animation (three lines to X on open, X to three lines on close)
  • Drawer slides from left, ~80% viewport width
  • Semi-transparent backdrop dims content
  • Backdrop click dismisses drawer
  • Escape key dismisses drawer
  • Drawer can be reopened after dismissal (regression test added)
  • Touch targets >= 24px (WCAG 2.2 SC 2.5.8)
  • aria-modal, aria-label, aria-expanded attributes
  • 11 system specs, 843 total tests pass

- Renders X icon button in drawer header next to MedTracker title
- 44x44px touch target meets WCAG 2.2 SC 2.5.8 recommended size
- aria-label="Close menu" for screen readers
- Focus ring for keyboard navigation
- Triggers sheet-content#close Stimulus action
Remove unnecessary grid gap-4 from single-child wrapper.
py-4 provides section separation; inner gap-2 handles item spacing.
@damacus damacus merged commit 2f7370c into main Feb 9, 2026
9 checks passed
@damacus damacus deleted the cascade/coding-agent-servername-uri-mcp-beads-11ba22 branch February 9, 2026 23:12
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