floem/views/button.rs
1#![deny(missing_docs)]
2use crate::{style_class, views::Decorators, IntoView, View, ViewId};
3use core::ops::FnMut;
4
5style_class!(
6 /// The style class that is applied to buttons.
7 pub ButtonClass
8);
9
10/// Creates a new simple [Button] view with the default [ButtonClass] style.
11///
12/// ### Examples
13/// ```rust
14/// # use floem::views::button;
15/// # use floem::prelude::{*, palette::css};
16/// # use floem::views::Decorators;
17/// # use floem::style::CursorStyle;
18/// // Basic usage
19/// let button1 = button("Click me").action(move || println!("Button1 clicked!"));
20/// let button2 = button("Click me").action(move || println!("Button2 clicked!"));
21/// // Apply styles for the button
22/// let styled = button("Click me")
23/// .action(|| println!("Styled button clicked!"))
24/// .style(|s| s
25/// .border(1.0)
26/// .border_radius(10.0)
27/// .padding(10.0)
28/// .background(css::YELLOW_GREEN)
29/// .color(css::DARK_GREEN)
30/// .cursor(CursorStyle::Pointer)
31/// .active(|s| s.color(css::WHITE).background(css::RED))
32/// .hover(|s| s.background(Color::from_rgb8(244, 67, 54)))
33/// .focus_visible(|s| s.border(2.).border_color(css::BLUE))
34/// );
35/// ```
36pub fn button<V: IntoView + 'static>(child: V) -> Button {
37 Button::new(child)
38}
39
40/// A simple Button view. See [`button`].
41pub struct Button {
42 id: ViewId,
43}
44
45impl View for Button {
46 fn id(&self) -> ViewId {
47 self.id
48 }
49}
50
51impl Button {
52 /// Create new [Button].
53 /// ### Examples
54 /// ```rust
55 /// # use floem::views::button;
56 /// # use floem::prelude::{*, palette::css};
57 /// # use floem::views::Decorators;
58 /// # use floem::style::CursorStyle;
59 /// // Basic usage
60 /// let button1 = button("Click me").action(move || println!("Button1 clicked!"));
61 /// let button2 = button("Click me").action(move || println!("Button2 clicked!"));
62 /// // Apply styles for the button
63 /// let styled = button("Click me")
64 /// .action(|| println!("Styled button clicked!"))
65 /// .style(|s| s
66 /// .border(1.0)
67 /// .border_radius(10.0)
68 /// .padding(10.0)
69 /// .background(css::YELLOW_GREEN)
70 /// .color(css::DARK_GREEN)
71 /// .cursor(CursorStyle::Pointer)
72 /// .active(|s| s.color(css::WHITE).background(css::RED))
73 /// .hover(|s| s.background(Color::from_rgb8(244, 67, 54)))
74 /// .focus_visible(|s| s.border(2.).border_color(css::BLUE))
75 /// );
76 /// ```
77 /// ### Reactivity
78 /// Button's label is not reactive.
79 pub fn new(child: impl IntoView) -> Self {
80 let id = ViewId::new();
81 id.add_child(Box::new(child.into_view()));
82 Button { id }.keyboard_navigable().class(ButtonClass)
83 }
84
85 /// Attach action executed on button click.
86 /// ### Example
87 /// ```rust
88 /// # use floem::views::button;
89 /// let button_with_action = button("Click me")
90 /// .action(move || println!("Button2 clicked!"));
91 /// ```
92 pub fn action(self, mut on_press: impl FnMut() + 'static) -> Self {
93 self.on_click_stop(move |_| {
94 on_press();
95 })
96 }
97}
98
99/// A trait that adds a `button` method to any type that implements `IntoView`.
100pub trait ButtonExt {
101 /// Create a [Button] from the parent.
102 fn button(self) -> Button;
103}
104impl<T: IntoView + 'static> ButtonExt for T {
105 fn button(self) -> Button {
106 button(self)
107 }
108}