button.rs
1use gpui2::elements::div;
2use gpui2::geometry::rems;
3use gpui2::{Element, IntoElement, ViewContext};
4use strum::IntoEnumIterator;
5use ui::prelude::*;
6use ui::{h_stack, v_stack, Button, Icon, IconPosition, Label};
7
8use crate::story::Story;
9
10#[derive(Element, Default)]
11pub struct ButtonStory {}
12
13impl ButtonStory {
14 fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
15 let states = InteractionState::iter();
16
17 Story::container(cx)
18 .child(Story::title_for::<_, Button<V>>(cx))
19 .child(
20 div()
21 .flex()
22 .gap_8()
23 .child(
24 div()
25 .child(Story::label(cx, "Ghost (Default)"))
26 .child(h_stack().gap_2().children(states.clone().map(|state| {
27 v_stack()
28 .gap_1()
29 .child(
30 Label::new(state.to_string())
31 .color(ui::LabelColor::Muted)
32 .size(ui::LabelSize::Small),
33 )
34 .child(
35 Button::new("Label")
36 .variant(ButtonVariant::Ghost)
37 .state(state),
38 )
39 })))
40 .child(Story::label(cx, "Ghost – Left Icon"))
41 .child(h_stack().gap_2().children(states.clone().map(|state| {
42 v_stack()
43 .gap_1()
44 .child(
45 Label::new(state.to_string())
46 .color(ui::LabelColor::Muted)
47 .size(ui::LabelSize::Small),
48 )
49 .child(
50 Button::new("Label")
51 .variant(ButtonVariant::Ghost)
52 .icon(Icon::Plus)
53 .icon_position(IconPosition::Left)
54 .state(state),
55 )
56 })))
57 .child(Story::label(cx, "Ghost – Right Icon"))
58 .child(h_stack().gap_2().children(states.clone().map(|state| {
59 v_stack()
60 .gap_1()
61 .child(
62 Label::new(state.to_string())
63 .color(ui::LabelColor::Muted)
64 .size(ui::LabelSize::Small),
65 )
66 .child(
67 Button::new("Label")
68 .variant(ButtonVariant::Ghost)
69 .icon(Icon::Plus)
70 .icon_position(IconPosition::Right)
71 .state(state),
72 )
73 }))),
74 )
75 .child(
76 div()
77 .child(Story::label(cx, "Filled"))
78 .child(h_stack().gap_2().children(states.clone().map(|state| {
79 v_stack()
80 .gap_1()
81 .child(
82 Label::new(state.to_string())
83 .color(ui::LabelColor::Muted)
84 .size(ui::LabelSize::Small),
85 )
86 .child(
87 Button::new("Label")
88 .variant(ButtonVariant::Filled)
89 .state(state),
90 )
91 })))
92 .child(Story::label(cx, "Filled – Left Button"))
93 .child(h_stack().gap_2().children(states.clone().map(|state| {
94 v_stack()
95 .gap_1()
96 .child(
97 Label::new(state.to_string())
98 .color(ui::LabelColor::Muted)
99 .size(ui::LabelSize::Small),
100 )
101 .child(
102 Button::new("Label")
103 .variant(ButtonVariant::Filled)
104 .icon(Icon::Plus)
105 .icon_position(IconPosition::Left)
106 .state(state),
107 )
108 })))
109 .child(Story::label(cx, "Filled – Right Button"))
110 .child(h_stack().gap_2().children(states.clone().map(|state| {
111 v_stack()
112 .gap_1()
113 .child(
114 Label::new(state.to_string())
115 .color(ui::LabelColor::Muted)
116 .size(ui::LabelSize::Small),
117 )
118 .child(
119 Button::new("Label")
120 .variant(ButtonVariant::Filled)
121 .icon(Icon::Plus)
122 .icon_position(IconPosition::Right)
123 .state(state),
124 )
125 }))),
126 )
127 .child(
128 div()
129 .child(Story::label(cx, "Fixed With"))
130 .child(h_stack().gap_2().children(states.clone().map(|state| {
131 v_stack()
132 .gap_1()
133 .child(
134 Label::new(state.to_string())
135 .color(ui::LabelColor::Muted)
136 .size(ui::LabelSize::Small),
137 )
138 .child(
139 Button::new("Label")
140 .variant(ButtonVariant::Filled)
141 .state(state)
142 .width(Some(rems(6.).into())),
143 )
144 })))
145 .child(Story::label(cx, "Fixed With – Left Icon"))
146 .child(h_stack().gap_2().children(states.clone().map(|state| {
147 v_stack()
148 .gap_1()
149 .child(
150 Label::new(state.to_string())
151 .color(ui::LabelColor::Muted)
152 .size(ui::LabelSize::Small),
153 )
154 .child(
155 Button::new("Label")
156 .variant(ButtonVariant::Filled)
157 .state(state)
158 .icon(Icon::Plus)
159 .icon_position(IconPosition::Left)
160 .width(Some(rems(6.).into())),
161 )
162 })))
163 .child(Story::label(cx, "Fixed With – Right Icon"))
164 .child(h_stack().gap_2().children(states.clone().map(|state| {
165 v_stack()
166 .gap_1()
167 .child(
168 Label::new(state.to_string())
169 .color(ui::LabelColor::Muted)
170 .size(ui::LabelSize::Small),
171 )
172 .child(
173 Button::new("Label")
174 .variant(ButtonVariant::Filled)
175 .state(state)
176 .icon(Icon::Plus)
177 .icon_position(IconPosition::Right)
178 .width(Some(rems(6.).into())),
179 )
180 }))),
181 ),
182 )
183 .child(Story::label(cx, "Button with `on_click`"))
184 .child(
185 Button::new("Label")
186 .variant(ButtonVariant::Ghost)
187 // NOTE: There currently appears to be a bug in GPUI2 where only the last event handler will fire.
188 // So adding additional buttons with `on_click`s after this one will cause this `on_click` to not fire.
189 .on_click(|_view, _cx| println!("Button clicked.")),
190 )
191 }
192}