Skip to main content

maud_ui/primitives/
scroll_area.rs

1//! ScrollArea component — custom-styled scrollbar with auto-hide behavior.
2use maud::{html, Markup};
3
4/// ScrollArea rendering properties
5#[derive(Debug, Clone)]
6pub struct Props {
7    /// CSS value for max-height (e.g., "12rem", "200px")
8    pub max_height: String,
9    /// Unique identifier for the viewport
10    pub id: String,
11    /// Content to scroll
12    pub children: Markup,
13}
14
15impl Default for Props {
16    fn default() -> Self {
17        Self {
18            max_height: "12rem".to_string(),
19            id: "scroll-area-default".to_string(),
20            children: html! {},
21        }
22    }
23}
24
25/// Render a ScrollArea with custom scrollbar and auto-hide behavior
26pub fn render(props: Props) -> Markup {
27    html! {
28        div class="mui-scroll-area" data-mui="scroll-area" style={"max-height: " (props.max_height)} {
29            div class="mui-scroll-area__viewport" id=(props.id) tabindex="0" role="region" aria-label="Scrollable region" {
30                (props.children)
31            }
32            div class="mui-scroll-area__scrollbar" aria-hidden="true" {
33                div class="mui-scroll-area__thumb" {}
34            }
35        }
36    }
37}
38
39/// Showcase the ScrollArea component
40pub fn showcase() -> Markup {
41    let tags: [&str; 18] = [
42        "v1.4.0-beta.1", "v1.3.2", "v1.3.1", "v1.3.0",
43        "v1.2.5", "v1.2.4", "v1.2.3", "v1.2.2",
44        "v1.2.1", "v1.2.0", "v1.1.3", "v1.1.2",
45        "v1.1.1", "v1.1.0", "v1.0.2", "v1.0.1",
46        "v1.0.0", "v0.9.0-rc.1",
47    ];
48
49    let tag_list = html! {
50        div style="display:flex;flex-direction:column;" {
51            @for tag in tags.iter() {
52                div style="padding:0.5rem 0.75rem;font-size:0.8125rem;font-family:var(--mui-font-mono);border-bottom:1px solid var(--mui-border);" {
53                    (tag)
54                }
55            }
56        }
57    };
58
59    let changelog = html! {
60        div style="padding:0.75rem;font-size:0.8125rem;font-family:var(--mui-font-mono);line-height:1.6;white-space:pre;" {
61            "commit a1b2c3d\n"
62            "Author: Jane Smith\n"
63            "Date:   Mon Apr 13 09:14:22 2026 +0000\n\n"
64            "    fix: resolve race condition in SSE reconnect\n\n"
65            "commit e4f5a6b\n"
66            "Author: Alex Chen\n"
67            "Date:   Sun Apr 12 17:32:08 2026 +0000\n\n"
68            "    feat: add pagination to search results\n\n"
69            "commit c7d8e9f\n"
70            "Author: Jane Smith\n"
71            "Date:   Sat Apr 11 11:05:44 2026 +0000\n\n"
72            "    refactor: extract calendar date math\n\n"
73            "commit 0a1b2c3\n"
74            "Author: Sam Lee\n"
75            "Date:   Fri Apr 10 14:22:11 2026 +0000\n\n"
76            "    docs: update API reference for v1.3\n\n"
77            "commit d4e5f6a\n"
78            "Author: Alex Chen\n"
79            "Date:   Thu Apr 9 08:47:33 2026 +0000\n\n"
80            "    fix: breadcrumb separator a11y\n"
81        }
82    };
83
84    html! {
85        div.mui-showcase__grid {
86            div {
87                p.mui-showcase__caption { "Release tags" }
88                div style="border:1px solid var(--mui-border);border-radius:var(--mui-radius-lg);overflow:hidden;max-width:14rem;" {
89                    (render(Props {
90                        max_height: "14rem".to_string(),
91                        id: "demo-scroll-tags".to_string(),
92                        children: tag_list,
93                    }))
94                }
95            }
96
97            div {
98                p.mui-showcase__caption { "Commit log" }
99                div style="border:1px solid var(--mui-border);border-radius:var(--mui-radius-lg);overflow:hidden;max-width:26rem;" {
100                    (render(Props {
101                        max_height: "14rem".to_string(),
102                        id: "demo-scroll-log".to_string(),
103                        children: changelog,
104                    }))
105                }
106            }
107        }
108    }
109}