editor: Minimum scroll thumb size (#25162)

Closes #22610

This PR fixes the invisible scroll thumb or very tiny scroll thumb when
viewing long or wide files.

The difference between `track_bounds` (imagine scrollbar total height)
and `thumb_size` is the remaining area, which maps to the total height
of the page for scrolling to work as expected. This is already accounted
for. That means we can adjust the thumb size as needed, and the
remaining height/width will be mapped correctly.

So, we can simply use define a minimum size for the thumb and handle
cases where the track bounds are smaller than the defined minimum size.
In such cases, the scrollbar will take up the full height/width of the
track bounds. This is handled mainly to avoid panics in extreme edge
cases. Practically, at such small heights/widths, users are unlikely to
attempt scrolling.

Before:


https://github.com/user-attachments/assets/cf2edf03-8b9a-4678-b3c6-9dcbd01e5db8

After:


https://github.com/user-attachments/assets/e9496a44-3e7d-4be7-b892-2762cccd9959

Release Notes:

- Fixed issue where scroll thumb was invisible or too small when viewing
long or wide files.
This commit is contained in:
smit 2025-02-19 21:14:54 +05:30 committed by GitHub
parent 486e106205
commit 686978d7c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -79,6 +79,7 @@ use util::{RangeExt, ResultExt};
use workspace::{item::Item, notifications::NotifyTaskExt, Workspace};
const INLINE_BLAME_PADDING_EM_WIDTHS: f32 = 7.;
const MIN_SCROLL_THUMB_SIZE: f32 = 25.;
#[derive(Debug, Clone, PartialEq, Eq)]
enum DisplayDiffHunk {
@ -1383,17 +1384,21 @@ impl EditorElement {
if text_units_per_page.horizontal >= total_text_units_x {
return None;
}
let thumb_percent =
(text_units_per_page.horizontal / total_text_units_x).min(1.);
Some(track_bounds_x.size.width * thumb_percent)
if track_bounds_x.size.width < px(MIN_SCROLL_THUMB_SIZE) {
return Some(track_bounds_x.size.width);
}
let thumb_size = track_bounds_x.size.width
* (text_units_per_page.horizontal / total_text_units_x);
Some(thumb_size.clamp(px(MIN_SCROLL_THUMB_SIZE), track_bounds_x.size.width))
}),
total_text_units.vertical.zip(track_bounds.vertical).map(
|(total_text_units_y, track_bounds_y)| {
let thumb_percent = (text_units_per_page.vertical / total_text_units_y).min(1.);
track_bounds_y.size.height * thumb_percent
if track_bounds_y.size.height < px(MIN_SCROLL_THUMB_SIZE) {
return track_bounds_y.size.height;
}
let thumb_size = track_bounds_y.size.height
* (text_units_per_page.vertical / total_text_units_y);
thumb_size.clamp(px(MIN_SCROLL_THUMB_SIZE), track_bounds_y.size.height)
},
),
);