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}