waterui_layout/scroll.rs
1//! Scroll containers that defer behaviour to the active renderer backend.
2
3use waterui_core::{AnyView, View, raw_view};
4
5use crate::StretchAxis;
6
7/// A scrollable view that displays content larger than its frame.
8///
9/// Use a `ScrollView` when you have content that might not fit in the available space.
10/// The view automatically enables scrolling in the specified direction.
11///
12/// ```ignore
13/// scroll(
14/// vstack((
15/// text("Item 1"),
16/// text("Item 2"),
17/// text("Item 3"),
18/// // ... many more items
19/// ))
20/// )
21/// ```
22///
23/// By default, `ScrollView` scrolls vertically. For horizontal scrolling:
24///
25/// ```ignore
26/// scroll_horizontal(long_content)
27/// ```
28///
29/// Or both directions:
30///
31/// ```ignore
32/// scroll_both(large_image)
33/// ```
34#[derive(Debug)]
35pub struct ScrollView {
36 axis: Axis,
37 content: AnyView,
38}
39
40/// Defines the scrolling directions supported by `ScrollView`.
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)]
42#[non_exhaustive]
43pub enum Axis {
44 /// Allow horizontal scrolling only.
45 Horizontal,
46 /// Allow vertical scrolling only (default).
47 #[default]
48 Vertical,
49 /// Allow scrolling in both directions.
50 All,
51}
52
53impl ScrollView {
54 /// Creates a new `ScrollView` with the specified scroll axis and content.
55 #[must_use]
56 pub const fn new(axis: Axis, content: AnyView) -> Self {
57 Self { axis, content }
58 }
59
60 /// Decomposes the `ScrollView` into its axis and content.
61 pub fn into_inner(self) -> (Axis, AnyView) {
62 (self.axis, self.content)
63 }
64
65 /// Creates a `ScrollView` with horizontal scrolling.
66 pub fn horizontal(content: impl View) -> Self {
67 Self::new(Axis::Horizontal, AnyView::new(content))
68 }
69
70 /// Creates a `ScrollView` with vertical scrolling.
71 pub fn vertical(content: impl View) -> Self {
72 Self::new(Axis::Vertical, AnyView::new(content))
73 }
74
75 /// Creates a `ScrollView` with scrolling in both directions.
76 pub fn both(content: impl View) -> Self {
77 Self::new(Axis::All, AnyView::new(content))
78 }
79}
80
81raw_view!(ScrollView, StretchAxis::Both);
82
83/// Creates a vertical `ScrollView` with the given content.
84///
85/// This is the most common scroll direction for lists and long content.
86/// The actual scrolling behavior is implemented by the renderer backend.
87pub fn scroll(content: impl View) -> ScrollView {
88 ScrollView::vertical(content)
89}
90
91/// Creates a horizontal `ScrollView` with the given content.
92///
93/// Useful for wide content that needs to scroll left-right.
94/// The actual scrolling behavior is implemented by the renderer backend.
95pub fn scroll_horizontal(content: impl View) -> ScrollView {
96 ScrollView::horizontal(content)
97}
98
99/// Creates a `ScrollView` that can scroll in both directions.
100///
101/// Useful for large content like images or tables that may need both horizontal and vertical scrolling.
102/// The actual scrolling behavior is implemented by the renderer backend.
103pub fn scroll_both(content: impl View) -> ScrollView {
104 ScrollView::both(content)
105}