1use std::marker::PhantomData;
2
3use crate::prelude::*;
4
5#[derive(Clone, Copy)]
6enum TrafficLightColor {
7 Red,
8 Yellow,
9 Green,
10}
11
12#[derive(Element)]
13struct TrafficLight<S: 'static + Send + Sync> {
14 state_type: PhantomData<S>,
15 color: TrafficLightColor,
16 window_has_focus: bool,
17}
18
19impl<S: 'static + Send + Sync> TrafficLight<S> {
20 fn new(color: TrafficLightColor, window_has_focus: bool) -> Self {
21 Self {
22 state_type: PhantomData,
23 color,
24 window_has_focus,
25 }
26 }
27
28 fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
29 let color = ThemeColor::new(cx);
30
31 let fill = match (self.window_has_focus, self.color) {
32 (true, TrafficLightColor::Red) => color.mac_os_traffic_light_red,
33 (true, TrafficLightColor::Yellow) => color.mac_os_traffic_light_yellow,
34 (true, TrafficLightColor::Green) => color.mac_os_traffic_light_green,
35 (false, _) => color.filled_element,
36 };
37
38 div().w_3().h_3().rounded_full().bg(fill)
39 }
40}
41
42#[derive(Element)]
43pub struct TrafficLights<S: 'static + Send + Sync> {
44 state_type: PhantomData<S>,
45 window_has_focus: bool,
46}
47
48impl<S: 'static + Send + Sync> TrafficLights<S> {
49 pub fn new() -> Self {
50 Self {
51 state_type: PhantomData,
52 window_has_focus: true,
53 }
54 }
55
56 pub fn window_has_focus(mut self, window_has_focus: bool) -> Self {
57 self.window_has_focus = window_has_focus;
58 self
59 }
60
61 fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
62 let color = ThemeColor::new(cx);
63
64 div()
65 .flex()
66 .items_center()
67 .gap_2()
68 .child(TrafficLight::new(
69 TrafficLightColor::Red,
70 self.window_has_focus,
71 ))
72 .child(TrafficLight::new(
73 TrafficLightColor::Yellow,
74 self.window_has_focus,
75 ))
76 .child(TrafficLight::new(
77 TrafficLightColor::Green,
78 self.window_has_focus,
79 ))
80 }
81}
82
83#[cfg(feature = "stories")]
84pub use stories::*;
85
86#[cfg(feature = "stories")]
87mod stories {
88 use crate::Story;
89
90 use super::*;
91
92 #[derive(Element)]
93 pub struct TrafficLightsStory<S: 'static + Send + Sync> {
94 state_type: PhantomData<S>,
95 }
96
97 impl<S: 'static + Send + Sync> TrafficLightsStory<S> {
98 pub fn new() -> Self {
99 Self {
100 state_type: PhantomData,
101 }
102 }
103
104 fn render(
105 &mut self,
106 _view: &mut S,
107 cx: &mut ViewContext<S>,
108 ) -> impl Element<ViewState = S> {
109 Story::container(cx)
110 .child(Story::title_for::<_, TrafficLights<S>>(cx))
111 .child(Story::label(cx, "Default"))
112 .child(TrafficLights::new())
113 .child(Story::label(cx, "Unfocused"))
114 .child(TrafficLights::new().window_has_focus(false))
115 }
116 }
117}