Parent PRD
#320
What to build
Build the <mnl-panel> molecule — the most architecturally complex component in the design system. It's a responsive overlay that automatically adapts its presentation based on viewport:
Mobile (< lg): Bottom Sheet
- Slides up from the bottom of the viewport
- Has a drag handle at the top (visual affordance, optional drag-to-dismiss)
- Backdrop overlay (semi-transparent)
- Transitions:
transform: translateY(100%) → translateY(0) with duration-300 ease-out
- Dismiss: tap backdrop, swipe down (optional), or explicit close button
Desktop (lg+): Centered Dialog
- Fades in at center of viewport with subtle scale transition
- Backdrop overlay
- Transitions:
opacity-0 scale-95 → opacity-100 scale-100 with duration-300
- Dismiss: click backdrop, Escape key, or explicit close button
- Max-width constrained (e.g.,
max-w-lg)
Shared API
- Signal inputs:
open (boolean), mode ('auto' | 'sheet' | 'dialog' — default 'auto' which uses viewport)
- Output:
closed (emits when panel is dismissed by any method)
- Content projection: header slot (
[mnlPanelHeader]) + body (default <ng-content>)
- Traps focus when open (focus trap for accessibility)
- Escape key closes the panel
aria-modal="true", role="dialog", aria-labelledby linked to header
Implementation approach
- Uses
matchMedia('(min-width: 1024px)') listener to determine mode when set to 'auto'
- CSS transitions only — no Angular animations module
- Focus trap via a lightweight directive or manual
keydown handler
- Body scroll lock when panel is open (prevent background scrolling)
Storybook: Stories under Molecules/Panel showing sheet mode, dialog mode, and auto mode at different viewports. Include a story with a form inside to demonstrate real usage.
Acceptance criteria
Blocked by
User stories addressed
- User story 20: Responsive panel (sheet on mobile, dialog on desktop)
- User story 30: Smooth transitions
- User story 35: Budget forms in panel
Parent PRD
#320
What to build
Build the
<mnl-panel>molecule — the most architecturally complex component in the design system. It's a responsive overlay that automatically adapts its presentation based on viewport:Mobile (< lg): Bottom Sheet
transform: translateY(100%)→translateY(0)withduration-300 ease-outDesktop (lg+): Centered Dialog
opacity-0 scale-95→opacity-100 scale-100withduration-300max-w-lg)Shared API
open(boolean),mode('auto' | 'sheet' | 'dialog' — default 'auto' which uses viewport)closed(emits when panel is dismissed by any method)[mnlPanelHeader]) + body (default<ng-content>)aria-modal="true",role="dialog",aria-labelledbylinked to headerImplementation approach
matchMedia('(min-width: 1024px)')listener to determine mode when set to 'auto'keydownhandlerStorybook: Stories under
Molecules/Panelshowing sheet mode, dialog mode, and auto mode at different viewports. Include a story with a form inside to demonstrate real usage.Acceptance criteria
mode="sheet"forces bottom sheet regardless of viewportmode="dialog"forces dialog regardless of viewportclosedclosedaria-modal="true"androle="dialog"presentprefers-reduced-motionBlocked by
User stories addressed