freya_components/scroll_views/
scroll_bar.rs1use dioxus::prelude::*;
2use freya_elements::{
3 self as dioxus_elements,
4};
5use freya_hooks::{
6 use_applied_theme,
7 ScrollBarTheme,
8 ScrollBarThemeWith,
9};
10
11#[derive(Props, Clone, PartialEq)]
13pub struct ScrollBarProps {
14 pub theme: Option<ScrollBarThemeWith>,
16 pub children: Element,
17 #[props(into)]
18 pub size: String,
19 #[props(default = 0., into)]
20 pub offset_x: f32,
21 #[props(default = 0., into)]
22 pub offset_y: f32,
23 pub clicking_scrollbar: bool,
24 #[props(default = false)]
25 pub is_vertical: bool,
26}
27
28#[derive(Clone, Copy, PartialEq, Debug)]
29enum ScrollBarState {
30 Idle,
31 Hovering,
32}
33
34#[allow(non_snake_case)]
36pub fn ScrollBar(
37 ScrollBarProps {
38 size,
39 clicking_scrollbar,
40 offset_x: inner_offset_x,
41 offset_y: inner_offset_y,
42 theme,
43 children,
44 is_vertical,
45 }: ScrollBarProps,
46) -> Element {
47 let mut status = use_signal(|| ScrollBarState::Idle);
48 let ScrollBarTheme { background, .. } = use_applied_theme!(&theme, scroll_bar);
49
50 let onmouseenter = move |_| status.set(ScrollBarState::Hovering);
51 let onmouseleave = move |_| status.set(ScrollBarState::Idle);
52
53 let (inner_size, opacity) = match *status.read() {
54 _ if clicking_scrollbar => (size.as_str(), 225.),
55 ScrollBarState::Idle => ("5", 0.),
56 ScrollBarState::Hovering => (size.as_str(), 225.),
57 };
58
59 let (offset_x, offset_y, width, height, inner_width, inner_height) = if is_vertical {
60 (
61 size.as_str(),
62 "0",
63 size.as_str(),
64 "fill",
65 inner_size,
66 "auto",
67 )
68 } else {
69 (
70 "0",
71 size.as_str(),
72 "fill",
73 size.as_str(),
74 "auto",
75 inner_size,
76 )
77 };
78
79 rsx!(
80 rect {
81 width,
82 height,
83 layer: "-999",
84 offset_x: "-{offset_x}",
85 offset_y: "-{offset_y}",
86 rect {
87 onmouseenter,
88 onmouseleave,
89 a11y_role: "scroll-bar",
90 width: "fill",
91 height: "fill",
92 background: "{background}",
93 background_opacity: "{opacity}",
94 direction: if is_vertical { "vertical" } else { "horizontal" },
95 cross_align: "end",
96 rect {
97 width: inner_width,
98 height: inner_height,
99 offset_x: "{inner_offset_x}",
100 offset_y: "{inner_offset_y}",
101 {children}
102 }
103 }
104 }
105 )
106}