ribir_widgets/buttons/
outlined_button.rs1use ribir_core::prelude::*;
2
3use super::{ButtonImpl, ButtonTemplate, ButtonType, IconPosition};
4
5#[derive(Clone)]
6pub struct OutlinedButtonStyle {
7 pub height: f32,
8 pub icon_size: Size,
9 pub label_gap: f32,
10 pub icon_pos: IconPosition,
11 pub label_style: CowArc<TextStyle>,
12 pub radius: f32,
13 pub padding_style: EdgeInsets,
14 pub border_width: f32,
15}
16
17impl CustomStyle for OutlinedButtonStyle {
18 fn default_style(ctx: &BuildCtx) -> Self {
19 OutlinedButtonStyle {
20 height: 40.,
21 icon_size: Size::splat(18.),
22 label_gap: 8.,
23 icon_pos: IconPosition::Before,
24 label_style: TypographyTheme::of(ctx).label_large.text.clone(),
25 radius: 20.,
26 padding_style: EdgeInsets::horizontal(16.),
27 border_width: 1.,
28 }
29 }
30}
31
32#[derive(Clone, Declare)]
33pub struct OutlinedButtonDecorator {
34 #[allow(unused)]
35 pub button_type: ButtonType,
36 pub color: Color,
37}
38
39impl ComposeDecorator for OutlinedButtonDecorator {
40 fn compose_decorator(_: State<Self>, host: Widget) -> impl WidgetBuilder { fn_widget!(host) }
41}
42
43#[derive(Default, Declare)]
78pub struct OutlinedButton {
79 #[declare(default=Palette::of(ctx!()).primary())]
80 color: Color,
81}
82
83impl ComposeChild for OutlinedButton {
84 type Child = ButtonTemplate;
85
86 fn compose_child(this: impl StateWriter<Value = Self>, child: Self::Child) -> impl WidgetBuilder {
87 let ButtonTemplate { icon, label } = &child;
88 let button_type = match (&icon, &label) {
89 (Some(_), Some(_)) => ButtonType::BOTH,
90 (Some(_), None) => ButtonType::ICON,
91 (None, Some(_)) => ButtonType::LABEL,
92 (None, None) => panic!("Button content cannot be empty!"),
93 };
94
95 fn_widget! {
96 @ {
97 let OutlinedButtonStyle {
98 height,
99 icon_size,
100 label_gap,
101 icon_pos,
102 label_style,
103 radius,
104 padding_style,
105 border_width,
106 } = OutlinedButtonStyle::of(ctx!());
107
108 @OutlinedButtonDecorator {
109 button_type,
110 color: pipe!($this.color),
111 @ButtonImpl {
112 height,
113 icon_size,
114 label_gap,
115 icon_pos,
116 label_style,
117 background_color: None,
118 foreground_color: pipe!(Palette::of(ctx!()).base_of(&$this.color)),
119 radius,
120 border_style: pipe!(Border::all(BorderSide {
121 width: border_width,
122 color: Palette::of(ctx!()).base_of(&$this.color).into()
123 })),
124 padding_style,
125
126 @ { child }
127 }
128 }
129 }
130 }
131 }
132}