Skip to content

scroll: Scroll content past a scrollable's maximum size - #3613

Open
UncertaintyDeterminesYou4ndMe wants to merge 1 commit into
longbridge:mainfrom
UncertaintyDeterminesYou4ndMe:scrollable-max-size
Open

UncertaintyDeterminesYou4ndMe wants to merge 1 commit into
longbridge:mainfrom
UncertaintyDeterminesYou4ndMe:scrollable-max-size

Conversation

@UncertaintyDeterminesYou4ndMe

Copy link
Copy Markdown
Contributor

Description

An element with a maximum size along the axis it scrolls does not scroll: under v_flex().max_h(px(320.)).overflow_y_scrollbar(), the rows past 320px are clipped and cannot be reached. Both copies of Scrollable, in gpui-component and in gpui-shell, have the code involved; this changes both.

Scrollable wraps the element. The wrapper copies its size, minimum size and maximum size, and the element becomes the content of a scroll area inside the wrapper. Two things keep such an element from scrolling:

  • The content keeps the maximum size as well, so it is never larger than the area and nothing overflows. The content now drops the maximum size on the scrolled axis; the wrapper still applies it.
  • With GPUI Fast, the area's size_full(), 100% of the wrapper, does not hold it to the wrapper's maximum size. In a column whose height follows its content, placed in a row, the area comes out as tall as the inside of that column (140px for a 100px maximum between two 20px blocks), and the wrapper clips it. With the default GPUI the area already gets the wrapper's 100px; the two use different Taffy versions (0.14 and 0.13). The wrapper is now a flex container along the scrolled axis, so the area is a flex item and shrinks to the wrapper's size with either. Where the wrapper's size is fixed or comes from its parent, as with flex_1() or size_full(), the area keeps the size it had.

ScrollBounce takes the layout of the area it wraps, and ScrollableMask is absolutely positioned, so neither becomes a second flex item. With both axes (overflow_scrollbar()) the wrapper is a column, so only the area's height is held to the wrapper's maximum this way.

Found in a form whose fields sit under max_h(320).overflow_y_scrollbar() inside a card.

How to Test

cargo test -p gpui-component --lib -- scroll::scrollable
cargo test -p gpui-component --features gpui-fast,test-support --lib -- scroll::scrollable
cargo test -p gpui-shell --release --lib -- scroll::tests

max_height_scrollable_scrolls_to_its_last_row (gpui-component) and scrollable_with_a_max_height_scrolls_what_overflows_it (gpui-shell) lay out the column described above and scroll it to its last row. max_width_scrollable_scrolls_what_overflows_it and scrollable_with_a_max_width_scrolls_what_overflows_it scroll a row with a maximum width. Without the first change all four fail. Without the flex wrapper the two max-height tests fail with GPUI Fast (gpui-shell uses it by default): the last row ends 140px below the first row's top instead of 100px. With the default GPUI they pass either way. The gpui-shell flex-item test now also scrolls to its last row; it passes before and after the change.

AI-assisted: written with Claude Code and reviewed by me before submission.

Checklist

  • I have read the CONTRIBUTING document and followed the guidelines.
  • Reviewed the changes in this PR and confirmed AI generated code (If any) is accurate.
  • Passed cargo run for story tests related to the changes. (Not run; the tests above cover the layout.)
  • Tested macOS, Windows and Linux platforms performance (if the change is platform-specific). (Not platform-specific.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant