tessera_ui_basic_components/
icon_button.rs

1//! An interactive button that displays an icon.
2//!
3//! ## Usage
4//!
5//! Use for compact actions where an icon is sufficient to convey the meaning.
6use derive_builder::Builder;
7use tessera_ui::tessera;
8
9use crate::{
10    RippleState,
11    button::{ButtonArgs, button},
12    glass_button::{GlassButtonArgs, glass_button},
13    icon::{IconArgs, icon},
14};
15
16/// Arguments for [`icon_button`].
17#[derive(Clone, Builder)]
18#[builder(pattern = "owned")]
19pub struct IconButtonArgs {
20    /// Appearance/behavior settings for the underlying [`button`].
21    #[builder(default = "ButtonArgs::default()", setter(custom))]
22    pub button: ButtonArgs,
23    /// Icon that will be rendered at the center of the button.
24    #[builder(setter(into))]
25    pub icon: IconArgs,
26}
27
28impl IconButtonArgsBuilder {
29    /// Override the [`ButtonArgs`] using either a ready instance or a builder-produced value.
30    pub fn button(mut self, button: impl Into<ButtonArgs>) -> Self {
31        self.button = Some(button.into());
32        self
33    }
34}
35
36/// Lifted [`glass_button`] counterpart for icon buttons.
37#[derive(Clone, Builder)]
38#[builder(pattern = "owned")]
39pub struct GlassIconButtonArgs {
40    /// Appearance/behavior settings for the underlying [`glass_button`].
41    #[builder(default = "GlassButtonArgs::default()", setter(custom))]
42    pub button: GlassButtonArgs,
43    /// Icon rendered at the center of the glass button.
44    #[builder(setter(into))]
45    pub icon: IconArgs,
46}
47
48impl GlassIconButtonArgsBuilder {
49    /// Override the [`GlassButtonArgs`] using either a ready instance or a builder-produced value.
50    pub fn button(mut self, button: impl Into<GlassButtonArgs>) -> Self {
51        self.button = Some(button.into());
52        self
53    }
54}
55
56/// # icon_button
57///
58/// Renders a standard button with an icon as its content.
59///
60/// ## Usage
61///
62/// Use for common actions like "edit", "delete", or "settings" in a toolbar or list item.
63///
64/// ## Parameters
65///
66/// - `args` — configures the underlying button and the icon; see [`IconButtonArgs`].
67/// - `ripple_state` — a clonable [`RippleState`] to manage the ripple animation.
68///
69/// ## Examples
70///
71/// ```no_run
72/// use std::sync::Arc;
73/// use tessera_ui_basic_components::{
74///     icon_button::{icon_button, IconButtonArgsBuilder},
75///     button::ButtonArgsBuilder,
76///     icon::IconArgsBuilder,
77///     image_vector::{ImageVectorSource, load_image_vector_from_source},
78///     ripple_state::RippleState,
79/// };
80///
81/// let ripple_state = RippleState::new();
82/// let svg_path = "../assets/emoji_u1f416.svg";
83/// let vector_data = load_image_vector_from_source(
84///     &ImageVectorSource::Path(svg_path.to_string())
85/// ).unwrap();
86///
87/// icon_button(
88///     IconButtonArgsBuilder::default()
89///         .button(
90///             ButtonArgsBuilder::default()
91///                 .on_click(Arc::new(|| {}))
92///                 .build()
93///                 .unwrap()
94///         )
95///         .icon(IconArgsBuilder::default().content(vector_data.clone()).build().unwrap())
96///         .build()
97///         .unwrap(),
98///     ripple_state,
99/// );
100/// ```
101#[tessera]
102pub fn icon_button(args: impl Into<IconButtonArgs>, ripple_state: RippleState) {
103    let args: IconButtonArgs = args.into();
104    let icon_args = args.icon.clone();
105
106    button(args.button, ripple_state, move || {
107        icon(icon_args.clone());
108    });
109}
110
111/// # glass_icon_button
112///
113/// Renders a button with a glass effect and an icon as its content.
114///
115/// ## Usage
116///
117/// Use for prominent icon-based actions in a modern, layered UI.
118///
119/// ## Parameters
120///
121/// - `args` — configures the underlying glass button and the icon; see [`GlassIconButtonArgs`].
122/// - `ripple_state` — a clonable [`RippleState`] to manage the ripple animation.
123///
124/// ## Examples
125///
126/// ```no_run
127/// use std::sync::Arc;
128/// use tessera_ui_basic_components::{
129///     icon_button::{glass_icon_button, GlassIconButtonArgsBuilder},
130///     glass_button::GlassButtonArgsBuilder,
131///     icon::IconArgsBuilder,
132///     image_vector::{ImageVectorSource, load_image_vector_from_source},
133///     ripple_state::RippleState,
134/// };
135///
136/// let ripple_state = RippleState::new();
137/// let svg_path = "../assets/emoji_u1f416.svg";
138/// let vector_data = load_image_vector_from_source(
139///     &ImageVectorSource::Path(svg_path.to_string())
140/// ).unwrap();
141///
142/// glass_icon_button(
143///     GlassIconButtonArgsBuilder::default()
144///         .button(
145///             GlassButtonArgsBuilder::default()
146///                 .on_click(Arc::new(|| {}))
147///                 .build()
148///                 .unwrap()
149///         )
150///         .icon(IconArgsBuilder::default().content(vector_data).build().unwrap())
151///         .build()
152///         .unwrap(),
153///     ripple_state,
154/// );
155/// ```
156#[tessera]
157pub fn glass_icon_button(args: impl Into<GlassIconButtonArgs>, ripple_state: RippleState) {
158    let args: GlassIconButtonArgs = args.into();
159    let icon_args = args.icon.clone();
160
161    glass_button(args.button, ripple_state, move || {
162        icon(icon_args.clone());
163    });
164}