Repository navigation
fix(Layer): a capped layer over its trigger keeps its top - #10497
Conversation
A layer taller than the room on both sides of its trigger sits over the trigger, where the viewport fit shifts it. The keyboard cap makes it shorter, so it fits below the trigger, and the fallback order moved it there: the field being typed into jumped down as the keyboard came up, and back up as it went. While the cap holds such a layer, the runtime now lifts it back to the block-start it had when the cap landed, with insets that move its anchor area. Taking the cap off drops the lift.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report🔎 Preview ·
|
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| LayerProvider | 4.2 kB (0) · 20 B CSS (0) | — | ✓ · ✓ · ✗ |
| lab/TransferList | 106.0 kB (+150 B) · 1.7 kB CSS (0) | — | — · — · — |
| DateInput | 181.3 kB (+146 B) · 16.7 kB CSS (0) | — | — · — · — |
112 more components
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| SideNavHeading | 73.6 kB (+146 B) · 11.2 kB CSS (0) | — | — · — · — |
| DateRangeInput | 90.2 kB (+145 B) · 12.3 kB CSS (0) | — | — · — · — |
| lab/TransferListSelector | 112.7 kB (+145 B) · 1.9 kB CSS (0) | — | — · — · — |
| richtext/RichTextView | 274.2 kB (+145 B) · 2.3 kB CSS (0) | — | — · — · — |
| DateTimeInput | 203.4 kB (+144 B) · 18.4 kB CSS (0) | — | — · — · — |
| TopNav | 70.4 kB (+144 B) · 10.8 kB CSS (0) | — | — · — · — |
| Typeahead | 77.8 kB (+144 B) · 12.3 kB CSS (0) | — | — · — · — |
| Switch | 99.5 kB (+143 B) · 9.9 kB CSS (0) | — | — · — · — |
| Pagination | 107.3 kB (+142 B) · 17.5 kB CSS (0) | — | — · — · — |
| lab/ListInput | 99.6 kB (+142 B) · 1.6 kB CSS (0) | — | — · — · — |
| Lightbox | 110.1 kB (+140 B) · 10.3 kB CSS (0) | — | — · — · — |
| MultiSelector | 92.7 kB (+140 B) · 16.6 kB CSS (0) | — | — · — · — |
| SideNavCollapseButton | 59.3 kB (+140 B) · 9.9 kB CSS (0) | — | — · — · — |
| Carousel | 67.7 kB (+137 B) · 10.8 kB CSS (0) | — | — · — · — |
| Selector | 97.3 kB (+137 B) · 17.1 kB CSS (0) | — | — · — · — |
| TopNavHeading | 72.9 kB (+136 B) · 11.0 kB CSS (0) | — | — · — · — |
| richtext/RichTextEditor | 294.5 kB (+136 B) · 2.6 kB CSS (0) | — | — · — · — |
| Banner | 60.5 kB (+134 B) · 10.4 kB CSS (0) | — | — · — · — |
| Tokenizer | 89.4 kB (+134 B) · 18.3 kB CSS (0) | — | — · — · — |
| lab/CommentThread | 317.5 kB (+134 B) · 2.4 kB CSS (0) | — | — · — · — |
| richtext/RichTextEditorToolbar | 249.2 kB (+134 B) · 454 B CSS (0) | — | — · — · — |
| ChatLayoutScrollButton | 59.0 kB (+132 B) · 10.1 kB CSS (0) | — | — · — · — |
| DrawerHeader | 61.5 kB (+132 B) · 12.8 kB CSS (0) | — | — · — · — |
| MobileNav | 68.8 kB (+132 B) · 10.5 kB CSS (0) | — | — · — · — |
| ToggleButton | 59.4 kB (+132 B) · 10.0 kB CSS (0) | — | — · — · — |
| TopNavMenu | 72.6 kB (+132 B) · 11.1 kB CSS (0) | — | — · — · — |
| TimeInput | 157.3 kB (+131 B) · 15.7 kB CSS (0) | — | — · — · — |
| ChatDictationButton | 59.1 kB (+130 B) · 10.0 kB CSS (0) | — | — · — · — |
| Toast | 96.1 kB (+130 B) · 10.2 kB CSS (0) | — | — · — · — |
| ChatSendButton | 58.9 kB (+129 B) · 9.9 kB CSS (0) | — | — · — · — |
| FieldLabel | 49.1 kB (+129 B) · 5.6 kB CSS (0) | — | — · — · — |
| Button | 58.5 kB (+128 B) · 9.9 kB CSS (0) | — | — · — · — |
| Stepper | 60.2 kB (+128 B) · 10.0 kB CSS (0) | — | — · — · — |
| CheckboxListItem | 69.1 kB (+127 B) · 11.3 kB CSS (0) | — | — · — · — |
| BaseTypeahead | 69.3 kB (+126 B) · 10.8 kB CSS (0) | — | — · — · — |
| ChatComposerTokenElement | 73.7 kB (+126 B) · 11.2 kB CSS (0) | — | — · — · — |
| MobileNavToggle | 58.8 kB (+126 B) · 9.9 kB CSS (0) | — | — · — · — |
| StatusDot | 29.5 kB (+126 B) · 5.3 kB CSS (0) | — | — · — · — |
| TextArea | 60.4 kB (+126 B) · 9.2 kB CSS (0) | — | — · — · — |
| ChatComposer | 75.6 kB (+125 B) · 11.7 kB CSS (0) | — | — · — · — |
| ChatComposerInput | 73.7 kB (+125 B) · 11.2 kB CSS (0) | — | — · — · — |
| Table | 115.4 kB (+125 B) · 17.7 kB CSS (0) | — | — · — · — |
| DialogHeader | 61.3 kB (+124 B) · 11.4 kB CSS (0) | — | — · — · — |
| DropdownMenu | 94.3 kB (+124 B) · 17.1 kB CSS (0) | — | — · — · — |
| IconButton | 58.5 kB (+124 B) · 9.9 kB CSS (0) | — | — · — · — |
| CheckboxInput | 62.5 kB (+123 B) · 9.1 kB CSS (0) | — | — · — · — |
| TextInput | 65.9 kB (+123 B) · 11.0 kB CSS (0) | — | — · — · — |
| BreadcrumbItem | 82.5 kB (+122 B) · 12.0 kB CSS (0) | — | — · — · — |
| SegmentedControl | 91.9 kB (+122 B) · 6.8 kB CSS (0) | — | — · — · — |
| TabList | 42.0 kB (+122 B) · 6.4 kB CSS (0) | — | — · — · — |
| lab/ChatReactionBar | 102.7 kB (+122 B) · 1.1 kB CSS (0) | — | — · — · — |
| Avatar | 41.4 kB (+121 B) · 5.5 kB CSS (0) | — | — · — · — |
| Markdown | 177.8 kB (+121 B) · 20.0 kB CSS (0) | — | — · — · — |
| SideNav | 88.4 kB (+121 B) · 11.3 kB CSS (0) | — | — · — · — |
| Calendar | 69.5 kB (+120 B) · 10.5 kB CSS (0) | — | — · — · — |
| ListItem | 68.0 kB (+120 B) · 11.3 kB CSS (0) | — | — · — · — |
| AvatarGroup | 44.2 kB (+119 B) · 5.6 kB CSS (0) | — | — · — · — |
| CodeBlock | 73.2 kB (+118 B) · 11.2 kB CSS (0) | — | — · — · — |
| Toolbar | 41.3 kB (+118 B) · 7.9 kB CSS (0) | — | — · — · — |
| lab/EmojiPicker | 84.4 kB (+118 B) · 751 B CSS (0) | — | — · — · — |
| lab/TourStep | 93.5 kB (+118 B) · 590 B CSS (0) | — | — · — · — |
| TabMenu | 69.7 kB (+117 B) · 11.0 kB CSS (0) | — | — · — · — |
| lab/CommentComposer | 143.6 kB (+117 B) · 1.9 kB CSS (0) | — | — · — · — |
| InfoTip | 45.3 kB (+116 B) · 5.3 kB CSS (0) | — | — · — · — |
| Link | 51.4 kB (+116 B) · 7.0 kB CSS (0) | — | — · — · — |
| MoreMenu | 94.6 kB (+116 B) · 17.1 kB CSS (0) | — | — · — · — |
| Popover · Storybook | 87.1 kB (+116 B) · 13.9 kB CSS (0) | 1,490 (0) | ✓ · ✓ · ✓ |
| Slider | 104.9 kB (+116 B) · 8.7 kB CSS (0) | — | — · — · — |
| ComplexSelector | 69.0 kB (+115 B) · 11.7 kB CSS (0) | — | — · — · — |
| SideNavItem | 68.5 kB (+115 B) · 11.0 kB CSS (0) | — | — · — · — |
| lab/CommentPin | 54.8 kB (+115 B) · 1.2 kB CSS (0) | — | — · — · — |
| DropdownMenuSubMenu | 68.3 kB (+114 B) · 9.7 kB CSS (0) | — | — · — · — |
| TopNavMegaMenu | 67.8 kB (+114 B) · 11.7 kB CSS (0) | — | — · — · — |
| FileInput | 67.4 kB (+113 B) · 10.8 kB CSS (0) | — | — · — · — |
| HoverCard | 26.2 kB (+113 B) · 4.3 kB CSS (0) | — | — · — · — |
| RadioList | 54.4 kB (+112 B) · 7.2 kB CSS (0) | — | — · — · — |
| lab/Comments | 322.5 kB (+111 B) · 2.5 kB CSS (0) | — | — · — · — |
| AlertDialog | 103.1 kB (+110 B) · 14.2 kB CSS (0) | — | — · — · — |
| NumberInput | 69.9 kB (+110 B) · 11.3 kB CSS (0) | — | — · — · — |
| lab/Schedule | 103.0 kB (+110 B) · 3.9 kB CSS (0) | — | — · — · — |
| CheckboxList | 67.8 kB (+108 B) · 8.1 kB CSS (0) | — | — · — · — |
| lab/ChatEmojiPicker | 101.6 kB (+107 B) · 773 B CSS (0) | — | — · — · — |
| InputGroup | 54.7 kB (+106 B) · 7.8 kB CSS (0) | — | — · — · — |
| PowerSearch | 280.6 kB (+106 B) · 23.5 kB CSS (0) | — | — · — · — |
| ChatLayout | 61.8 kB (+104 B) · 10.4 kB CSS (0) | — | — · — · — |
| CommandPalette | 71.2 kB (+104 B) · 12.4 kB CSS (0) | — | — · — · — |
| Field | 53.0 kB (+104 B) · 7.2 kB CSS (0) | — | — · — · — |
| TableCell | 107.2 kB (+104 B) · 17.4 kB CSS (0) | — | — · — · — |
| ContextMenu | 105.9 kB (+103 B) · 17.0 kB CSS (0) | — | — · — · — |
| Tooltip | 27.8 kB (+103 B) · 4.3 kB CSS (0) | — | — · — · — |
| charts/ChartTooltip | 174.1 kB (+101 B) · 423 B CSS (0) | — | — · — · — |
| TableSelectionToolbar | 68.1 kB (+101 B) · 13.0 kB CSS (0) | — | — · — · — |
| Thumbnail | 62.9 kB (+101 B) · 11.5 kB CSS (0) | — | — · — · — |
| charts/Chart | 196.8 kB (+100 B) · 494 B CSS (0) | — | — · — · — |
| lab/SelectableCardGroup | 62.4 kB (+100 B) · 162 B CSS (0) | — | — · — · — |
| AppShell | 89.0 kB (+99 B) · 13.4 kB CSS (0) | — | — · — · — |
| RadioListItem | 65.5 kB (+99 B) · 10.1 kB CSS (0) | — | — · — · — |
| lab/DiffViewer | 84.8 kB (+99 B) · 2.1 kB CSS (0) | — | — · — · — |
| TableHeaderCell | 106.7 kB (+98 B) · 17.2 kB CSS (0) | — | — · — · — |
| AvatarGroupOverflow | 46.6 kB (+96 B) · 5.5 kB CSS (0) | — | — · — · — |
| CommandPaletteInput | 30.8 kB (+2 B) · 7.5 kB CSS (0) | — | — · — · — |
| ChatMessageList | 27.3 kB (0) · 7.0 kB CSS (0) | — | — · — · — |
| ChatToolCalls | 31.2 kB (0) · 8.3 kB CSS (0) | — | — · — · — |
| Heading | 11.6 kB (0) · 5.4 kB CSS (0) | — | — · — · — |
| ProgressBar | 11.7 kB (0) · 6.2 kB CSS (0) | — | — · — · — |
| Spinner | 23.9 kB (0) · 6.1 kB CSS (0) | — | — · — · — |
| Text | 11.0 kB (0) · 5.4 kB CSS (0) | — | — · — · — |
| Timestamp | 31.4 kB (0) · 10.2 kB CSS (0) | — | — · — · — |
| charts/ChartLegend | 47.1 kB (−1 B) · 224 B CSS (0) | — | — · — · — |
| Timer | 13.1 kB (−2 B) · 5.9 kB CSS (0) | — | — · — · — |
| layer | — | — | — · ✓ · — |
| Layer | — | — | ✓ · ✓ · — |
Package size: @astryxdesign/core 6.90 MB packed (+1.0 kB); no new dependencies.
API changes: none in this pull request
Committed API report behind this build: cli 20 rows, core 25 rows; run pnpm api:report.
Touched components checked; add ci:run-visual, ci:run-a11y or ci:run-rtl to run the full suites.
Generated by PR Enrichment workflow | View full report
There was a problem hiding this comment.
Approved pending CI: CI has not run on this head yet, so a maintainer needs to add the ci:run label for the unit and browser suites, WebKit included, to run.
The lift keeps a layer that the viewport fit shifted over its trigger at its top while the keyboard cap shortens it, as spec:AST-059 FR9 requires. The three new and changed unit cases fail on main and pass here, and a Chromium run of the taller Keyboard Avoidance popover held its top at 16 px in every frame (68 px on main). No blocking findings.
[Automated review]
|
/approve-spec 6b3d6d1 |
|
/approve-spec 6630e04 |
User impact
On a phone or an iPad, a popover can be taller than the room on both sides of its trigger. The viewport fit then places it over the trigger. When the software keyboard or a hardware keyboard's shortcut bar arrived, the popover jumped 52 px down. The field being typed into left the caret, and jumped back as the keyboard went down.
Problem and solution fit
So while capped, such a layer is lifted back to the block-start it had when the cap landed.
Expected behavior and authority
spec:AST-059FR9 says a layer the keyboard caps keeps its block-start edge and ends 10 px above the keyboard. FR4 shifts a layer taller than both sides over its trigger. No record changes.Smallest restoration
Layer/useLayerKeyboardClearance.tsmeasures where the shorter layer lands. If the fallback order moved it down without holding its bottom, the hook commits a lift of that distance.useLayer.tsxapplies the lift as block-start and block-end insets, which move the layer's anchor area up. Taking the cap off drops the lift. A layer placed above its trigger is not lifted. An engine that ignores the insets keeps today's behavior.Evidence
mainand pass here. The proof alone onmainis c321ab806c.mainmoved the layer 52 px on an iPhone and an iPad. Here it held in 6 of 6 takes.Scope
Testing
At 6b3d6d1 on
main0d7498a:pnpm exec vitest run packages/core/src/Layer packages/core/src/Popover packages/core/src/Selector: 39 files, 983 tests pass. The three new and changed unit cases fail onmain(caps of 67, 299 and 279 px instead of 247, 327 and 307 px).main, both engines fail both cases: the layer moves 52 px.PopoverKeyboardandkeyboardCappedListsbrowser specs: Chromium passed 17; WebKit passed 15 and skipped 2 Chromium-only proofs.mainonce and this change twice. Onmainthe layer's top went from 16 to 68 px. Here it stayed at 16 px, and the field's top held within 0.1 px. No script wrotescrollTopin any take. I viewed every frame in content-only crops.tscfor core, ESLint, Prettier, the 25-word comment check andpnpm review:prepass.mainon their own.