[DS-37] Implement Overlay component #10

Merged
chris merged 4 commits from feature/DS-37 into feature/DS-17 2026-09-04 07:38:47 -06:00
Owner

Ticket

DS-37 Implement Overlay component

Base branch note

This branch is based on feature/DS-17 (in Review, unmerged), not main — DS-37 needs the
kebab-case/native/-only component convention that only exists on that branch. The PR base is set
to feature/DS-17 accordingly, so this diff shows only DS-37's own commits. Once DS-17 merges to
main, this PR's diff (and its future rebase target) will reflect that.

Summary

  • Adds a new Overlay primitive (src/overlay/) — backdrop, portal (via RN's own Modal, aliased
    to react-native-web's Modal for Storybook/browser), DOM focus trap, Escape/back-button dismiss
    via onRequestClose, and web scroll-locking — that focus-stealing UI (Select today; Modal,
    ContextMenu, Confirm, a future Drawer later) composes on top of instead of reimplementing.
  • Fades in/out by default (animationType='fade'), with an animationType override for other
    motion (Select uses it to keep its prior slide-up sheet).
  • Composable API: backdropClassName/contentClassName for NativeWind-based placement,
    backdropStyle/contentStyle as an inline-style escape hatch for dynamically-computed anchoring
    (e.g. a future ContextMenu), and dismissible to gate backdrop/Escape/back-button close for
    confirm-style flows.
  • Scroll-lock uses a module-scoped reference count so nested/concurrent overlays (e.g. a Select
    opened from inside a Modal) don't unlock scroll early when they close out of order.
  • Refactors Select (src/select/native/index.tsx) to render Overlay instead of its own
    hand-rolled Modal + backdrop/sheet Pressables — same observable behavior, verified by its
    existing 9-test suite (only a -sheet → -content testID rename).
  • Three Storybook stories (src/overlay/native/stories.tsx) demonstrate the API generalizing to a
    centered dialog, a bottom sheet, and a non-dismissible confirm-style overlay.
  • src/overlay/native/test.tsx — 12 tests covering visibility, backdrop/content dismiss, the
    bubble guard, dismissible={false}, the onRequestClose (Escape/back-button) path, and
    non-LIFO scroll-lock behavior across multiple open overlays.

Verification: bun run typecheck, bun run lint, bun run test (49 pass, 0 fail), and
bun run build all pass.

## Ticket [DS-37](http://192.168.2.100:7123/home/browse/DS-37/) Implement Overlay component ## Base branch note This branch is based on `feature/DS-17` (in Review, unmerged), not `main` — DS-37 needs the kebab-case/`native/`-only component convention that only exists on that branch. The PR base is set to `feature/DS-17` accordingly, so this diff shows only DS-37's own commits. Once DS-17 merges to `main`, this PR's diff (and its future rebase target) will reflect that. ## Summary - Adds a new `Overlay` primitive (`src/overlay/`) — backdrop, portal (via RN's own `Modal`, aliased to `react-native-web`'s `Modal` for Storybook/browser), DOM focus trap, Escape/back-button dismiss via `onRequestClose`, and web scroll-locking — that focus-stealing UI (`Select` today; `Modal`, `ContextMenu`, `Confirm`, a future `Drawer` later) composes on top of instead of reimplementing. - Fades in/out by default (`animationType='fade'`), with an `animationType` override for other motion (`Select` uses it to keep its prior slide-up sheet). - Composable API: `backdropClassName`/`contentClassName` for NativeWind-based placement, `backdropStyle`/`contentStyle` as an inline-style escape hatch for dynamically-computed anchoring (e.g. a future `ContextMenu`), and `dismissible` to gate backdrop/Escape/back-button close for confirm-style flows. - Scroll-lock uses a module-scoped reference count so nested/concurrent overlays (e.g. a `Select` opened from inside a `Modal`) don't unlock scroll early when they close out of order. - Refactors `Select` (`src/select/native/index.tsx`) to render `Overlay` instead of its own hand-rolled `Modal` + backdrop/sheet `Pressable`s — same observable behavior, verified by its existing 9-test suite (only a `-sheet` → `-content` testID rename). - Three Storybook stories (`src/overlay/native/stories.tsx`) demonstrate the API generalizing to a centered dialog, a bottom sheet, and a non-dismissible confirm-style overlay. - `src/overlay/native/test.tsx` — 12 tests covering visibility, backdrop/content dismiss, the bubble guard, `dismissible={false}`, the `onRequestClose` (Escape/back-button) path, and non-LIFO scroll-lock behavior across multiple open overlays. Verification: `bun run typecheck`, `bun run lint`, `bun run test` (49 pass, 0 fail), and `bun run build` all pass.
chris merged commit 6e460f163c into feature/DS-17 2026-09-04 07:38:47 -06:00
chris deleted branch feature/DS-37 2026-09-04 07:38:47 -06:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
chris/design-system!10
No description provided.