Skip to content

feat(branches): ResponsiveDialog — dialog on desktop, bottom sheet on mobile#43

Merged
mattmaynes merged 1 commit into
mainfrom
0031-responsive-dialog
Jul 12, 2026
Merged

feat(branches): ResponsiveDialog — dialog on desktop, bottom sheet on mobile#43
mattmaynes merged 1 commit into
mainfrom
0031-responsive-dialog

Conversation

@mattmaynes

Copy link
Copy Markdown
Contributor

Summary

Adds ResponsiveDialog to @rogueoak/canopy/branches (spec 0031): one compound that renders a centred modal on desktop and a bottom sheet on mobile, chosen at (max-width: 767px). Mirrors the Dialog family one-for-one, so a consumer swaps Dialog*ResponsiveDialog* with no other change.

  • Desktop (≥768px): delegates to DialogContent verbatim → pixel-identical to a plain Dialog.
  • Mobile (<768px): bottom-anchored sheet on the same Radix primitive — full-width, max-h-[85vh] + scroll, rounded-t-lg, grab-handle affordance, slides up.
  • Behaviour + a11y (focus trap, scroll lock, Esc, scrim dismiss, aria-modal/aria-labelledby/aria-describedby) are Radix's, shared by both forms.

Changes

  • roots: bottom-sheet-in/out keyframes + --animate-bottom-sheet-* theme vars (Y-axis sibling of the drawer slide).
  • canopy: exported useMediaQuery / useIsMobile / MOBILE_QUERY (extracted from SideNav's inlined pattern); ResponsiveDialog* family + barrel export.
  • spec 0031 + architecture reflection.
  • No new token, no new dependency, no dark:.

Test

  • pnpm build && pnpm test && pnpm lint && pnpm format:check all green locally (262 tests, incl. a parameterised suite over both forms).

🤖 Generated with Claude Code

… on mobile)

ResponsiveDialog mirrors the Dialog family one-for-one so a consumer swaps
Dialog* -> ResponsiveDialog* with no other change. On viewports >=768px it
delegates to DialogContent verbatim (exact parity); below 768px it renders a
bottom-anchored sheet on the same Radix primitive - full-width, capped at 85vh
and scrollable, grab-handle affordance, sliding up via a new bottom-sheet-*
motion utility. Behaviour and a11y (focus trap, scroll lock, Esc, scrim,
aria-*) are shared by both forms; only geometry and motion differ. No new token.

- roots: add bottom-sheet-in/out keyframes + --animate-bottom-sheet-* theme vars
- canopy: exported useMediaQuery/useIsMobile hook (extracted from SideNav's pattern)
- spec 0031

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014BG2KnZxnE2rMd2XcDmNcg
@mattmaynes mattmaynes merged commit f69814e into main Jul 12, 2026
1 check passed
@mattmaynes mattmaynes deleted the 0031-responsive-dialog branch July 12, 2026 17:33
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