1#![allow(missing_docs)]
2use crate::{prelude::*, Icon, IconName, IconSize, IconWithIndicator, Indicator};
3use gpui::Hsla;
4
5/// An icon that appears within a button.
6///
7/// Can be used as either an icon alongside a label, like in [`Button`](crate::Button),
8/// or as a standalone icon, like in [`IconButton`](crate::IconButton).
9#[derive(IntoElement)]
10pub(super) struct ButtonIcon {
11 icon: IconName,
12 size: IconSize,
13 color: Color,
14 disabled: bool,
15 selected: bool,
16 selected_icon: Option<IconName>,
17 selected_icon_color: Option<Color>,
18 selected_style: Option<ButtonStyle>,
19 indicator: Option<Indicator>,
20 indicator_border_color: Option<Hsla>,
21}
22
23impl ButtonIcon {
24 pub fn new(icon: IconName) -> Self {
25 Self {
26 icon,
27 size: IconSize::default(),
28 color: Color::default(),
29 disabled: false,
30 selected: false,
31 selected_icon: None,
32 selected_icon_color: None,
33 selected_style: None,
34 indicator: None,
35 indicator_border_color: None,
36 }
37 }
38
39 pub fn size(mut self, size: impl Into<Option<IconSize>>) -> Self {
40 if let Some(size) = size.into() {
41 self.size = size;
42 }
43
44 self
45 }
46
47 pub fn color(mut self, color: impl Into<Option<Color>>) -> Self {
48 if let Some(color) = color.into() {
49 self.color = color;
50 }
51
52 self
53 }
54
55 pub fn selected_icon(mut self, icon: impl Into<Option<IconName>>) -> Self {
56 self.selected_icon = icon.into();
57 self
58 }
59
60 pub fn selected_icon_color(mut self, color: impl Into<Option<Color>>) -> Self {
61 self.selected_icon_color = color.into();
62 self
63 }
64
65 pub fn indicator(mut self, indicator: Indicator) -> Self {
66 self.indicator = Some(indicator);
67 self
68 }
69
70 pub fn indicator_border_color(mut self, color: Option<Hsla>) -> Self {
71 self.indicator_border_color = color;
72 self
73 }
74}
75
76impl Disableable for ButtonIcon {
77 fn disabled(mut self, disabled: bool) -> Self {
78 self.disabled = disabled;
79 self
80 }
81}
82
83impl Toggleable for ButtonIcon {
84 fn toggle_state(mut self, selected: bool) -> Self {
85 self.selected = selected;
86 self
87 }
88}
89
90impl SelectableButton for ButtonIcon {
91 fn selected_style(mut self, style: ButtonStyle) -> Self {
92 self.selected_style = Some(style);
93 self
94 }
95}
96
97impl RenderOnce for ButtonIcon {
98 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
99 let icon = self
100 .selected_icon
101 .filter(|_| self.selected)
102 .unwrap_or(self.icon);
103
104 let icon_color = if self.disabled {
105 Color::Disabled
106 } else if self.selected_style.is_some() && self.selected {
107 self.selected_style.unwrap().into()
108 } else if self.selected {
109 self.selected_icon_color.unwrap_or(Color::Selected)
110 } else {
111 self.color
112 };
113
114 let icon = Icon::new(icon).size(self.size).color(icon_color);
115
116 match self.indicator {
117 Some(indicator) => IconWithIndicator::new(icon, Some(indicator))
118 .indicator_border_color(self.indicator_border_color)
119 .into_any_element(),
120 None => icon.into_any_element(),
121 }
122 }
123}