Skip to content

Commit

Permalink
feat: Add hover and active effects for the scrollbar thumbs (#333)
Browse files Browse the repository at this point in the history
  • Loading branch information
marc2332 authored Oct 16, 2023
1 parent c128ca5 commit ebfa9cc
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 10 deletions.
26 changes: 22 additions & 4 deletions crates/components/src/scroll_views/scroll_thumb.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,44 @@
use dioxus::prelude::*;
use freya_elements::elements as dioxus_elements;
use freya_elements::events::MouseEvent;
use freya_hooks::{use_get_theme, ScrollbarTheme};
use freya_hooks::use_get_theme;

#[derive(Props)]
pub struct ScrollThumbProps<'a> {
clicking_scrollbar: bool,
onmousedown: EventHandler<'a, MouseEvent>,
#[props(into)]
width: String,
#[props(into)]
height: String,
}

#[derive(Debug, Default, PartialEq, Clone, Copy)]
pub enum ScrollThumbState {
#[default]
Idle,
// Thumb is being hovered
Hovering,
}

#[allow(non_snake_case)]
pub fn ScrollThumb<'a>(cx: Scope<'a, ScrollThumbProps<'a>>) -> Element<'a> {
let theme = use_get_theme(cx);
let ScrollbarTheme {
thumb_background, ..
} = &theme.scrollbar;
let state = use_state(cx, ScrollThumbState::default);
let thumb_background = match state.get() {
_ if cx.props.clicking_scrollbar => theme.scrollbar.active_thumb_background,
ScrollThumbState::Idle => theme.scrollbar.thumb_background,
ScrollThumbState::Hovering => theme.scrollbar.hover_thumb_background,
};

render!(
rect {
onmouseenter: |_| {
state.set(ScrollThumbState::Hovering)
},
onmouseleave: |_| {
state.set(ScrollThumbState::Idle)
},
onmousedown: |e| {
cx.props.onmousedown.call(e);
},
Expand Down
21 changes: 18 additions & 3 deletions crates/components/src/scroll_views/scroll_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,18 +227,20 @@ pub fn ScrollView<'a>(cx: Scope<'a, ScrollViewProps<'a>>) -> Element {
// Mark the Y axis scrollbar as the one being dragged
let onmousedown_y = |e: MouseEvent| {
let coordinates = e.get_element_coordinates();
*clicking_scrollbar.write_silent() = Some((Axis::Y, coordinates.y));
*clicking_scrollbar.write() = Some((Axis::Y, coordinates.y));
};

// Mark the X axis scrollbar as the one being dragged
let onmousedown_x = |e: MouseEvent| {
let coordinates = e.get_element_coordinates();
*clicking_scrollbar.write_silent() = Some((Axis::X, coordinates.x));
*clicking_scrollbar.write() = Some((Axis::X, coordinates.x));
};

// Unmark any scrollbar
let onclick = |_: MouseEvent| {
*clicking_scrollbar.write_silent() = None;
if clicking_scrollbar.read().is_some() {
*clicking_scrollbar.write() = None;
}
};

let horizontal_scrollbar_size = if horizontal_scrollbar_is_visible {
Expand All @@ -252,6 +254,17 @@ pub fn ScrollView<'a>(cx: Scope<'a, ScrollViewProps<'a>>) -> Element {
0
};

let is_scrolling_x = clicking_scrollbar
.read()
.as_ref()
.map(|f| f.0 == Axis::X)
.unwrap_or_default();
let is_scrolling_y = clicking_scrollbar
.read()
.as_ref()
.map(|f| f.0 == Axis::Y)
.unwrap_or_default();

render!(
rect {
role: "scrollView",
Expand Down Expand Up @@ -284,6 +297,7 @@ pub fn ScrollView<'a>(cx: Scope<'a, ScrollViewProps<'a>>) -> Element {
height: "{horizontal_scrollbar_size}",
offset_x: "{scrollbar_x}",
ScrollThumb {
clicking_scrollbar: is_scrolling_x,
onmousedown: onmousedown_x,
width: "{scrollbar_width}",
height: "100%",
Expand All @@ -295,6 +309,7 @@ pub fn ScrollView<'a>(cx: Scope<'a, ScrollViewProps<'a>>) -> Element {
height: "100%",
offset_y: "{scrollbar_y}",
ScrollThumb {
clicking_scrollbar: is_scrolling_y,
onmousedown: onmousedown_y,
width: "100%",
height: "{scrollbar_height}",
Expand Down
21 changes: 18 additions & 3 deletions crates/components/src/scroll_views/virtual_scroll_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,18 +262,20 @@ pub fn VirtualScrollView<'a, T>(cx: Scope<'a, VirtualScrollViewProps<'a, T>>) ->
// Mark the Y axis scrollbar as the one being dragged
let onmousedown_y = |e: MouseEvent| {
let coordinates = e.get_element_coordinates();
*clicking_scrollbar.write_silent() = Some((Axis::Y, coordinates.y));
*clicking_scrollbar.write() = Some((Axis::Y, coordinates.y));
};

// Mark the X axis scrollbar as the one being dragged
let onmousedown_x = |e: MouseEvent| {
let coordinates = e.get_element_coordinates();
*clicking_scrollbar.write_silent() = Some((Axis::X, coordinates.x));
*clicking_scrollbar.write() = Some((Axis::X, coordinates.x));
};

// Unmark any scrollbar
let onclick = |_: MouseEvent| {
*clicking_scrollbar.write_silent() = None;
if clicking_scrollbar.read().is_some() {
*clicking_scrollbar.write() = None;
}
};

let horizontal_scrollbar_size = if horizontal_scrollbar_is_visible {
Expand Down Expand Up @@ -305,6 +307,17 @@ pub fn VirtualScrollView<'a, T>(cx: Scope<'a, VirtualScrollViewProps<'a, T>>) ->
let children =
render_range.map(|i| (cx.props.builder)((i + 1, i, cx, &cx.props.builder_values)));

let is_scrolling_x = clicking_scrollbar
.read()
.as_ref()
.map(|f| f.0 == Axis::X)
.unwrap_or_default();
let is_scrolling_y = clicking_scrollbar
.read()
.as_ref()
.map(|f| f.0 == Axis::Y)
.unwrap_or_default();

render!(
rect {
role: "scrollView",
Expand Down Expand Up @@ -335,6 +348,7 @@ pub fn VirtualScrollView<'a, T>(cx: Scope<'a, VirtualScrollViewProps<'a, T>>) ->
height: "{horizontal_scrollbar_size}",
offset_x: "{scrollbar_x}",
ScrollThumb {
clicking_scrollbar: is_scrolling_x,
onmousedown: onmousedown_x,
width: "{scrollbar_width}",
height: "100%",
Expand All @@ -346,6 +360,7 @@ pub fn VirtualScrollView<'a, T>(cx: Scope<'a, VirtualScrollViewProps<'a, T>>) ->
height: "100%",
offset_y: "{scrollbar_y}",
ScrollThumb {
clicking_scrollbar: is_scrolling_y,
onmousedown: onmousedown_y,
width: "100%",
height: "{scrollbar_height}",
Expand Down
6 changes: 6 additions & 0 deletions crates/hooks/src/use_theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub struct SwitchTheme {
pub struct ScrollbarTheme {
pub background: &'static str,
pub thumb_background: &'static str,
pub hover_thumb_background: &'static str,
pub active_thumb_background: &'static str,
}

/// Theming properties for the App body.
Expand Down Expand Up @@ -175,6 +177,8 @@ pub const LIGHT_THEME: Theme = Theme {
scrollbar: ScrollbarTheme {
background: "rgb(225, 225, 225)",
thumb_background: "rgb(135, 135, 135)",
hover_thumb_background: "rgb(115, 115, 115)",
active_thumb_background: "rgb(95, 95, 95)",
},
tooltip: TooltipTheme {
background: "rgb(230,230,230)",
Expand Down Expand Up @@ -240,6 +244,8 @@ pub const DARK_THEME: Theme = Theme {
scrollbar: ScrollbarTheme {
background: "rgb(35, 35, 35)",
thumb_background: "rgb(100, 100, 100)",
hover_thumb_background: "rgb(120, 120, 120)",
active_thumb_background: "rgb(140, 140, 140)",
},
tooltip: TooltipTheme {
background: "rgb(35,35,35)",
Expand Down

0 comments on commit ebfa9cc

Please sign in to comment.