vizia_core/views/
chip.rs

1use crate::{icons::ICON_X, prelude::*};
2use std::sync::Arc;
3
4/// A visual indicator such as a tag.
5#[derive(Lens)]
6pub struct Chip {
7    on_close: Option<Arc<dyn Fn(&mut EventContext) + Send + Sync>>,
8}
9
10impl Chip {
11    /// Creates a new [Chip] view with the provided text.
12    ///
13    /// # Example
14    /// ```
15    /// # use vizia_core::prelude::*;
16    /// #
17    /// # let cx = &mut Context::default();
18    /// #
19    /// Chip::new(cx, "Chip");
20    /// ```
21    pub fn new<T>(cx: &mut Context, text: impl Res<T> + Clone) -> Handle<Self>
22    where
23        T: ToStringLocalized,
24    {
25        Self { on_close: None }
26            .build(cx, move |cx| {
27                Label::new(cx, text).height(Stretch(1.0)).alignment(Alignment::Left);
28                Binding::new(cx, Chip::on_close.map(|on_close| on_close.is_some()), |cx, val| {
29                    if val.get(cx) {
30                        let on_close = Chip::on_close.get(cx).unwrap();
31                        Button::new(cx, |cx| Svg::new(cx, ICON_X))
32                            .class("close-icon")
33                            .height(Pixels(16.0))
34                            .width(Pixels(16.0))
35                            .alignment(Alignment::Center)
36                            .on_press(move |cx| (on_close)(cx));
37                    }
38                });
39            })
40            .toggle_class("close", Chip::on_close.map(|on_close| on_close.is_some()))
41            .layout_type(LayoutType::Row)
42    }
43}
44
45impl View for Chip {
46    fn element(&self) -> Option<&'static str> {
47        Some("chip")
48    }
49}
50
51/// Used in conjunction with the `variant` modifier for selecting the style variant of a chip.
52#[derive(Debug, Clone, Copy, Data, PartialEq, Eq)]
53pub enum ChipVariant {
54    /// A filled chip.
55    Filled,
56    /// A chip with no fill and just a border.
57    Outline,
58}
59
60impl_res_simple!(ChipVariant);
61
62impl Handle<'_, Chip> {
63    /// Set the callback triggered when the close button of the chip is pressed.
64    /// The chip close button is not displayed by default. Setting this callback causes the close button to be displayed.
65    pub fn on_close(self, callback: impl 'static + Fn(&mut EventContext) + Send + Sync) -> Self {
66        self.modify(|chip: &mut Chip| {
67            chip.on_close = Some(Arc::new(callback));
68        })
69    }
70
71    /// Selects the style variant to be used by the chip. Accepts a value of, or lens to, a [ChipVariant].
72    ///
73    /// # Example
74    /// ```
75    /// # use vizia_core::prelude::*;
76    /// #
77    /// #
78    /// # let cx = &mut Context::default();
79    /// #
80    /// Chip::new(cx, "Chip")
81    ///     .variant(ChipVariant::Filled);
82    /// ```
83    pub fn variant<U: Into<ChipVariant>>(self, variant: impl Res<U>) -> Self {
84        self.bind(variant, |handle, variant| {
85            let variant = variant.get(&handle).into();
86
87            match variant {
88                ChipVariant::Filled => {
89                    handle.toggle_class("outline", false);
90                }
91
92                ChipVariant::Outline => {
93                    handle.toggle_class("outline", true);
94                }
95            }
96        })
97    }
98}