Repository navigation
feat(core): prototype BottomSheetStack - #5813
imdreamrunner wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR Analysis Report
Modified ComponentsBottomSheet (@astryxdesign/core)
Bundle Size Summary
Accessibility AuditStatus: No accessibility violations detected. Visual Regression194 added · 0 removed. View the report A repository maintainer can accept these exact frames: Generated by PR Enrichment workflow | View full report |
|
AI review status for this pull request.
|
There was a problem hiding this comment.
Approval waits on a maintainer providing or identifying the governing spec for stacked bottom sheets: whether Core adopts this separate BottomSheetStack, with its controlled openSheetIds list and fixed receding motion, or one of the AST-044 options in #6042, #6728, #7503 and #7648. Whatever that decision, two defects need fixing: the non-modal hasScrim={false} shell orders itself with z-index: 1000, which AST-027 DEC-3 rules out in favor of the browser top layer, and a listed top sheet that unmounts leaves an unnamed, scroll-locked modal with nothing operable. The branch also needs a rebase onto main, where it conflicts in the overlay-dismissal family record and three BottomSheet files, and the stack's push and pop detection should not depend on a ref that rendering reads but only an effect updates.
[Automated review]
| }, | ||
| dialogNonModal: { | ||
| pointerEvents: 'none', | ||
| zIndex: 1000, |
There was a problem hiding this comment.
This non-modal shell orders the whole stack against the page with z-index: 1000 plus show(). AST-027 DEC-3 says a dialog's cross-surface order "comes from the browser host and Layer contract, not a number", and it rejects "a large z-index as a substitute for Layer". Could the first version ship modal-only, or route the non-modal mode through Layer and the native top layer?
| const isStackVisible = | ||
| topSheet != null || visibleTransition.exitingSheet != null; |
There was a problem hiding this comment.
isStackVisible counts the last listed id even when no BottomSheet with that id is mounted. If the top sheet unmounts while its id stays listed, the dialog stays modal and scroll-locked, loses its accessible name, and only an inert covered sheet remains. BottomSheetSwitcher guards this case with unmountedSheetIds; the same guard here, plus a development warning, would close or recover the stack.
| if (stacksEqual(previousSheets, openSheetIds)) { | ||
| return; | ||
| } | ||
| committedOpenSheetIdsRef.current = [...openSheetIds]; |
There was a problem hiding this comment.
After mount, committedOpenSheetIdsRef is updated only here, yet render reads it (lines 220–228) to choose every sheet's phase, inert and aria-hidden. react-component-runtime INV4 says a ref mutation must not be the sole source for rendered output. Keeping the previous stack in state and adjusting it during render would also remove this state-setting effect.



Summary
This is a working prototype for API review of
BottomSheetStack.BottomSheetSwitcherProposed API
openSheetIdsis ordered bottom-to-top. An empty array closes the stack.BottomSheetSwitcherremains the mutually-exclusive replacement-step API; it is not widened to accept arrays.Design choices
push()/pop()API and no hidden ordering inferred from independent child booleans.BottomSheetkeeps its existingsheetId, content, height, snap-point, and purpose props.stackingAnimationfunctions.Validation
pnpm lint:strictpnpm buildpnpm check:repo0.96 / -8px; three levels measured0.92 / -16px,0.96 / -8px,1 / 0px; only the top layer was interactivepnpm testwas also run. Its six failures reproduce on currentmain: two ContextMenu BottomSheet tests, two known story-tree failures, and two discovery timeouts that pass in isolation.