Skip to content

[Refactor] Extract BottomSheet primitive from 3 PWA components#186

Merged
samzong merged 1 commit intomainfrom
fix/bottom-sheet-primitive
Mar 27, 2026
Merged

[Refactor] Extract BottomSheet primitive from 3 PWA components#186
samzong merged 1 commit intomainfrom
fix/bottom-sheet-primitive

Conversation

@samzong
Copy link
Copy Markdown
Collaborator

@samzong samzong commented Mar 27, 2026

Summary

Extract the duplicated bottom-sheet pattern (backdrop + spring animation + drag-to-dismiss + drag handle + focus trap + escape key) from AgentSelector, GatewayDebugLog, and SettingsSheet into a single BottomSheet primitive.

Type of change

  • [Refactor] internal cleanup

Why is this needed?

Three components copy-pasted ~40 lines of identical bottom-sheet infrastructure. The copies had silently diverged:

  • GatewayDebugLog was missing role="dialog", aria-modal, aria-label, focus trap, and focus restore
  • SettingsSheet was missing focus trap and focus restore
  • All three lacked body scroll lock (background scrolls through the sheet on iOS Safari)

What changed?

  • New: BottomSheet.tsx (~110 lines) — encapsulates backdrop, spring animation, drag-to-dismiss, drag handle, focus trap, focus restore, body scroll lock, escape key, safe area, and ARIA attributes
  • Modified: AgentSelector.tsx (156 → 67 lines) — delegates sheet infrastructure to BottomSheet, keeps only agent-specific content
  • Modified: GatewayDebugLog.tsx (192 → 132 lines) — delegates sheet infrastructure, gains role="dialog" / aria-modal / aria-label / focus trap / focus restore
  • Modified: SettingsSheet.tsx (165 → 113 lines) — delegates sheet infrastructure, gains focus trap / focus restore
  • Net: -64 lines, 3 accessibility bugs fixed, body scroll lock added

Architecture impact

  • Owning layer: renderer (PWA)
  • Cross-layer impact: none
  • Invariants touched from docs/architecture-invariants.md: none
  • Why those invariants remain protected: change is renderer-only, no protocol/state/persistence changes

Linked issues

Closes #

Validation

  • pnpm lint
  • pnpm test
  • pnpm check:ui-contract
  • pnpm check (full gate: lint + architecture + ui-contract + renderer-copy + i18n + dead-code + format + typecheck + test)
  • Not run

Commands, screenshots, or notes:

pnpm check — all gates passed

Screenshots or recordings

No visual change — same animation, same thresholds, same styling. Behavioral fixes (focus trap, scroll lock) are not visible in screenshots.

Release note

  • No user-facing change. Release note is NONE.
NONE

Checklist

  • The PR title uses at least one approved prefix: [Feat], [Fix], [UI], [Docs], [Refactor], [Build], or [Chore]
  • The summary explains both what changed and why
  • Validation reflects the commands actually run for this PR
  • Architecture impact is described and references any touched invariants
  • Cross-layer changes are explicitly justified
  • The release note block is accurate

@github-actions
Copy link
Copy Markdown
Contributor

Hi @samzong,
Thanks for your pull request!
If the PR is ready, use the /auto-cc command to assign Reviewer to Review.
We will review it shortly.

Details

Instructions for interacting with me using comments are available here.
If you have questions or suggestions related to my behavior, please file an issue against the gh-ci-bot repository.

@samzong samzong merged commit 5536d7f into main Mar 27, 2026
7 checks passed
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