Skip to main content

button

Function button 

Source
pub fn button(label: impl Into<String>) -> El
Examples found in repository?
examples/custom_shader.rs (line 23)
22fn gradient_button(label: &str, top: Color, bottom: Color, radius: f32) -> El {
23    button(label).text_color(tokens::PRIMARY_FOREGROUND).shader(
24        ShaderBinding::custom("gradient")
25            .color("vec_a", top)
26            .color("vec_b", bottom)
27            .f32("vec_c", radius),
28    )
29}
30
31fn fixture() -> El {
32    column([
33        h1("Custom shader demo"),
34        paragraph(
35            "Three buttons below paint via a registered custom shader \
36             (gradient.wgsl). The right-hand button is a stock rounded_rect \
37             for contrast.",
38        )
39        .muted(),
40        titled_card(
41            "gradient.wgsl — vertical linear gradient",
42            [row([
43                gradient_button(
44                    "Sunrise",
45                    Color::rgb(255, 200, 90),
46                    Color::rgb(245, 95, 110),
47                    tokens::RADIUS_MD,
48                ),
49                gradient_button(
50                    "Ocean",
51                    Color::rgb(120, 200, 255),
52                    Color::rgb(40, 90, 200),
53                    tokens::RADIUS_MD,
54                ),
55                gradient_button(
56                    "Forest",
57                    Color::rgb(180, 230, 140),
58                    Color::rgb(40, 110, 80),
59                    tokens::RADIUS_MD,
60                ),
61                spacer(),
62                button("Stock").secondary(),
63            ])
64            .gap(tokens::SPACE_3)],
65        ),
66    ])
67    .gap(tokens::SPACE_4)
68    .padding(tokens::SPACE_7)
69}
More examples
Hide additional examples
examples/settings_calibration.rs (line 103)
97fn settings_header() -> El {
98    row([
99        icon_button("menu").ghost(),
100        divider().width(Size::Fixed(1.0)).height(Size::Fixed(22.0)),
101        h3("Settings").key("metric:page.title"),
102        spacer(),
103        button("Reset").secondary(),
104        button("Save changes").primary(),
105    ])
106    .key("metric:header")
107    .gap(tokens::SPACE_3)
108    .height(Size::Fixed(56.0))
109    .padding(Sides::xy(tokens::SPACE_4, 0.0))
110    .align(Align::Center)
111    .stroke(tokens::BORDER)
112}
113
114fn settings_nav_card() -> El {
115    column([
116        settings_nav_item("Account", true),
117        settings_nav_item("Security", false),
118        settings_nav_item("Notifications", false),
119        settings_nav_item("Appearance", false),
120        settings_nav_item("Billing", false),
121    ])
122    .gap(tokens::SPACE_1)
123    .padding(tokens::SPACE_1)
124    .width(Size::Fixed(220.0))
125    .height(Size::Fill(1.0))
126    .style_profile(StyleProfile::Surface)
127    .surface_role(SurfaceRole::Panel)
128    .fill(tokens::CARD)
129    .stroke(tokens::BORDER)
130    .radius(tokens::RADIUS_MD)
131    .shadow(tokens::SHADOW_MD)
132}
133
134fn settings_nav_item(label: &'static str, selected: bool) -> El {
135    let mut item = row([
136        El::new(Kind::Custom("nav-dot"))
137            .fill(tokens::MUTED_FOREGROUND)
138            .radius(tokens::RADIUS_PILL)
139            .width(Size::Fixed(6.0))
140            .height(Size::Fixed(6.0)),
141        text(label)
142            .font_weight(FontWeight::Medium)
143            .ellipsis()
144            .width(Size::Fill(1.0)),
145    ])
146    .key(if selected {
147        "metric:settings.nav.row".to_string()
148    } else {
149        format!("settings-nav-{label}")
150    })
151    .metrics_role(MetricsRole::ListItem)
152    .align(Align::Center)
153    .focusable();
154
155    if selected {
156        item = item.current();
157    } else {
158        item = item.color(tokens::MUTED_FOREGROUND);
159    }
160
161    item
162}
163
164fn settings_body() -> El {
165    column([
166        column([
167            h1("Account").heading().key("metric:section.title"),
168            text("Manage identity, workspace defaults, and security preferences.")
169                .muted()
170                .wrap_text()
171                .key("metric:page.subtitle"),
172        ])
173        .gap(tokens::SPACE_1)
174        .height(Size::Hug),
175        scroll([profile_card(), preferences_card()])
176            .key("settings-body-scroll")
177            .gap(tokens::SPACE_4)
178            .width(Size::Fill(1.0))
179            .height(Size::Fill(1.0)),
180    ])
181    .gap(tokens::SPACE_4)
182    .width(Size::Fill(1.0))
183    .height(Size::Fill(1.0))
184}
185
186fn profile_card() -> El {
187    card([
188        card_header([
189            card_title("Profile"),
190            card_description("This information appears in audit logs and shared documents."),
191        ]),
192        card_content([form([
193            row([
194                setting_field("Display name", "Alicia Koch", "display-name"),
195                setting_field("Email", "alicia@acme.co", "email"),
196            ])
197            .gap(tokens::SPACE_3),
198            row([
199                setting_select("Role", "Workspace admin", "role"),
200                setting_select("Region", "US East", "region"),
201            ])
202            .gap(tokens::SPACE_3),
203        ])]),
204    ])
205    .key("metric:profile.card")
206}
207
208fn setting_field(label: &'static str, value: &'static str, key: &'static str) -> El {
209    form_item([
210        form_label(label),
211        form_control(
212            text_input(value, &Selection::caret(key, value.len()), key).key(
213                if key == "display-name" {
214                    "metric:form.input"
215                } else {
216                    key
217                },
218            ),
219        ),
220    ])
221    .width(Size::Fill(1.0))
222}
223
224fn setting_select(label: &'static str, value: &'static str, key: &'static str) -> El {
225    form_item([form_label(label), form_control(select_trigger(key, value))]).width(Size::Fill(1.0))
226}
227
228fn preferences_card() -> El {
229    card([
230        card_header([
231            card_title("Preferences"),
232            card_description("Defaults used when creating new dashboards and exports."),
233        ]),
234        card_content([column([
235            preference_row(
236                "Compact navigation",
237                "Use tighter rows in the sidebar and command menus.",
238                switch(true).key("compact-navigation"),
239            ),
240            divider(),
241            preference_row(
242                "Email summaries",
243                "Send a daily digest when documents change.",
244                switch(false).key("email-summaries"),
245            ),
246            divider(),
247            preference_row(
248                "Require approval",
249                "Route external sharing through an owner review.",
250                checkbox(true).key("approval-required"),
251            ),
252        ])
253        .gap(0.0)
254        .width(Size::Fill(1.0))])
255        .padding(0.0),
256    ])
257    .key("metric:preferences.card")
258}
259
260fn preference_row(title: &'static str, description: &'static str, control: El) -> El {
261    row([
262        column([
263            text(title).semibold().ellipsis().width(Size::Fill(1.0)),
264            text(description)
265                .caption()
266                .ellipsis()
267                .width(Size::Fill(1.0)),
268        ])
269        .gap(2.0)
270        .width(Size::Fill(1.0))
271        .height(Size::Hug),
272        control,
273    ])
274    .key(if title == "Compact navigation" {
275        "metric:preference.row".to_string()
276    } else {
277        format!("preference-{title}")
278    })
279    .metrics_role(MetricsRole::PreferenceRow)
280    .gap(tokens::SPACE_4)
281    .padding(Sides::xy(tokens::SPACE_4, tokens::SPACE_3))
282    .align(Align::Center)
283}
284
285fn settings_aside() -> El {
286    column([security_card(), scale_card()])
287        .gap(tokens::SPACE_4)
288        .width(Size::Fixed(300.0))
289        .height(Size::Fill(1.0))
290}
291
292fn security_card() -> El {
293    card([
294        card_header([
295            card_title("Security"),
296            card_description("Two-factor authentication is enabled for all privileged users."),
297        ]),
298        card_content([
299            compact_stat("Passkeys", "2 registered", badge("On").success()),
300            compact_stat("Sessions", "3 active", button("Review").secondary()),
301        ]),
302    ])
303    .width(Size::Fill(1.0))
304}
examples/circular_layout.rs (line 63)
48fn fixture() -> El {
49    let centre = h2("Compass").center_text();
50    let dirs = [
51        ("North", "n"),
52        ("NE", "ne"),
53        ("East", "e"),
54        ("SE", "se"),
55        ("South", "s"),
56        ("SW", "sw"),
57        ("West", "w"),
58        ("NW", "nw"),
59    ];
60
61    let mut children: Vec<El> = vec![centre];
62    for (label, k) in dirs {
63        children.push(button(label).key(k).primary());
64    }
65
66    column([
67        h1("Custom layout — circular"),
68        paragraph(
69            "Eight buttons positioned on a circle by an author-supplied \
70             LayoutFn. Stock paint, automatic hover/press, and hit-test \
71             all keep working — only the rect distribution changed.",
72        )
73        .muted(),
74        stack(children)
75            .key("compass")
76            .layout(circular)
77            .width(Size::Fill(1.0))
78            .height(Size::Fixed(360.0)),
79    ])
80    .gap(tokens::SPACE_4)
81    .padding(tokens::SPACE_7)
82}
examples/toast.rs (line 46)
31fn fixture() -> El {
32    // Apps wrap their main view in `overlays(main, [])` so the
33    // runtime can append the synthesized toast layer as an overlay
34    // sibling — same convention as for popovers and modals.
35    overlays(
36        column([
37            h2("Toasts"),
38            paragraph(
39                "Apps queue toasts by returning ToastSpec values from \
40                 App::drain_toasts. The runtime stamps each with a TTL, \
41                 stacks them at the bottom-right corner, and dismisses \
42                 them on click or auto-expiry.",
43            )
44            .muted(),
45            row([
46                button("Save changes").key("save"),
47                button("Trigger error").key("err"),
48                button("Show info").key("info"),
49            ])
50            .gap(tokens::SPACE_2),
51        ])
52        .gap(tokens::SPACE_4)
53        .padding(tokens::SPACE_7)
54        .width(Size::Fill(1.0))
55        .height(Size::Fill(1.0)),
56        [],
57    )
58}
examples/polish_calibration.rs (line 344)
317fn form_probe() -> El {
318    form([
319        form_item([
320            form_label("Valid input"),
321            form_control(
322                text_input(
323                    "Valid input",
324                    &Selection::caret("valid-input", 11),
325                    "valid-input",
326                )
327                .key("metric:form.input"),
328            ),
329            form_description("Default field spacing and helper text."),
330        ]),
331        form_item([
332            form_label("Invalid input"),
333            form_control(
334                text_input(
335                    "Invalid input",
336                    &Selection::caret("invalid-input", 13),
337                    "invalid-input",
338                )
339                .invalid(),
340            ),
341            form_message("This field needs attention."),
342        ]),
343        row([
344            button("Disabled").secondary().disabled(),
345            button("Loading").primary().loading(),
346            spacer(),
347        ]),
348    ])
349    .padding(tokens::SPACE_3)
350    .fill(tokens::MUTED)
351    .stroke(tokens::BORDER)
352    .radius(tokens::RADIUS_MD)
353}
examples/modal.rs (line 33)
9fn modal_fixture() -> El {
10    stack([
11        column([
12            h1("Account"),
13            titled_card(
14                "Profile",
15                [
16                    row([text("Email"), spacer(), text("user@example.com").muted()]),
17                    row([text("Plan"), spacer(), badge("Pro").info()]),
18                ],
19            ),
20            titled_card(
21                "Danger zone",
22                [row([
23                    column([
24                        text("Delete account").bold(),
25                        text("Remove this account and all associated data.")
26                            .muted()
27                            .small(),
28                    ])
29                    .gap(tokens::SPACE_1)
30                    .align(Align::Start)
31                    .width(Size::Hug),
32                    spacer(),
33                    button("Delete").destructive().key("open-delete"),
34                ])],
35            ),
36        ])
37        .gap(tokens::SPACE_4)
38        .padding(tokens::SPACE_7),
39        modal(
40            "delete-account",
41            "Delete account?",
42            [
43                text("Permanent action. Export data first.").muted(),
44                row([
45                    spacer(),
46                    button("Cancel").ghost().key("cancel-delete"),
47                    button("Delete").destructive().key("confirm-delete"),
48                ])
49                .gap(tokens::SPACE_2),
50            ],
51        ),
52    ])
53}