From 5e7954f152484c5465d069a55e901fa186c30ec2 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Sat, 7 Oct 2023 11:55:10 -0400 Subject: [PATCH] Add `TrafficLights` component --- crates/storybook2/src/stories/components.rs | 1 + .../src/stories/components/traffic_lights.rs | 28 +++++++ crates/storybook2/src/story_selector.rs | 2 + crates/ui2/src/components.rs | 2 + crates/ui2/src/components/traffic_lights.rs | 84 +++++++++++++++++++ 5 files changed, 117 insertions(+) create mode 100644 crates/storybook2/src/stories/components/traffic_lights.rs create mode 100644 crates/ui2/src/components/traffic_lights.rs diff --git a/crates/storybook2/src/stories/components.rs b/crates/storybook2/src/stories/components.rs index 0e522a2fc11f4c7162be167b7cec67ad7be7eac8..f097ea47276d8fc5deac5e70d62acd818b6b5791 100644 --- a/crates/storybook2/src/stories/components.rs +++ b/crates/storybook2/src/stories/components.rs @@ -8,4 +8,5 @@ pub mod tab; pub mod tab_bar; pub mod terminal; pub mod toolbar; +pub mod traffic_lights; pub mod workspace; diff --git a/crates/storybook2/src/stories/components/traffic_lights.rs b/crates/storybook2/src/stories/components/traffic_lights.rs new file mode 100644 index 0000000000000000000000000000000000000000..056e258aaaba5145bfa90e51fe0d404f6dab8b07 --- /dev/null +++ b/crates/storybook2/src/stories/components/traffic_lights.rs @@ -0,0 +1,28 @@ +use std::marker::PhantomData; + +use ui::prelude::*; +use ui::TrafficLights; + +use crate::story::Story; + +#[derive(Element)] +pub struct TrafficLightsStory { + state_type: PhantomData, +} + +impl TrafficLightsStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, TrafficLights>(cx)) + .child(Story::label(cx, "Default")) + .child(TrafficLights::new()) + .child(Story::label(cx, "Unfocused")) + .child(TrafficLights::new().window_has_focus(false)) + } +} diff --git a/crates/storybook2/src/story_selector.rs b/crates/storybook2/src/story_selector.rs index 6acbb975848f151887cb1bd103d02a8bf5f470a3..761d4d78d6a0dcd2ac9d840277d9747b9ca6261c 100644 --- a/crates/storybook2/src/story_selector.rs +++ b/crates/storybook2/src/story_selector.rs @@ -46,6 +46,7 @@ pub enum ComponentStory { TabBar, Terminal, Toolbar, + TrafficLights, Workspace, } @@ -66,6 +67,7 @@ impl ComponentStory { Self::TabBar => components::tab_bar::TabBarStory::new().into_any(), Self::Terminal => components::terminal::TerminalStory::new().into_any(), Self::Toolbar => components::toolbar::ToolbarStory::new().into_any(), + Self::TrafficLights => components::traffic_lights::TrafficLightsStory::new().into_any(), Self::Workspace => components::workspace::WorkspaceStory::new().into_any(), } } diff --git a/crates/ui2/src/components.rs b/crates/ui2/src/components.rs index 094dae076f9c28a0794112199b166b8571645293..2a58ec5f1ecf45c81f66462ac96e85895f180fbb 100644 --- a/crates/ui2/src/components.rs +++ b/crates/ui2/src/components.rs @@ -13,6 +13,7 @@ mod tab; mod tab_bar; mod terminal; mod toolbar; +mod traffic_lights; mod workspace; pub use assistant_panel::*; @@ -30,4 +31,5 @@ pub use tab::*; pub use tab_bar::*; pub use terminal::*; pub use toolbar::*; +pub use traffic_lights::*; pub use workspace::*; diff --git a/crates/ui2/src/components/traffic_lights.rs b/crates/ui2/src/components/traffic_lights.rs new file mode 100644 index 0000000000000000000000000000000000000000..122171fdf53f9ace5975fd7ce81149277b7951ff --- /dev/null +++ b/crates/ui2/src/components/traffic_lights.rs @@ -0,0 +1,84 @@ +use std::marker::PhantomData; + +use crate::prelude::*; +use crate::{theme, token, SystemColor}; + +#[derive(Clone, Copy)] +enum TrafficLightColor { + Red, + Yellow, + Green, +} + +#[derive(Element)] +struct TrafficLight { + state_type: PhantomData, + color: TrafficLightColor, + window_has_focus: bool, +} + +impl TrafficLight { + fn new(color: TrafficLightColor, window_has_focus: bool) -> Self { + Self { + state_type: PhantomData, + color, + window_has_focus, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + let theme = theme(cx); + let system_color = SystemColor::new(); + + let fill = match (self.window_has_focus, self.color) { + (true, TrafficLightColor::Red) => system_color.mac_os_traffic_light_red, + (true, TrafficLightColor::Yellow) => system_color.mac_os_traffic_light_yellow, + (true, TrafficLightColor::Green) => system_color.mac_os_traffic_light_green, + (false, _) => theme.lowest.base.active.background, + }; + + div().w_3().h_3().rounded_full().fill(fill) + } +} + +#[derive(Element)] +pub struct TrafficLights { + state_type: PhantomData, + window_has_focus: bool, +} + +impl TrafficLights { + pub fn new() -> Self { + Self { + state_type: PhantomData, + window_has_focus: true, + } + } + + pub fn window_has_focus(mut self, window_has_focus: bool) -> Self { + self.window_has_focus = window_has_focus; + self + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + let theme = theme(cx); + let token = token(); + + div() + .flex() + .items_center() + .gap_2() + .child(TrafficLight::new( + TrafficLightColor::Red, + self.window_has_focus, + )) + .child(TrafficLight::new( + TrafficLightColor::Yellow, + self.window_has_focus, + )) + .child(TrafficLight::new( + TrafficLightColor::Green, + self.window_has_focus, + )) + } +}