Skip to content

Commit

Permalink
feat: Scroll controller (#772)
Browse files Browse the repository at this point in the history
* feat: Scroll controller

* clean up and support virtual scroll view

* feat: scroll_to

* clean up

* docs

* test
  • Loading branch information
marc2332 authored Jul 14, 2024
1 parent 9ffa035 commit 1cd1d2c
Show file tree
Hide file tree
Showing 5 changed files with 454 additions and 12 deletions.
2 changes: 2 additions & 0 deletions crates/components/src/scroll_views/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod scroll_bar;
mod scroll_thumb;
mod scroll_view;
mod use_scroll_controller;
mod virtual_scroll_view;

use freya_elements::events::{
Expand All @@ -10,6 +11,7 @@ use freya_elements::events::{
pub use scroll_bar::*;
pub use scroll_thumb::*;
pub use scroll_view::*;
pub use use_scroll_controller::*;
pub use virtual_scroll_view::*;

// Holding alt while scrolling makes it 5x faster (VSCode behavior).
Expand Down
65 changes: 56 additions & 9 deletions crates/components/src/scroll_views/scroll_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use freya_hooks::{
ScrollViewThemeWith,
};

use super::use_scroll_controller::ScrollController;
use crate::{
get_container_size,
get_corrected_scroll_position,
Expand All @@ -24,6 +25,10 @@ use crate::{
get_scrollbar_pos_and_size,
is_scrollbar_visible,
manage_key_event,
scroll_views::use_scroll_controller::{
use_scroll_controller,
ScrollConfig,
},
Axis,
ScrollBar,
ScrollThumb,
Expand All @@ -48,6 +53,8 @@ pub struct ScrollViewProps {
/// Enable scrolling with arrow keys.
#[props(default = true, into)]
pub scroll_with_arrows: bool,

pub scroll_controller: Option<ScrollController>,
}

/// Scrollable area with bidirectional support and scrollbars.
Expand All @@ -59,28 +66,66 @@ pub struct ScrollViewProps {
/// fn app() -> Element {
/// rsx!(
/// ScrollView {
/// theme: theme_with!(ScrollViewTheme {
/// width: "100%".into(),
/// height: "300".into(),
/// }),
/// show_scrollbar: true,
/// rect {
/// rect {
/// background: "blue",
/// height: "500",
/// height: "400",
/// width: "100%"
/// }
/// rect {
/// background: "red",
/// height: "400",
/// width: "100%"
/// }
/// }
/// )
/// }
/// ```
///
/// # With a Scroll Controller
///
/// ```no_run
/// # use freya::prelude::*;
/// fn app() -> Element {
/// let mut scroll_controller = use_scroll_controller(|| ScrollConfig::default());
///
/// rsx!(
/// ScrollView {
/// scroll_controller,
/// rect {
/// background: "blue",
/// height: "400",
/// width: "100%"
/// }
/// Button {
/// label {
/// onclick: move |_| {
/// scroll_controller.scroll_to(ScrollPosition::Start, ScrollDirection::Vertical);
/// },
/// label {
/// "Scroll up"
/// }
/// }
/// }
/// rect {
/// background: "red",
/// height: "400",
/// width: "100%"
/// }
/// }
/// )
/// }
/// ```
#[allow(non_snake_case)]
pub fn ScrollView(props: ScrollViewProps) -> Element {
let mut clicking_scrollbar = use_signal::<Option<(Axis, f64)>>(|| None);
let mut clicking_shift = use_signal(|| false);
let mut clicking_alt = use_signal(|| false);
let mut scrolled_y = use_signal(|| 0);
let mut scrolled_x = use_signal(|| 0);
let mut scroll_controller = props
.scroll_controller
.unwrap_or_else(|| use_scroll_controller(ScrollConfig::default));
let (mut scrolled_x, mut scrolled_y) = scroll_controller.into();
let (node_ref, size) = use_node();

let mut focus = use_focus();
let theme = use_applied_theme!(&props.theme, scroll_view);
let scrollbar_theme = use_applied_theme!(&props.scrollbar_theme, scroll_bar);
Expand All @@ -92,6 +137,8 @@ pub fn ScrollView(props: ScrollViewProps) -> Element {
let show_scrollbar = props.show_scrollbar;
let scroll_with_arrows = props.scroll_with_arrows;

scroll_controller.use_apply(size.inner.width, size.inner.height);

let direction_is_vertical = user_direction == "vertical";

let vertical_scrollbar_is_visible =
Expand Down
Loading

0 comments on commit 1cd1d2c

Please sign in to comment.