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 theme = theme(cx);
30
31 let fill = match (self.window_has_focus, self.color) {
32 (true, TrafficLightColor::Red) => theme.mac_os_traffic_light_red,
33 (true, TrafficLightColor::Yellow) => theme.mac_os_traffic_light_yellow,
34 (true, TrafficLightColor::Green) => theme.mac_os_traffic_light_green,
35 (false, _) => theme.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 div()
63 .flex()
64 .items_center()
65 .gap_2()
66 .child(TrafficLight::new(
67 TrafficLightColor::Red,
68 self.window_has_focus,
69 ))
70 .child(TrafficLight::new(
71 TrafficLightColor::Yellow,
72 self.window_has_focus,
73 ))
74 .child(TrafficLight::new(
75 TrafficLightColor::Green,
76 self.window_has_focus,
77 ))
78 }
79}
80
81#[cfg(feature = "stories")]
82pub use stories::*;
83
84#[cfg(feature = "stories")]
85mod stories {
86 use crate::Story;
87
88 use super::*;
89
90 #[derive(Element)]
91 pub struct TrafficLightsStory<S: 'static + Send + Sync> {
92 state_type: PhantomData<S>,
93 }
94
95 impl<S: 'static + Send + Sync> TrafficLightsStory<S> {
96 pub fn new() -> Self {
97 Self {
98 state_type: PhantomData,
99 }
100 }
101
102 fn render(
103 &mut self,
104 _view: &mut S,
105 cx: &mut ViewContext<S>,
106 ) -> impl Element<ViewState = S> {
107 Story::container(cx)
108 .child(Story::title_for::<_, TrafficLights<S>>(cx))
109 .child(Story::label(cx, "Default"))
110 .child(TrafficLights::new())
111 .child(Story::label(cx, "Unfocused"))
112 .child(TrafficLights::new().window_has_focus(false))
113 }
114 }
115}