1use gpui::{AnyElement, IntoElement, Point};
2
3use crate::{IconDecoration, IconDecorationKind, prelude::*};
4
5#[derive(IntoElement, RegisterComponent)]
6pub struct DecoratedIcon {
7 icon: Icon,
8 decoration: Option<IconDecoration>,
9}
10
11impl DecoratedIcon {
12 pub const fn new(icon: Icon, decoration: Option<IconDecoration>) -> Self {
13 Self { icon, decoration }
14 }
15}
16
17impl RenderOnce for DecoratedIcon {
18 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
19 div()
20 .relative()
21 .size(self.icon.size)
22 .child(self.icon)
23 .children(self.decoration)
24 }
25}
26
27impl Component for DecoratedIcon {
28 fn scope() -> ComponentScope {
29 ComponentScope::Images
30 }
31
32 fn description() -> Option<&'static str> {
33 Some(
34 "An icon with an optional decoration overlay (like an X, triangle, or dot) that can be positioned relative to the icon",
35 )
36 }
37
38 fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
39 let decoration_x = IconDecoration::new(
40 IconDecorationKind::X,
41 cx.theme().colors().surface_background,
42 cx,
43 )
44 .color(cx.theme().status().error)
45 .position(Point {
46 x: px(-2.),
47 y: px(-2.),
48 });
49
50 let decoration_triangle = IconDecoration::new(
51 IconDecorationKind::Triangle,
52 cx.theme().colors().surface_background,
53 cx,
54 )
55 .color(cx.theme().status().error)
56 .position(Point {
57 x: px(-2.),
58 y: px(-2.),
59 });
60
61 let decoration_dot = IconDecoration::new(
62 IconDecorationKind::Dot,
63 cx.theme().colors().surface_background,
64 cx,
65 )
66 .color(cx.theme().status().error)
67 .position(Point {
68 x: px(-2.),
69 y: px(-2.),
70 });
71
72 Some(
73 v_flex()
74 .gap_6()
75 .children(vec![example_group_with_title(
76 "Decorations",
77 vec![
78 single_example(
79 "No Decoration",
80 DecoratedIcon::new(Icon::new(IconName::FileDoc), None)
81 .into_any_element(),
82 ),
83 single_example(
84 "X Decoration",
85 DecoratedIcon::new(Icon::new(IconName::FileDoc), Some(decoration_x))
86 .into_any_element(),
87 ),
88 single_example(
89 "Triangle Decoration",
90 DecoratedIcon::new(
91 Icon::new(IconName::FileDoc),
92 Some(decoration_triangle),
93 )
94 .into_any_element(),
95 ),
96 single_example(
97 "Dot Decoration",
98 DecoratedIcon::new(Icon::new(IconName::FileDoc), Some(decoration_dot))
99 .into_any_element(),
100 ),
101 ],
102 )])
103 .into_any_element(),
104 )
105 }
106}