editor: Implement hover color for scrollbars (#28064)

This PR adds hover colors to the editor scrollbars:


https://github.com/user-attachments/assets/6600810e-7e8e-4dee-9bef-b7be303b5fe0

The color used here is the existing `scrollbar_thumb_hover_background`
color provided by themes.

Looking forward to feedback 😄 

Release Notes:

- Added hover state to editor scrollbars.
This commit is contained in:
Finn Evers 2025-05-06 09:17:43 +02:00 committed by GitHub
parent 55a0bb2a91
commit 3b90d62bb2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 109 additions and 25 deletions

View file

@ -123,6 +123,29 @@ impl OngoingScroll {
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum ScrollbarThumbState {
Idle,
Hovered,
Dragging,
}
#[derive(PartialEq, Eq)]
pub struct ActiveScrollbarState {
axis: Axis,
thumb_state: ScrollbarThumbState,
}
impl ActiveScrollbarState {
pub fn new(axis: Axis, thumb_state: ScrollbarThumbState) -> Self {
ActiveScrollbarState { axis, thumb_state }
}
pub fn thumb_state_for_axis(&self, axis: Axis) -> Option<ScrollbarThumbState> {
(self.axis == axis).then_some(self.thumb_state)
}
}
pub struct ScrollManager {
pub(crate) vertical_scroll_margin: f32,
anchor: ScrollAnchor,
@ -131,7 +154,7 @@ pub struct ScrollManager {
last_autoscroll: Option<(gpui::Point<f32>, f32, f32, AutoscrollStrategy)>,
show_scrollbars: bool,
hide_scrollbar_task: Option<Task<()>>,
dragging_scrollbar: Option<Axis>,
active_scrollbar: Option<ActiveScrollbarState>,
visible_line_count: Option<f32>,
forbid_vertical_scroll: bool,
}
@ -145,7 +168,7 @@ impl ScrollManager {
autoscroll_request: None,
show_scrollbars: true,
hide_scrollbar_task: None,
dragging_scrollbar: None,
active_scrollbar: None,
last_autoscroll: None,
visible_line_count: None,
forbid_vertical_scroll: false,
@ -322,24 +345,53 @@ impl ScrollManager {
self.autoscroll_request.map(|(autoscroll, _)| autoscroll)
}
pub fn active_scrollbar_state(&self) -> Option<&ActiveScrollbarState> {
self.active_scrollbar.as_ref()
}
pub fn dragging_scrollbar_axis(&self) -> Option<Axis> {
self.dragging_scrollbar
self.active_scrollbar
.as_ref()
.map(|scrollbar| scrollbar.axis)
}
pub fn any_scrollbar_dragged(&self) -> bool {
self.dragging_scrollbar.is_some()
self.active_scrollbar
.as_ref()
.is_some_and(|scrollbar| scrollbar.thumb_state == ScrollbarThumbState::Dragging)
}
pub fn set_dragged_scrollbar_axis(&mut self, axis: Axis, cx: &mut Context<Editor>) {
if self.dragging_scrollbar != Some(axis) {
self.dragging_scrollbar = Some(axis);
cx.notify();
}
pub fn set_hovered_scroll_thumb_axis(&mut self, axis: Axis, cx: &mut Context<Editor>) {
self.update_active_scrollbar_state(
Some(ActiveScrollbarState::new(
axis,
ScrollbarThumbState::Hovered,
)),
cx,
);
}
pub fn reset_scrollbar_dragging_state(&mut self, cx: &mut Context<Editor>) {
if self.dragging_scrollbar.is_some() {
self.dragging_scrollbar = None;
pub fn set_dragged_scroll_thumb_axis(&mut self, axis: Axis, cx: &mut Context<Editor>) {
self.update_active_scrollbar_state(
Some(ActiveScrollbarState::new(
axis,
ScrollbarThumbState::Dragging,
)),
cx,
);
}
pub fn reset_scrollbar_state(&mut self, cx: &mut Context<Editor>) {
self.update_active_scrollbar_state(None, cx);
}
fn update_active_scrollbar_state(
&mut self,
new_state: Option<ActiveScrollbarState>,
cx: &mut Context<Editor>,
) {
if self.active_scrollbar != new_state {
self.active_scrollbar = new_state;
cx.notify();
}
}