aetna_core/widgets/
button.rs1use std::panic::Location;
27
28use crate::anim::Timing;
29use crate::cursor::Cursor;
30use crate::metrics::MetricsRole;
31use crate::style::StyleProfile;
32use crate::tokens;
33use crate::tree::*;
34use crate::{IntoIconSource, icon, text};
35
36#[track_caller]
37pub fn button(label: impl Into<String>) -> El {
38 El::new(Kind::Custom("button"))
39 .at_loc(Location::caller())
40 .style_profile(StyleProfile::Solid)
41 .metrics_role(MetricsRole::Button)
42 .surface_role(SurfaceRole::Raised)
43 .focusable()
44 .paint_overflow(Sides::all(tokens::RING_WIDTH))
45 .cursor(Cursor::Pointer)
46 .text(label)
47 .text_align(TextAlign::Center)
48 .text_role(TextRole::Label)
49 .fill(tokens::SECONDARY)
50 .stroke(tokens::BORDER)
51 .text_color(tokens::SECONDARY_FOREGROUND)
52 .default_radius(tokens::RADIUS_MD)
53 .default_width(Size::Hug)
54 .default_height(Size::Fixed(tokens::CONTROL_HEIGHT))
55 .default_padding(Sides::xy(tokens::SPACE_3, 0.0))
56 .animate(Timing::SPRING_QUICK)
57}
58
59#[track_caller]
60pub fn icon_button(source: impl IntoIconSource) -> El {
61 El::new(Kind::Custom("icon_button"))
62 .at_loc(Location::caller())
63 .style_profile(StyleProfile::Solid)
64 .metrics_role(MetricsRole::IconButton)
65 .surface_role(SurfaceRole::Raised)
66 .focusable()
67 .paint_overflow(Sides::all(tokens::RING_WIDTH))
68 .cursor(Cursor::Pointer)
69 .icon_source(source)
70 .icon_size(tokens::ICON_SM)
71 .icon_stroke_width(2.0)
72 .fill(tokens::SECONDARY)
73 .stroke(tokens::BORDER)
74 .text_color(tokens::SECONDARY_FOREGROUND)
75 .default_radius(tokens::RADIUS_MD)
76 .default_width(Size::Fixed(tokens::CONTROL_HEIGHT))
77 .default_height(Size::Fixed(tokens::CONTROL_HEIGHT))
78 .animate(Timing::SPRING_QUICK)
79}
80
81#[track_caller]
82pub fn button_with_icon(source: impl IntoIconSource, label: impl Into<String>) -> El {
83 El::new(Kind::Custom("button_with_icon"))
84 .at_loc(Location::caller())
85 .style_profile(StyleProfile::Solid)
86 .metrics_role(MetricsRole::Button)
87 .surface_role(SurfaceRole::Raised)
88 .focusable()
89 .paint_overflow(Sides::all(tokens::RING_WIDTH))
90 .cursor(Cursor::Pointer)
91 .axis(Axis::Row)
92 .default_gap(tokens::SPACE_2)
93 .align(Align::Center)
94 .justify(Justify::Center)
95 .child(
96 icon(source)
97 .icon_size(tokens::ICON_SM)
98 .color(tokens::SECONDARY_FOREGROUND),
99 )
100 .child(text(label).label())
101 .fill(tokens::SECONDARY)
102 .stroke(tokens::BORDER)
103 .text_color(tokens::SECONDARY_FOREGROUND)
104 .default_radius(tokens::RADIUS_MD)
105 .default_width(Size::Hug)
106 .default_height(Size::Fixed(tokens::CONTROL_HEIGHT))
107 .default_padding(Sides::xy(tokens::SPACE_3, 0.0))
108 .animate(Timing::SPRING_QUICK)
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn buttons_ease_variant_changes() {
117 assert!(button("Save").animate.is_some());
118 assert!(button("Save").primary().animate.is_some());
119 assert!(icon_button("settings").animate.is_some());
120 assert!(button_with_icon("folder", "Open").animate.is_some());
121 }
122}