radix_leptos_primitives/components/
scroll_area.rs1use crate::utils::merge_classes;
2use leptos::children::Children;
3use leptos::prelude::*;
4
5#[component]
9pub fn ScrollArea(
10 #[prop(optional)] class: Option<String>,
11 #[prop(optional)] style: Option<String>,
12 #[prop(optional)] children: Option<Children>,
13 #[prop(optional)] orientation: Option<ScrollAreaOrientation>,
14 #[prop(optional)] scroll_hidden: Option<bool>,
15) -> impl IntoView {
16 let orientation = orientation.unwrap_or_default();
17 let scroll_hidden = scroll_hidden.unwrap_or(false);
18
19 let class = merge_classes(vec![
20 "scroll-area",
21 &orientation.to_class(),
22 class.as_deref().unwrap_or(""),
23 ]);
24
25 view! {
26 <div
27 class=class
28 style=style
29 data-orientation=orientation.to_aria()
30 >
31 {children.map(|c| c())}
32 </div>
33 }
34}
35
36#[component]
38pub fn ScrollAreaViewport(
39 #[prop(optional)] class: Option<String>,
40 #[prop(optional)] style: Option<String>,
41 #[prop(optional)] children: Option<Children>,
42) -> impl IntoView {
43 let class = merge_classes(vec!["scroll-area-viewport", class.as_deref().unwrap_or("")]);
44
45 view! {
46 <div
47 class=class
48 style=style
49 >
50 {children.map(|c| c())}
51 </div>
52 }
53}
54
55#[component]
57pub fn ScrollAreaScrollbar(
58 #[prop(optional)] class: Option<String>,
59 #[prop(optional)] style: Option<String>,
60 #[prop(optional)] children: Option<Children>,
61 #[prop(optional)] orientation: Option<ScrollAreaOrientation>,
62 #[prop(optional)] force_mount: Option<bool>,
63) -> impl IntoView {
64 let orientation = orientation.unwrap_or_default();
65 let force_mount = force_mount.unwrap_or(false);
66
67 let class = merge_classes(vec![
68 "scroll-area-scrollbar",
69 &orientation.to_class(),
70 class.as_deref().unwrap_or(""),
71 ]);
72
73 view! {
74 <div
75 class=class
76 style=style
77 data-orientation=orientation.to_aria()
78 >
79 {children.map(|c| c())}
80 </div>
81 }
82}
83
84#[component]
86pub fn ScrollAreaThumb(
87 #[prop(optional)] class: Option<String>,
88 #[prop(optional)] style: Option<String>,
89) -> impl IntoView {
90 let class = merge_classes(vec!["scroll-area-thumb", class.as_deref().unwrap_or("")]);
91
92 view! {
93 <div
94 class=class
95 style=style
96 />
97 }
98}
99
100#[component]
102pub fn ScrollAreaCorner(
103 #[prop(optional)] class: Option<String>,
104 #[prop(optional)] style: Option<String>,
105) -> impl IntoView {
106 let class = merge_classes(vec!["scroll-area-corner", class.as_deref().unwrap_or("")]);
107
108 view! {
109 <div
110 class=class
111 style=style
112 />
113 }
114}
115
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
118pub enum ScrollAreaOrientation {
119 #[default]
120 Vertical,
121 Horizontal,
122 Both,
123}
124
125impl ScrollAreaOrientation {
126 pub fn to_class(&self) -> &'static str {
127 match self {
128 ScrollAreaOrientation::Vertical => "vertical",
129 ScrollAreaOrientation::Horizontal => "horizontal",
130 ScrollAreaOrientation::Both => "both",
131 }
132 }
133
134 pub fn to_aria(&self) -> &'static str {
135 match self {
136 ScrollAreaOrientation::Vertical => "vertical",
137 ScrollAreaOrientation::Horizontal => "horizontal",
138 ScrollAreaOrientation::Both => "both",
139 }
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use crate::utils::merge_classes;
146 use crate::ScrollAreaOrientation;
147 use wasm_bindgen_test::*;
148
149 wasm_bindgen_test_configure!(run_in_browser);
150
151 #[test]
153 fn test_scroll_area_creation() {}
154
155 #[test]
156 fn test_scroll_area_with_class() {}
157
158 #[test]
159 fn test_scroll_area_with_style() {}
160
161 #[test]
162 fn test_scroll_area_vertical_orientation() {}
163
164 #[test]
165 fn test_scroll_area_horizontal_orientation() {}
166
167 #[test]
168 fn test_scroll_area_both_orientation() {}
169
170 #[test]
171 fn test_scroll_area_scroll_hidden() {}
172
173 #[test]
175 fn test_scroll_area_viewport_creation() {}
176
177 #[test]
178 fn test_scroll_area_viewport_with_class() {}
179
180 #[test]
181 fn test_scroll_area_viewport_with_style() {}
182
183 #[test]
185 fn test_scroll_area_scrollbar_creation() {}
186
187 #[test]
188 fn test_scroll_area_scrollbar_with_class() {}
189
190 #[test]
191 fn test_scroll_area_scrollbar_with_style() {}
192
193 #[test]
194 fn test_scroll_area_scrollbar_vertical_orientation() {}
195
196 #[test]
197 fn test_scroll_area_scrollbar_horizontal_orientation() {}
198
199 #[test]
200 fn test_scroll_area_scrollbar_both_orientation() {}
201
202 #[test]
203 fn test_scroll_area_scrollbar_force_mount() {}
204
205 #[test]
207 fn test_scroll_area_thumb_creation() {}
208
209 #[test]
210 fn test_scroll_area_thumb_with_class() {}
211
212 #[test]
213 fn test_scroll_area_thumb_with_style() {}
214
215 #[test]
217 fn test_scroll_area_corner_creation() {}
218
219 #[test]
220 fn test_scroll_area_corner_with_class() {}
221
222 #[test]
223 fn test_scroll_area_corner_with_style() {}
224
225 #[test]
227 fn test_scroll_area_orientation_default() {
228 let orientation = ScrollAreaOrientation::default();
229 assert_eq!(orientation, ScrollAreaOrientation::Vertical);
230 }
231
232 #[test]
233 fn test_scroll_area_orientation_vertical() {
234 let orientation = ScrollAreaOrientation::Vertical;
235 assert_eq!(orientation.to_class(), "vertical");
236 assert_eq!(orientation.to_aria(), "vertical");
237 }
238
239 #[test]
240 fn test_scroll_area_orientation_horizontal() {
241 let orientation = ScrollAreaOrientation::Horizontal;
242 assert_eq!(orientation.to_class(), "horizontal");
243 assert_eq!(orientation.to_aria(), "horizontal");
244 }
245
246 #[test]
247 fn test_scroll_area_orientation_both() {
248 let orientation = ScrollAreaOrientation::Both;
249 assert_eq!(orientation.to_class(), "both");
250 assert_eq!(orientation.to_aria(), "both");
251 }
252
253 #[test]
255 fn test_merge_classes_empty() {
256 let result = merge_classes(Vec::new());
257 assert_eq!(result, "");
258 }
259
260 #[test]
261 fn test_merge_classes_single() {
262 let result = merge_classes(vec!["class1"]);
263 assert_eq!(result, "class1");
264 }
265
266 #[test]
267 fn test_merge_classes_multiple() {
268 let result = merge_classes(vec!["class1", "class2", "class3"]);
269 assert_eq!(result, "class1 class2 class3");
270 }
271
272 #[test]
273 fn test_merge_classes_with_empty() {
274 let result = merge_classes(vec!["class1", "", "class3"]);
275 assert_eq!(result, "class1 class3");
276 }
277
278 #[test]
280 fn test_scroll_area_property_based() {
281 use proptest::prelude::*;
282 proptest!(|(____class in ".*", __style in ".*")| {
283
284 });
285 }
286
287 #[test]
288 fn test_scroll_area_viewport_property_based() {
289 use proptest::prelude::*;
290 proptest!(|(____class in ".*", __style in ".*")| {
291
292 });
293 }
294
295 #[test]
296 fn test_scroll_area_scrollbar_property_based() {
297 use proptest::prelude::*;
298 proptest!(|(____class in ".*", __style in ".*")| {
299
300 });
301 }
302
303 #[test]
304 fn test_scroll_area_thumb_property_based() {
305 use proptest::prelude::*;
306 proptest!(|(____class in ".*", __style in ".*")| {
307
308 });
309 }
310
311 #[test]
312 fn test_scroll_area_corner_property_based() {
313 use proptest::prelude::*;
314 proptest!(|(____class in ".*", __style in ".*")| {
315
316 });
317 }
318}