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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::{Renderable};
use crate::node::{Node, NodeContainer};
use std::borrow::BorrowMut;
use crate::{DefaultModifiers, scale};
use crate::components::{Icon, Text, TextStyle};
#[derive(Debug, Clone)]
pub enum ButtonStyle {
Link,
Flat,
Outlined,
Filled,
}
#[derive(Debug, Clone)]
pub struct Button {
children: Vec<Box<dyn Renderable>>,
node: Node,
pub label: String,
pub style: ButtonStyle,
pub icon: Option<String>,
}
impl Button {
pub fn new(label: &str, style: ButtonStyle) -> Self {
Button {
children: vec![],
node: Node::default(),
label: label.to_string(),
style,
icon: None,
}
.tag("button")
}
pub fn destructive(&mut self) -> Self {
self.add_class(format!("button--{:?}--destructive", self.style).to_lowercase().as_str())
}
pub fn disabled(&mut self, is_disabled: bool) -> Self {
if is_disabled {
self.add_class(format!("button--{:?}--disabled", self.style).to_lowercase().as_str())
} else {
self.clone()
}
}
pub fn attach_to_form(&mut self, form_name: &str) -> Self {
self
.set_attr("form", form_name)
.set_attr("type", "submit")
}
pub fn action(&mut self, url: &str) -> Self {
self
.set_attr("href", url)
.tag("a")
}
pub fn icon(&mut self, name: &str) -> Self {
self.icon = Some(name.to_string());
self.clone()
}
fn append_child<'a, T>(&'a mut self, child: T)
where
T: 'static + Renderable,
{
self.children.push(Box::new(child));
}
}
impl NodeContainer for Button {
fn get_node(&mut self) -> &mut Node {
self.node.borrow_mut()
}
}
impl DefaultModifiers<Button> for Button {}
impl Renderable for Button {
fn render(&self) -> Node {
let mut button = self.clone()
.add_class("button")
.add_class(format!("button--{:?}", self.style).to_lowercase().as_str())
.set_attr("role", "button");
if let Some(icon) = button.icon {
let icon = Icon::new(icon.as_str())
.size(16)
.margin_right(scale(2))
.render();
button.node.children.push(icon);
}
let text = Text::new(self.label.as_str(), TextStyle::Button).render();
button.node.children.push(text);
button.node
}
}