Skip to content

fix(BottomSheet): a set-height sheet keeps its content padding in WebKit's scroll range - #8557

Draft
vjeux wants to merge 1 commit into
meta:mainfrom
vjeux:uikit/f1-bottom-sheet-content-min-height
Draft

vjeux wants to merge 1 commit into
meta:mainfrom
vjeux:uikit/f1-bottom-sheet-content-min-height

Conversation

@vjeux

@vjeux vjeux commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Review only this PR's change: vjeux/astryx@8a13f3d...982a837

Why

In Safari on iPhone, and in WebKit generally, a bottom sheet at a set height (capped, tall, snap points) whose overflowing content sits directly in it, without a Section, scrolls to an end flush with the last line: the content padding below it is gone, so the last line sits against the sheet's bottom edge, under the home indicator. Chrome keeps the 16 px.

What led to it

This comes from the work to make Astryx's touch components behave as native iOS ones do (sheets, menus, gestures and their motion). The content box is height: 100%; min-height: min-content. On a set height 100% resolves, and WebKit ignores min-content on a block's min-height, so the box stays the body's height (522 px against 1,760 px of content) and its bottom padding falls out of the scroll range.

Options and tradeoffs

  • Add the padding to the scroll container instead: changes which box carries the padding, which component:BottomSheet FR3 assigns to the content box.
  • Drop height: 100%: loses the definite height that content sized in percentages relies on.
  • Use min-height: fit-content: the same size in the block axis, and WebKit honours it.

Why this choice

It is a one-value change that keeps the box's role and its percentage-height basis, and it makes WebKit lay the box out exactly as Chrome already does.

How to check it

  1. On the iOS simulator, open a BottomSheet story with a capped height and long content directly inside, and scroll to the end: 16 px of padding remains below the last line (0 px before).
  2. Run the new scroll-end guard in WebKit: its capped case fails on main and passes here; Chromium passes either way.

Evidence

  • iOS Safari (26.2 simulator, two takes each): 0 px before, 16 px after; the scroll range grows from 1,302 to 1,318 px.
  • Chromium: all 31 readings across every BottomSheet story, detent and scroll end are identical in layout and pixels. WebKit now matches Chromium's content box in all 31 (16 differed before), with pixels unchanged except at the capped sheet's scroll end.

Scope

  • One defect is restored.
  • Separable contradictory or unsettled tagalongs were removed or split.
  • No new public API, visual representation, default, or interaction model is hidden under the bug-fix label.
  • Public text and artifacts contain no internal Meta context.

@vercel

vercel Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Oct 26, 2026 10:43pm UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Oct 27, 2026, 12:10 AM UTC

@github-actions github-actions Bot added the needs:design-review Affects visuals — Design should review label Oct 26, 2026
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 26, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes: the min-height: fit-content change works in WebKit (a capped sheet with content placed directly in it now ends 16 px below its last line instead of 0 px, and Chromium is unchanged), but two points need addressing before approval.

  • The flex-row dialog host carried from #8534 contradicts the current component:BottomSheet record, whose element jobs say the dialog holds the panel "with its own grid"; please amend that line through the spec gate (an engineering owner can approve it with /approve-spec <head SHA>) or keep the grid.
  • Both changesets claim Safari fixes, but the readings come from Playwright WebKit, and spec:AST-013 FR10 asks for evidence from Safari itself; please add iOS Safari readings (including one behind the "about 40 ms" relayout figure) or narrow the wording to what was measured.

[Automated review]

display: 'grid',
alignContent: 'end',
justifyItems: 'center',
display: 'flex',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes the open dialog a flex row, but the current component:BottomSheet record (Performance and resources, element jobs) says the dialog "holds the panel at the block end with its own grid". Please amend that line through the spec gate or keep the grid host; the layout itself is unchanged in Chromium and WebKit.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The record line is amended in #8534 (1e69c8e), which this pull request carries; its owner question asks for the spec gate's approval.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The flex row is no longer part of this pull request: it now sits on main's grid host, where the fix and its guard pass in both engines. Whether the row stays is #8534's own owner question.

'@astryxdesign/core': patch
---

[fix] BottomSheet: in Safari, a sheet at a set height whose content sits directly in it keeps its bottom padding at the end of its scroll, instead of ending flush with the last line.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix holds in Playwright WebKit (0 px to 16 px at the scroll end of a capped direct-content sheet), but spec:AST-013 FR10 says Playwright WebKit does not prove Safari behavior. Please add an iOS Safari reading before and after, or describe the fix in terms of what was measured.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Narrowed in 9bfb74a to what was measured, Playwright's WebKit. iOS Safari readings before and after are being taken, and the wording will name Safari once they land.

Comment thread .changeset/bottom-sheet-flex-host.md Outdated
'@astryxdesign/core': patch
---

[fix] BottomSheet: in Safari, an update inside an open sheet no longer holds up the page about 40 ms longer than it should. The open sheet's dialog places its panel with a flex row instead of a grid; the layout is the same.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "about 40 ms" Safari figure needs a measurement from Safari itself under spec:AST-013 FR10; the commit messages report it from a phone-sized WebKit page.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Narrowed in #8534 1e69c8e: the figure is now attributed to Playwright's WebKit on a phone-sized page. iOS Safari frame gaps are being taken.

@github-actions github-actions Bot added the needs:spec-owner-review Current knowledge records await owner approval label Oct 26, 2026
…Kit's scroll range

The panel's content box takes min-height: min-content so it grows with its
content past a fixed-height viewport. WebKit ignores min-content on a
block's min-height, so on a sheet at a set height the box stayed its body's
height: content placed directly in it overflowed the box, and its block-end
padding fell out of the scroll range, ending the scroll flush with the last
line. fit-content is the same size in the block axis and WebKit honours it.

A guard reads, at each sheet's scroll end, how far the content clears the
range's end: on main a capped sheet with direct content reads 0 px in
WebKit, and 16 px (the content padding) with the fix. iOS Safari on the
26.2 simulator reads the same, 0 px before and 16 px after; Chromium was
already right. The guard also covers two hug sheets with direct content.
@vjeux
vjeux force-pushed the uikit/f1-bottom-sheet-content-min-height branch from 9bfb74a to 982a837 Compare October 26, 2026 22:30
@github-actions github-actions Bot removed the needs:spec-owner-review Current knowledge records await owner approval label Oct 26, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommending approval: switching the BottomSheet content box to min-height: fit-content keeps its bottom padding inside the scroll range of a set-height sheet with direct content in WebKit (0 px to 16 px at the scroll end), with no change in Chromium. The new scroll-end guard fails on the base in WebKit and passes on this head, and the dialog-host and Safari-wording points raised on the earlier revision are resolved. Firefox 151 still ends such a sheet flush, unchanged from main and outside this fix.

[Automated review]

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 Storybook Preview

View Storybook for this PR

🧪 Sandbox Preview

View Sandbox for this PR

Component Size

Component Import before Import after Delta CSS before CSS after Delta
core/BottomSheet 26.0KB 26.0KB 0B 7.7KB 7.7KB -2B
core/BottomSheetSwitcher 9.2KB 9.2KB 0B 3.3KB 3.3KB 0B
core/ContextMenu 77.3KB 77.3KB 0B 14.5KB 14.5KB -2B
core/DateInput 92.5KB 92.5KB +1B 14.6KB 14.6KB -3B
core/DateTimeInput 102.6KB 102.6KB +1B 15.1KB 15.1KB -3B
core/DropdownMenu 72.2KB 72.2KB -1B 14.6KB 14.6KB -3B
core/Markdown 143.9KB 143.9KB 0B 17.2KB 17.2KB -2B
core/MoreMenu 72.5KB 72.5KB -1B 14.6KB 14.6KB -3B
core/MultiSelector 75.7KB 75.7KB 0B 14.5KB 14.5KB 0B
core/Pagination 87.3KB 87.3KB 0B 15.2KB 15.2KB -1B
core/Popover 49.8KB 49.8KB +1B 12.0KB 11.9KB -3B
core/PowerSearch 147.7KB 147.7KB -1B 18.5KB 18.5KB -1B
core/Selector 78.7KB 78.7KB 0B 14.8KB 14.8KB -1B
core/Table 83.5KB 83.5KB -1B 15.0KB 15.0KB -2B
core/TableCell 78.4KB 78.4KB +1B 14.6KB 14.6KB -1B
core/TableHeaderCell 78.1KB 78.1KB +1B 14.6KB 14.6KB -1B
core/TimeInput 79.3KB 79.3KB 0B 13.6KB 13.6KB -3B

Sizes are gzip. Import counts the JavaScript the import loads eagerly; CSS counts the package stylesheet rules referenced by the modules it can load from its own package, lazily loaded ones included.

Bundle Size Summary

Gzip figures measure each package's entry file, not the code an import pulls in.

Package Entry (ESM) Entry gzip before Entry gzip after Delta
@astryxdesign/core 4.9KB 1.2KB 1.2KB 0B
Package stylesheet Gzip before Gzip after Delta
@astryxdesign/core 34.3KB 34.3KB 0B

Accessibility Audit

Status: No accessibility violations detected.

Visual Regression

55 of 502 shot(s) changed.

A change here is a question, not a failure: check whether the after is the
picture you intended. Record that review on the PR. Baseline maintenance is an
explicit dispatch of CI; this report never rewrites the baseline or adds a release gate.

component story theme mode pixels
Selector Indicator Space Bottom Sheet Narrow End RTL neutral light 753,933
Selector Indicator Space Bottom Sheet Wide Start neutral light 740,072
RichTextEditor Markdown parity: side by side probe dark 558,840
RichTextEditor Markdown parity: side by side probe light 540,756
Chat Full AI Chat probe light 230,823
Chat Full AI Chat probe dark 229,805
AppShell With Mobile Nav probe light 217,010
AppShell With Mobile Nav probe dark 216,960
Collapsible Dividers probe dark 66,445
Collapsible Dividers probe light 66,445
AppShell Playground neutral dark 65,198
AppShell Playground neutral light 63,788
Chat Default neutral dark 36,304
Chat Default neutral light 35,767
Chat Empty State probe light 23,531
Chat Empty State probe dark 22,622
ChatAutoScroll Scroll Behavior Comparison neutral dark 15,378
ChatAutoScroll Scroll Behavior Comparison neutral light 14,107
Chat With Attachments probe light 13,406
Chat With Attachments probe dark 11,232

and 35 more.


Generated by PR Enrichment workflow | Storybook | Sandbox | View full report

@cixzhang

Copy link
Copy Markdown
Contributor

Posted by Cindy's agent on her behalf: closed and reopened only to restart this PR's CI on the current workflow after tonight's queue-wide cancel; nothing in the PR changed.

@vjeux
vjeux marked this pull request as draft October 29, 2026 22:37

This branch was successfully deployed

1 active deployment
Preview — 982a8379 Deployed Oct 26, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot. needs:design-review Affects visuals — Design should review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants