Skip to content
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

gpui: Add restrict_scroll_to_axis to match web scrolling behavior #25963

Merged
merged 1 commit into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions crates/gpui/src/elements/div.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2127,6 +2127,7 @@ impl Interactivity {
if let Some(scroll_offset) = self.scroll_offset.clone() {
let overflow = style.overflow;
let allow_concurrent_scroll = style.allow_concurrent_scroll;
let restrict_scroll_to_axis = style.restrict_scroll_to_axis;
let line_height = window.line_height();
let hitbox = hitbox.clone();
window.on_mouse_event(move |event: &ScrollWheelEvent, phase, window, cx| {
Expand All @@ -2139,15 +2140,15 @@ impl Interactivity {
if overflow.x == Overflow::Scroll {
if !delta.x.is_zero() {
delta_x = delta.x;
} else if overflow.y != Overflow::Scroll {
} else if !restrict_scroll_to_axis && overflow.y != Overflow::Scroll {
delta_x = delta.y;
}
}
let mut delta_y = Pixels::ZERO;
if overflow.y == Overflow::Scroll {
if !delta.y.is_zero() {
delta_y = delta.y;
} else if overflow.x != Overflow::Scroll {
} else if !restrict_scroll_to_axis && overflow.x != Overflow::Scroll {
delta_y = delta.x;
}
}
Expand Down
23 changes: 23 additions & 0 deletions crates/gpui/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,28 @@ pub struct Style {
pub scrollbar_width: f32,
/// Whether both x and y axis should be scrollable at the same time.
pub allow_concurrent_scroll: bool,
/// Whether scrolling should be restricted to the axis indicated by the mouse wheel.
///
/// This means that:
/// - The mouse wheel alone will only ever scroll the Y axis.
/// - Holding `Shift` and using the mouse wheel will scroll the X axis.
///
/// ## Motivation
///
/// On the web when scrolling with the mouse wheel, scrolling up and down will always scroll the Y axis, even when
/// the mouse is over a horizontally-scrollable element.
///
/// The only way to scroll horizontally is to hold down `Shift` while scrolling, which then changes the scroll axis
/// to the X axis.
///
/// Currently, GPUI operates differently from the web in that it will scroll an element in either the X or Y axis
/// when scrolling with just the mouse wheel. This causes problems when scrolling in a vertical list that contains
/// horizontally-scrollable elements, as when you get to the horizontally-scrollable elements the scroll will be
/// hijacked.
///
/// Ideally we would match the web's behavior and not have a need for this, but right now we're adding this opt-in
/// style property to limit the potential blast radius.
pub restrict_scroll_to_axis: bool,

// Position properties
/// What should the `position` value of this struct use as a base offset?
Expand Down Expand Up @@ -702,6 +724,7 @@ impl Default for Style {
y: Overflow::Visible,
},
allow_concurrent_scroll: false,
restrict_scroll_to_axis: false,
scrollbar_width: 0.0,
position: Position::Relative,
inset: Edges::auto(),
Expand Down
Loading