From fca54dec2c2a4c948c4ddc9df0d47be20cc3684d Mon Sep 17 00:00:00 2001 From: lucasmerlin Date: Sun, 10 May 2026 01:50:37 +0200 Subject: [PATCH] Only paint scroll fade on enabled axes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `paint_fade_areas` previously checked overflow on both axes regardless of which directions were scroll-enabled. A horizontal-only ScrollArea with non-zero overflow.y (which can happen when the inner ui's content height differs from `inner_rect.size().y` for any reason) would draw permanent top/bottom fades — visible as a stripe through the content that never goes away because there's no way to scroll it off. Gate the top/bottom fades behind `direction_enabled.y` and the left/right fades behind `direction_enabled.x`. The ScrollArea already owns this state; pass it through `show_viewport_dyn`. --- crates/egui/src/containers/scroll_area.rs | 129 ++++++++++++---------- 1 file changed, 69 insertions(+), 60 deletions(-) diff --git a/crates/egui/src/containers/scroll_area.rs b/crates/egui/src/containers/scroll_area.rs index b99bcf5da..648c83ee6 100644 --- a/crates/egui/src/containers/scroll_area.rs +++ b/crates/egui/src/containers/scroll_area.rs @@ -1006,6 +1006,7 @@ impl ScrollArea { let margin = self .content_margin .unwrap_or_else(|| ui.spacing().scroll.content_margin); + let direction_enabled = self.direction_enabled; let mut prepared = self.begin(ui); let id = prepared.id; @@ -1027,7 +1028,7 @@ impl ScrollArea { inner_rect, }; - paint_fade_areas(ui, &output); + paint_fade_areas(ui, &output, direction_enabled); output } @@ -1509,9 +1510,13 @@ impl Prepared { } } -/// Paint fade-out gradients at the top and/or bottom of a scroll area to +/// Paint fade-out gradients at the edges of a scroll area to /// indicate that more content is available beyond the visible region. -fn paint_fade_areas(ui: &Ui, scroll_output: &ScrollAreaOutput) { +/// +/// Only fades for axes where scrolling is enabled — otherwise stray overflow +/// in a non-scrollable axis would draw a permanent fade with nothing to scroll +/// away to. +fn paint_fade_areas(ui: &Ui, scroll_output: &ScrollAreaOutput, direction_enabled: Vec2b) { let crate::style::ScrollFadeStyle { strength, size: fade_size, @@ -1531,65 +1536,69 @@ fn paint_fade_areas(ui: &Ui, scroll_output: &ScrollAreaOutput) { .intersect(ui.min_rect()) .expand(ui.visuals().clip_rect_margin); - // Top fade: animate opacity based on how far we've scrolled down. - if 0.0 < offset.y { - let t = (offset.y / fade_size).clamp(0.0, 1.0) * strength; - let bg_faded = bg.gamma_multiply(t); - let rect = Rect::from_min_max( - paint_rect.left_top(), - pos2(paint_rect.right(), paint_rect.top() + fade_size), - ); - ui.painter().add(Shape::gradient_rect( - rect, - Direction::TopDown, - [bg_faded, Color32::TRANSPARENT], - )); + if direction_enabled.y { + // Top fade: animate opacity based on how far we've scrolled down. + if 0.0 < offset.y { + let t = (offset.y / fade_size).clamp(0.0, 1.0) * strength; + let bg_faded = bg.gamma_multiply(t); + let rect = Rect::from_min_max( + paint_rect.left_top(), + pos2(paint_rect.right(), paint_rect.top() + fade_size), + ); + ui.painter().add(Shape::gradient_rect( + rect, + Direction::TopDown, + [bg_faded, Color32::TRANSPARENT], + )); + } + + // Bottom fade: animate opacity based on distance from the bottom. + let distance_from_bottom = overflow.y - offset.y; + if 0.0 < distance_from_bottom { + let t = (distance_from_bottom / fade_size).clamp(0.0, 1.0) * strength; + let bg_faded = bg.gamma_multiply(t); + let rect = Rect::from_min_max( + pos2(paint_rect.left(), paint_rect.bottom() - fade_size), + paint_rect.right_bottom(), + ); + ui.painter().add(Shape::gradient_rect( + rect, + Direction::BottomUp, + [bg_faded, Color32::TRANSPARENT], + )); + } } - // Bottom fade: animate opacity based on distance from the bottom. - let distance_from_bottom = overflow.y - offset.y; - if 0.0 < distance_from_bottom { - let t = (distance_from_bottom / fade_size).clamp(0.0, 1.0) * strength; - let bg_faded = bg.gamma_multiply(t); - let rect = Rect::from_min_max( - pos2(paint_rect.left(), paint_rect.bottom() - fade_size), - paint_rect.right_bottom(), - ); - ui.painter().add(Shape::gradient_rect( - rect, - Direction::BottomUp, - [bg_faded, Color32::TRANSPARENT], - )); - } + if direction_enabled.x { + // Left fade: animate opacity based on how far we've scrolled right. + if 0.0 < offset.x { + let t = (offset.x / fade_size).clamp(0.0, 1.0) * strength; + let bg_faded = bg.gamma_multiply(t); + let rect = Rect::from_min_max( + paint_rect.left_top(), + pos2(paint_rect.left() + fade_size, paint_rect.bottom()), + ); + ui.painter().add(Shape::gradient_rect( + rect, + Direction::LeftToRight, + [bg_faded, Color32::TRANSPARENT], + )); + } - // Left fade: animate opacity based on how far we've scrolled right. - if 0.0 < offset.x { - let t = (offset.x / fade_size).clamp(0.0, 1.0) * strength; - let bg_faded = bg.gamma_multiply(t); - let rect = Rect::from_min_max( - paint_rect.left_top(), - pos2(paint_rect.left() + fade_size, paint_rect.bottom()), - ); - ui.painter().add(Shape::gradient_rect( - rect, - Direction::LeftToRight, - [bg_faded, Color32::TRANSPARENT], - )); - } - - // Right fade: animate opacity based on distance from the right edge. - let distance_from_right = overflow.x - offset.x; - if 0.0 < distance_from_right { - let t = (distance_from_right / fade_size).clamp(0.0, 1.0) * strength; - let bg_faded = bg.gamma_multiply(t); - let rect = Rect::from_min_max( - pos2(paint_rect.right() - fade_size, paint_rect.top()), - paint_rect.right_bottom(), - ); - ui.painter().add(Shape::gradient_rect( - rect, - Direction::RightToLeft, - [bg_faded, Color32::TRANSPARENT], - )); + // Right fade: animate opacity based on distance from the right edge. + let distance_from_right = overflow.x - offset.x; + if 0.0 < distance_from_right { + let t = (distance_from_right / fade_size).clamp(0.0, 1.0) * strength; + let bg_faded = bg.gamma_multiply(t); + let rect = Rect::from_min_max( + pos2(paint_rect.right() - fade_size, paint_rect.top()), + paint_rect.right_bottom(), + ); + ui.painter().add(Shape::gradient_rect( + rect, + Direction::RightToLeft, + [bg_faded, Color32::TRANSPARENT], + )); + } } }