Repository navigation
fix(Popover): under a finger, a tap during the presentation is ignored, as on iOS #8223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b83240b
fbe71df
288070e
904c29f
1fd5176
e0a9bb5
1fda019
515dd46
415707b
5f98e88
134e7c9
1cc771f
940af75
62d1a30
1f71ae2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| '@astryxdesign/core': patch | ||
| --- | ||
|
|
||
| [chore] Internal: the layer runtime gains one exit copy for touch presentations that animate a popover out: a static, inert copy of the closing popover, shown only in the top layer where the popover was drawn, for the close to play on. Core's other inert copies now join no form, carry no anchor name and keep their color scheme, as their documentation says. | ||
|
|
||
| @vjeux |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| '@astryxdesign/core': patch | ||
| --- | ||
|
|
||
| [feature] Under a finger (a coarse primary pointer, on any touch device), Popover grows out of its trigger, wide before tall, with its edge held on the trigger, and shrinks back into the trigger when it closes. The growth plays the theme's `--duration-medium-min` (in the Storybook theme, the step nearest iOS's 206 ms growth) with its entrance easing, and the shrink plays its exit duration and easing, on the compositor. A close during the growth, or an open during the shrink, turns back from where the popover is. With reduced motion it cross-fades in and out, opacity only, in 200 ms or less. A fine primary pointer (a mouse) keeps its entrance. A tap that lands while it grows is ignored, and a pan started then scrolls nothing. The shrink plays on the layer runtime's exit copy, of which Popover is the first user. | ||
|
|
||
| @vjeux |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,8 @@ verified_by: | |
| packages/core/src/Layer/useLayerDismissal.test.tsx, | ||
| packages/core/src/Layer/layerClickBoundary.test.tsx, | ||
| packages/core/src/Layer/layerDismissalInvariants.test.tsx, | ||
| packages/core/src/Layer/layerExitCopy.test.ts, | ||
| packages/core/src/Layer/__tests__/layerExitCopy.interaction.browser.spec.ts, | ||
| packages/core/src/Popover/Popover.test.tsx, | ||
| packages/core/src/DropdownMenu/DropdownMenu.test.tsx, | ||
| packages/core/src/ContextMenu/ContextMenu.test.tsx, | ||
|
|
@@ -67,6 +69,7 @@ deciding_specs: [spec:AST-038, spec:AST-059] | |
| "INV7", | ||
| "INV11", | ||
| "INV12", | ||
| "INV13", | ||
| "INV14", | ||
| "INV15", | ||
| "INV17", | ||
|
|
@@ -314,6 +317,26 @@ else closes the layer, a scroll or pinch that starts outside does not, and | |
| Escape stays on the shared stack. Focus leaving the field stays each owner's to | ||
| handle (`family:overlay-dismissal` AV4). | ||
|
|
||
| ### Exit copy | ||
|
|
||
| The browser hides a popover the moment it closes, whether by a pick, Escape, or | ||
| its own light dismiss. A touch presentation whose close stays on screen plays it | ||
| on an exit copy: a static copy of the layer that `placeLayerExitCopy` takes as | ||
| the layer closes. The copy is laid out on the layer's own box and carries the | ||
| transform and opacity the layer is drawn with, so a copy taken while the layer | ||
| is still entering holds where it was drawn. It carries no ids, form names, or | ||
| form owner; it is `inert`, hidden from assistive technology, and out of pointer | ||
| reach; it keeps the layer's scroll positions. It is shown only in the top layer, | ||
| as a manual popover, so a clipping, transformed, or sticky ancestor neither cuts | ||
| nor moves it; a fixed box or a larger `z-index` is no substitute | ||
| (`spec:AST-027` FR8). Where the browser refuses that show during the closing | ||
| popover's own toggle, the copy waits, hidden, and enters the top layer once the | ||
| toggle is over: after the script that closed the layer, or in the next frame | ||
| before it paints. Where there is no top layer (no popover API), or the browser | ||
| still refuses, there is no copy and the close is immediate. The presentation | ||
| that placed the copy plays its exit on it (`spec:AST-094` FR7) and removes it | ||
| when its close settles. | ||
|
|
||
| ### Current dismissal plumbing | ||
|
|
||
| `family:overlay-dismissal` owns the shipped Escape/platform-close membership | ||
|
|
@@ -524,6 +547,12 @@ layers use Layer rendering without joining Escape/platform dismissal. | |
| correct, and the runtime polls nothing: an anchor that a scrolled | ||
| container hides is followed again when an intersection observer reports it | ||
| back in view. | ||
| - **INV13 — One exit copy per closing layer.** A layer's close plays on at most | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This INV13, with the Exit copy section above it, is record text CURRENT does not have, and an engineering owner asked that it not land through this pull request (“Record text lands only through an approved spec PR”). It arrives from #8186; landing it there with its own approval, or in a spec pull request, takes it out of this diff.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This INV13, with the Exit copy section (lines 304-321) and the rows at 565-571, 602-607, 629-632 and 682, is record text that
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This INV13, with the Exit copy section (lines 304-321) and the rows at 565-571, 602-607, 629-632 and 682, is record text
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This INV13, with the Exit copy section (lines 304-321) and the rows at 565-571, 602-607, 629-632 and 682, is record text |
||
| one exit copy, made by `placeLayerExitCopy`: drawn where the layer was drawn, | ||
| inert, hidden from assistive technology, without ids, form names, or form | ||
| owner, shown only in the top layer, and removed by its owner when the close | ||
| settles. Placing a second copy for the same layer removes the first; another | ||
| layer's copy stays. | ||
| - **INV14 — The runtime owns every layer's shared mechanism.** Internally, the layer runtime owns the shared | ||
| mechanism layers use: top-layer mounting, close-request delivery, the | ||
| presentation hold (keeping a layer's chosen presentation from the open until | ||
|
|
@@ -591,11 +620,12 @@ Current gaps are observable facts, not current target behavior: | |
| migration, verification, and completion criteria for these gaps. This record must | ||
| be updated only as that work ships. | ||
|
|
||
| INV14 and INV15 are not met yet, and `spec:AST-003` does not cover them: no | ||
| shared presentation hold, exit copy, runtime backdrop tint, or lift module | ||
| exists, and Dialog, Drawer, BottomSheet, Lightbox, MobileNav, ToastViewport, | ||
| and Selector each build their own top-layer mounting, exit, or backdrop, and | ||
| Popover builds its own presentation hold for its sheet presentation. | ||
| INV14 and INV15 are not met yet, and `spec:AST-003` does not cover them. The | ||
| runtime owns the shared exit copy (INV13, `placeLayerExitCopy`); no shared | ||
| presentation hold, runtime backdrop tint or lift module exists, Dialog, Drawer, | ||
| BottomSheet, Lightbox, MobileNav, ToastViewport, and Selector each build their | ||
| own top-layer mounting, exit, or backdrop, and Popover builds its own | ||
| presentation hold for its sheet presentation. | ||
| BottomSheet's own includes its sheet stack's mounting — the re-show that | ||
| keeps a document's sheets in open order, a step dialog's modal present, and | ||
| the non-modal sheet's popover host — alongside its scrim; the ordering rules | ||
|
|
@@ -648,6 +678,12 @@ is staged as `[breaking]` (`spec:AST-017` FR32) and `component:SelectableCard` | |
| entry/return, and controlled close behavior. | ||
| - A browser fallback change updates public `useLayer` and Popover docs and tests | ||
| for both the native path and actual fallback. | ||
| - An exit-copy change verifies, where each can be observed: the copy's reach, | ||
| accessibility and form exclusion in jsdom; its top-layer show (from script | ||
| and by light dismiss), its place mid-entrance, and that a layer keeps one | ||
| copy, in jsdom and in Chromium and WebKit; and the refused show's wait in | ||
| jsdom and on Chromium 150 and later, the engines that refuse a show during | ||
| another popover's toggle (Chromium 149 accepts it). | ||
|
|
||
| ## Owning code | ||
|
|
||
|
|
@@ -677,6 +713,8 @@ is staged as `[breaking]` (`spec:AST-017` FR32) and `component:SelectableCard` | |
| `stopPropagation()` also stops the native event in React 19, which would | ||
| break ContextMenu's outside `mousedown`, Typeahead's pending click, and the | ||
| layer's keep-open `pointerup`, so the seam never stops the native event. | ||
| - `Layer/layerExitCopy.ts` owns the exit copy a touch presentation's close plays | ||
| on. | ||
| - `Layer/layerStack.ts`, `Layer/useLayerDismissal.ts`, and | ||
| `Layer/LayerDepthContext.tsx` own current registration, presence, ordering, and | ||
| Escape/platform routing. | ||
|
|
@@ -730,6 +768,7 @@ this current architecture record. | |
| | INV3–INV5 | `useLayer.test.tsx` and `anchorName.test.ts` | A mode leaks geometry, RTL resolves from the wrong context, fallback clips, or a sibling anchor is lost | | ||
| | INV11 | `layerViewportInset.test.ts`, `useLayer.test.tsx`, and the `Core/Layer` viewport-inset stories under the story play guard at a desktop and a phone viewport; `BaseTypeahead.incremental.test.tsx` and the Typeahead incremental-results stories for the `spec:AST-092` FR6 exception | A second gutter definition, a `100%`-of-span cap, a layer narrower than its explicit size, a layer box wider than the viewport, a layer inside the gutter, or a layer that slides toward an off-screen anchor; for an open Typeahead popup, a later list for the same query that flips it to the other side or grows it past the room on its side, or a first list for a query that is capped to the span beside the trigger | | ||
| | INV12 | The `Core/Layer` viewport-inset stories' first-frame comparison, and `useLayer.test.tsx`'s synchronous anchor read | A layer whose first painted rectangle differs from its settled one | | ||
| | INV13 | `layerExitCopy.test.ts` and `layerExitCopy.interaction.browser.spec.ts` | A copy with an id, a form name, a form owner, or pointer reach; a copy off the layer's drawn box; a copy outside the top layer; a second copy for one layer | | ||
| | INV6, INV7 | `useLayer.test.tsx`, `Popover.test.tsx`, `DropdownMenu.test.tsx`, and `useMenuHover.test.tsx` | Duplicate close callback or the same press/re-hover reopens a surface | | ||
| | INV8 | `useLayerDismissal.test.tsx`, `layerDismissalInvariants.test.tsx`, and `useFocusTrap.test.tsx` | Current top registered layer is skipped, two layers close, or a blocker leaks through | | ||
| | INV9 | Representative Dialog, ContextMenu, Tooltip/HoverCard, and BottomSheet source/tests; `useBackdropPress.test.tsx`; `outsidePress.test.ts` | A current local channel silently changes ownership or policy | | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This INV13, the Exit copy section (lines 304-321) and the keyboard wording added to INV11 and INV12 are normative text that no engineering owner has approved at this head, and an engineering owner asked on this pull request that it be dropped here, since record text lands only through an approved spec pull request. It arrives from #8186 and #8208, so landing those first, with the text approved there or split into its own spec pull request, takes it out of this diff.