tessera_ui_basic_components/
button.rs1use std::sync::Arc;
2
3use derive_builder::Builder;
4use tessera_ui::{Color, DimensionValue, Dp};
5use tessera_ui_macros::tessera;
6
7use crate::{
8 ripple_state::RippleState,
9 shape_def::Shape,
10 surface::{SurfaceArgsBuilder, surface},
11};
12
13#[derive(Builder, Clone)]
15#[builder(pattern = "owned")]
16pub struct ButtonArgs {
17 #[builder(default = "Color::new(0.2, 0.5, 0.8, 1.0)")]
19 pub color: Color,
20 #[builder(default)]
22 pub hover_color: Option<Color>,
23 #[builder(default = "Shape::RoundedRectangle { corner_radius: 25.0, g2_k_value: 3.0 }")]
25 pub shape: Shape,
26 #[builder(default = "Dp(12.0)")]
28 pub padding: Dp,
29 #[builder(default, setter(strip_option))]
31 pub width: Option<DimensionValue>,
32 #[builder(default, setter(strip_option))]
34 pub height: Option<DimensionValue>,
35 pub on_click: Arc<dyn Fn() + Send + Sync>,
37 #[builder(default = "Color::from_rgb(1.0, 1.0, 1.0)")]
39 pub ripple_color: Color,
40 #[builder(default = "0.0")]
42 pub border_width: f32,
43 #[builder(default)]
45 pub border_color: Option<Color>,
46}
47
48impl std::fmt::Debug for ButtonArgs {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 f.debug_struct("ButtonArgs")
51 .field("color", &self.color)
52 .field("hover_color", &self.hover_color)
53 .field("shape", &self.shape)
54 .field("padding", &self.padding)
55 .field("width", &self.width)
56 .field("height", &self.height)
57 .field("on_click", &"<callback>")
58 .field("ripple_color", &self.ripple_color)
59 .field("border_width", &self.border_width)
60 .field("border_color", &self.border_color)
61 .finish()
62 }
63}
64
65impl Default for ButtonArgs {
66 fn default() -> Self {
67 ButtonArgsBuilder::default()
68 .on_click(Arc::new(|| {}))
69 .build()
70 .unwrap()
71 }
72}
73
74#[tessera]
101pub fn button(args: impl Into<ButtonArgs>, ripple_state: Arc<RippleState>, child: impl FnOnce()) {
102 let button_args: ButtonArgs = args.into();
103
104 surface(create_surface_args(&button_args), Some(ripple_state), child);
106}
107
108fn create_surface_args(args: &ButtonArgs) -> crate::surface::SurfaceArgs {
110 let mut builder = SurfaceArgsBuilder::default();
111
112 if let Some(width) = args.width {
114 builder = builder.width(width);
115 }
116
117 if let Some(height) = args.height {
119 builder = builder.height(height);
120 }
121
122 builder
123 .color(args.color)
124 .hover_color(args.hover_color)
125 .shape(args.shape)
126 .padding(args.padding)
127 .border_width(args.border_width)
128 .border_color(args.border_color)
129 .ripple_color(args.ripple_color)
130 .on_click(Some(args.on_click.clone()))
131 .build()
132 .unwrap()
133}
134
135impl ButtonArgs {
137 pub fn primary(on_click: Arc<dyn Fn() + Send + Sync>) -> Self {
139 ButtonArgsBuilder::default()
140 .color(Color::new(0.2, 0.5, 0.8, 1.0)) .on_click(on_click)
142 .build()
143 .unwrap()
144 }
145
146 pub fn secondary(on_click: Arc<dyn Fn() + Send + Sync>) -> Self {
148 ButtonArgsBuilder::default()
149 .color(Color::new(0.6, 0.6, 0.6, 1.0)) .on_click(on_click)
151 .build()
152 .unwrap()
153 }
154
155 pub fn success(on_click: Arc<dyn Fn() + Send + Sync>) -> Self {
157 ButtonArgsBuilder::default()
158 .color(Color::new(0.1, 0.7, 0.3, 1.0)) .on_click(on_click)
160 .build()
161 .unwrap()
162 }
163
164 pub fn danger(on_click: Arc<dyn Fn() + Send + Sync>) -> Self {
166 ButtonArgsBuilder::default()
167 .color(Color::new(0.8, 0.2, 0.2, 1.0)) .on_click(on_click)
169 .build()
170 .unwrap()
171 }
172}
173
174impl ButtonArgs {
176 pub fn with_color(mut self, color: Color) -> Self {
177 self.color = color;
178 self
179 }
180
181 pub fn with_hover_color(mut self, hover_color: Color) -> Self {
182 self.hover_color = Some(hover_color);
183 self
184 }
185
186 pub fn with_padding(mut self, padding: Dp) -> Self {
187 self.padding = padding;
188 self
189 }
190
191 pub fn with_shape(mut self, shape: Shape) -> Self {
192 self.shape = shape;
193 self
194 }
195
196 pub fn with_width(mut self, width: DimensionValue) -> Self {
197 self.width = Some(width);
198 self
199 }
200
201 pub fn with_height(mut self, height: DimensionValue) -> Self {
202 self.height = Some(height);
203 self
204 }
205
206 pub fn with_ripple_color(mut self, ripple_color: Color) -> Self {
207 self.ripple_color = ripple_color;
208 self
209 }
210
211 pub fn with_border(mut self, width: f32, color: Option<Color>) -> Self {
212 self.border_width = width;
213 self.border_color = color;
214 self
215 }
216}