1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//! Toolbar anatomy — compact action rows for page and table controls.
// Lock in full per-item documentation for this module (issue #73).
#![warn(missing_docs)]
use std::panic::Location;
use crate::tokens;
use crate::tree::*;
use crate::widgets::text::{h3, text};
/// A compact action row for page and table controls.
///
/// Brings no padding and no surface of its own — it's a transparent
/// `row` that expects a padded container around it. At the window root
/// that container is [`page`](crate::widgets::page::page) (which bakes
/// the window padding); inside a card it's the `card_header` /
/// `card_content` slots. A `toolbar` placed directly in an unpadded
/// root sits flush against the window edge and clips under rounded
/// window corners.
#[track_caller]
pub fn toolbar<I, E>(children: I) -> El
where
I: IntoIterator<Item = E>,
E: Into<El>,
{
row(children)
.at_loc(Location::caller())
.width(Size::Fill(1.0))
.height(Size::Hug)
.gap(tokens::SPACE_2)
.align(Align::Center)
}
/// Hug-sized cluster of related actions inside a [`toolbar`] — keeps its
/// buttons together so `spacer()` can push groups apart.
#[track_caller]
pub fn toolbar_group<I, E>(children: I) -> El
where
I: IntoIterator<Item = E>,
E: Into<El>,
{
row(children)
.at_loc(Location::caller())
.width(Size::Hug)
.height(Size::Hug)
.gap(tokens::SPACE_2)
.align(Align::Center)
}
/// Toolbar heading — an [`h3`] with line height tightened to match the
/// toolbar's compact row.
#[track_caller]
pub fn toolbar_title(title: impl Into<String>) -> El {
h3(title)
.at_loc(Location::caller())
.line_height(tokens::TEXT_BASE.size)
}
/// Muted single-line summary text next to the title — fills the remaining
/// row width and truncates with an ellipsis.
#[track_caller]
pub fn toolbar_description(description: impl Into<String>) -> El {
text(description)
.at_loc(Location::caller())
.muted()
.ellipsis()
.width(Size::Fill(1.0))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::widgets::button::button;
#[test]
fn toolbar_centers_action_rows() {
let bar = toolbar([toolbar_title("Documents"), spacer(), button("Upload")]);
assert_eq!(bar.axis, Axis::Row);
assert_eq!(bar.align, Align::Center);
assert_eq!(bar.width, Size::Fill(1.0));
assert_eq!(bar.gap, tokens::SPACE_2);
}
#[test]
fn toolbar_group_hugs_inline_actions() {
let group = toolbar_group([button("Filter"), button("Export")]);
assert_eq!(group.width, Size::Hug);
assert_eq!(group.align, Align::Center);
}
}