Checkpoint

Marshall Bowers created

Change summary

crates/gpui3/src/elements/div.rs               |  2 
crates/gpui3_macros/src/derive_element.rs      | 38 ++++++++-
crates/gpui3_macros/src/gpui3_macros.rs        |  2 
crates/storybook2/src/stories/kitchen_sink.rs  |  4 
crates/storybook2/src/stories/z_index.rs       |  4 
crates/storybook2/src/story_selector.rs        |  8 +-
crates/ui2/src/components/assistant_panel.rs   |  4 
crates/ui2/src/components/breadcrumb.rs        |  4 
crates/ui2/src/components/buffer.rs            |  4 
crates/ui2/src/components/chat_panel.rs        |  6 
crates/ui2/src/components/collab_panel.rs      |  4 
crates/ui2/src/components/command_palette.rs   |  4 
crates/ui2/src/components/context_menu.rs      |  4 
crates/ui2/src/components/editor_pane.rs       |  2 
crates/ui2/src/components/facepile.rs          |  4 
crates/ui2/src/components/icon_button.rs       |  8 +-
crates/ui2/src/components/keybinding.rs        |  6 
crates/ui2/src/components/language_selector.rs |  4 
crates/ui2/src/components/list.rs              | 23 +++--
crates/ui2/src/components/multi_buffer.rs      |  4 
crates/ui2/src/components/palette.rs           |  6 
crates/ui2/src/components/panel.rs             |  4 
crates/ui2/src/components/panes.rs             |  8 +-
crates/ui2/src/components/player_stack.rs      |  2 
crates/ui2/src/components/project_panel.rs     |  4 
crates/ui2/src/components/recent_projects.rs   |  4 
crates/ui2/src/components/status_bar.rs        | 48 ++++++-----
crates/ui2/src/components/tab.rs               |  4 
crates/ui2/src/components/tab_bar.rs           |  4 
crates/ui2/src/components/terminal.rs          |  4 
crates/ui2/src/components/theme_selector.rs    |  4 
crates/ui2/src/components/title_bar.rs         |  4 
crates/ui2/src/components/toast.rs             |  4 
crates/ui2/src/components/toolbar.rs           |  4 
crates/ui2/src/components/traffic_lights.rs    |  6 
crates/ui2/src/components/workspace.rs         | 75 ++++++++++++++-----
crates/ui2/src/element_ext.rs                  | 10 ++
crates/ui2/src/elements/avatar.rs              |  4 
crates/ui2/src/elements/button.rs              | 29 +++++--
crates/ui2/src/elements/details.rs             |  4 
crates/ui2/src/elements/icon.rs                |  4 
crates/ui2/src/elements/input.rs               |  4 
crates/ui2/src/elements/label.rs               |  4 
crates/ui2/src/elements/tool_divider.rs        |  2 
44 files changed, 237 insertions(+), 148 deletions(-)

Detailed changes

crates/gpui3/src/elements/div.rs 🔗

@@ -196,7 +196,7 @@ impl<V: 'static + Send + Sync, Marker: 'static + Send + Sync> Styled for Div<V,
 
 impl<V: Send + Sync + 'static> IdentifiedElement for Div<V, HasId> {}
 
-impl<V: Send + Sync + 'static> Interactive<V> for Div<V, HasId> {
+impl<V: Send + Sync + 'static, Marker: 'static + Send + Sync> Interactive<V> for Div<V, Marker> {
     fn listeners(&mut self) -> &mut MouseEventListeners<V> {
         &mut self.listeners
     }

crates/gpui3_macros/src/derive_element.rs 🔗

@@ -6,12 +6,35 @@ pub fn derive_element(input: TokenStream) -> TokenStream {
     let ast = parse_macro_input!(input as DeriveInput);
     let type_name = ast.ident;
 
+    let mut logme = false;
     let mut state_type = quote! { () };
 
     for param in &ast.generics.params {
         if let GenericParam::Type(type_param) = param {
             let type_ident = &type_param.ident;
             state_type = quote! {#type_ident};
+            break;
+        }
+    }
+
+    let attrs = &ast.attrs;
+    for attr in attrs {
+        if attr.path.is_ident("element") {
+            match attr.parse_meta() {
+                Ok(syn::Meta::List(i)) => {
+                    for nested_meta in i.nested {
+                        if let syn::NestedMeta::Meta(syn::Meta::NameValue(nv)) = nested_meta {
+                            if nv.path.is_ident("view_state") {
+                                if let syn::Lit::Str(lit_str) = nv.lit {
+                                    state_type = lit_str.value().parse().unwrap();
+                                    logme = true;
+                                }
+                            }
+                        }
+                    }
+                }
+                _ => (),
+            }
         }
     }
 
@@ -30,29 +53,32 @@ pub fn derive_element(input: TokenStream) -> TokenStream {
 
             fn layout(
                 &mut self,
-                state: &mut #state_type,
+                view_state: &mut Self::ViewState,
                 element_state: Option<Self::ElementState>,
                 cx: &mut gpui3::ViewContext<Self::ViewState>,
             ) -> (gpui3::LayoutId, Self::ElementState) {
                 use gpui3::IntoAnyElement;
 
-                let mut rendered_element = self.render(cx).into_any();
-                let layout_id = rendered_element.layout(state, cx);
+                let mut rendered_element = self.render(view_state, cx).into_any();
+                let layout_id = rendered_element.layout(view_state, cx);
                 (layout_id, rendered_element)
             }
 
             fn paint(
                 &mut self,
                 bounds: gpui3::Bounds<gpui3::Pixels>,
-                state: &mut Self::ViewState,
+                view_state: &mut Self::ViewState,
                 element_state: &mut Self::ElementState,
                 cx: &mut gpui3::ViewContext<Self::ViewState>,
             ) {
-                // TODO: Where do we get the `offset` from?
-                element_state.paint(state, None, cx)
+                element_state.paint(view_state, None, cx)
             }
         }
     };
 
+    if logme {
+        println!(">>>>>>>>>>>>>>>>>>>>>>\n{}", gen);
+    }
+
     gen.into()
 }

crates/gpui3_macros/src/gpui3_macros.rs 🔗

@@ -8,7 +8,7 @@ pub fn style_helpers(args: TokenStream) -> TokenStream {
     style_helpers::style_helpers(args)
 }
 
-#[proc_macro_derive(Element, attributes(element_crate))]
+#[proc_macro_derive(Element, attributes(element))]
 pub fn derive_element(input: TokenStream) -> TokenStream {
     derive_element::derive_element(input)
 }

crates/storybook2/src/stories/kitchen_sink.rs 🔗

@@ -18,9 +18,9 @@ impl<S: 'static + Send + Sync + Clone> KitchenSinkStory<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let element_stories = ElementStory::iter().map(|selector| selector.story());
-        let component_stories = ComponentStory::iter().map(|selector| selector.story());
+        let component_stories = ComponentStory::iter().map(|selector| selector.story(cx));
 
         Story::container(cx)
             .overflow_y_scroll(ScrollState::default())

crates/storybook2/src/stories/z_index.rs 🔗

@@ -19,7 +19,7 @@ impl<S: 'static + Send + Sync> ZIndexStory<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         Story::container(cx)
             .child(Story::title(cx, "z-index"))
             .child(
@@ -103,7 +103,7 @@ impl<S: 'static + Send + Sync> ZIndexExample<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         div()
             .relative()
             .size_full()

crates/storybook2/src/story_selector.rs 🔗

@@ -65,7 +65,7 @@ pub enum ComponentStory {
 }
 
 impl ComponentStory {
-    pub fn story<S: 'static + Send + Sync + Clone>(&self) -> AnyElement<S> {
+    pub fn story<S: 'static + Send + Sync + Clone>(&self, cx: &mut WindowContext) -> AnyElement<S> {
         match self {
             Self::AssistantPanel => ui::AssistantPanelStory::new().into_any(),
             Self::Buffer => ui::BufferStory::new().into_any(),
@@ -90,7 +90,7 @@ impl ComponentStory {
             Self::Toast => ui::ToastStory::new().into_any(),
             Self::Toolbar => ui::ToolbarStory::new().into_any(),
             Self::TrafficLights => ui::TrafficLightsStory::new().into_any(),
-            Self::Workspace => ui::WorkspaceStory::new().into_any(),
+            Self::Workspace => ui::workspace_story(cx).into_any().into_any(),
         }
     }
 }
@@ -131,10 +131,10 @@ impl FromStr for StorySelector {
 }
 
 impl StorySelector {
-    pub fn story<S: 'static + Send + Sync + Clone>(&self) -> AnyElement<S> {
+    pub fn story<S: 'static + Send + Sync + Clone>(&self, cx: &mut WindowContext) -> AnyElement<S> {
         match self {
             Self::Element(element_story) => element_story.story(),
-            Self::Component(component_story) => component_story.story(),
+            Self::Component(component_story) => component_story.story(cx),
             Self::KitchenSink => crate::stories::kitchen_sink::KitchenSinkStory::new().into_any(),
         }
     }

crates/ui2/src/components/assistant_panel.rs 🔗

@@ -26,7 +26,7 @@ impl<S: 'static + Send + Sync + Clone> AssistantPanel<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         struct PanelPayload {
@@ -110,7 +110,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, AssistantPanel<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/breadcrumb.rs 🔗

@@ -31,7 +31,7 @@ impl<S: 'static + Send + Sync + Clone> Breadcrumb<S> {
             .text_color(HighlightColor::Default.hsla(theme))
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, view_state: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         let symbols_len = self.symbols.len();
@@ -99,7 +99,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, view_state: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             let theme = theme(cx);
 
             Story::container(cx)

crates/ui2/src/components/buffer.rs 🔗

@@ -224,7 +224,7 @@ impl<S: 'static + Send + Sync + Clone> Buffer<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let rows = self.render_rows(cx);
 
@@ -263,7 +263,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             let theme = theme(cx);
 
             Story::container(cx)

crates/ui2/src/components/chat_panel.rs 🔗

@@ -25,7 +25,7 @@ impl<S: 'static + Send + Sync + Clone> ChatPanel<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         div()
@@ -89,7 +89,7 @@ impl<S: 'static + Send + Sync + Clone> ChatMessage<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         div()
             .flex()
             .flex_col()
@@ -130,7 +130,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, ChatPanel<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/collab_panel.rs 🔗

@@ -23,7 +23,7 @@ impl<S: 'static + Send + Sync + Clone> CollabPanel<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let color = ThemeColor::new(cx);
 
@@ -180,7 +180,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, CollabPanel<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/command_palette.rs 🔗

@@ -17,7 +17,7 @@ impl<S: 'static + Send + Sync + Clone> CommandPalette<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         div().child(
             Palette::new(self.scroll_state.clone())
                 .items(example_editor_actions())
@@ -49,7 +49,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, CommandPalette<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/context_menu.rs 🔗

@@ -43,7 +43,7 @@ impl<S: 'static + Send + Sync + Clone> ContextMenu<S> {
             items: items.into_iter().collect(),
         }
     }
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         v_stack()
@@ -87,7 +87,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, ContextMenu<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/editor_pane.rs 🔗

@@ -20,7 +20,7 @@ impl<S: 'static + Send + Sync + Clone> EditorPane<S> {
         Self { editor }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         struct LeftItemsPayload {
             path: PathBuf,
             symbols: Vec<Symbol>,

crates/ui2/src/components/facepile.rs 🔗

@@ -17,7 +17,7 @@ impl<S: 'static + Send + Sync> Facepile<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let player_count = self.players.len();
         let player_list = self.players.iter().enumerate().map(|(ix, player)| {
@@ -52,7 +52,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             let players = static_players();
 
             Story::container(cx)

crates/ui2/src/components/icon_button.rs 🔗

@@ -66,7 +66,7 @@ impl<S: 'static + Send + Sync> IconButton<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         let icon_color = match (self.state, self.color) {
@@ -80,9 +80,9 @@ impl<S: 'static + Send + Sync> IconButton<S> {
         }
 
         if let Some(click_handler) = self.handlers.click.clone() {
-            // div = div.on_click(MouseButton::Left, move |state, event, cx| {
-            //     click_handler(state, cx);
-            // });
+            div = div.on_mouse_down(MouseButton::Left, move |state, event, cx| {
+                click_handler(state, cx);
+            });
         }
 
         div.w_7()

crates/ui2/src/components/keybinding.rs 🔗

@@ -35,7 +35,7 @@ impl<S: 'static + Send + Sync + Clone> Keybinding<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         div()
             .flex()
             .gap_2()
@@ -72,7 +72,7 @@ impl<S: 'static + Send + Sync> Key<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         div()
@@ -189,7 +189,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             let all_modifier_permutations = ModifierKey::iter().permutations(2);
 
             Story::container(cx)

crates/ui2/src/components/language_selector.rs 🔗

@@ -17,7 +17,7 @@ impl<S: 'static + Send + Sync + Clone> LanguageSelector<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         div().child(
             Palette::new(self.scroll_state.clone())
                 .items(vec![
@@ -60,7 +60,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, LanguageSelector<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/list.rs 🔗

@@ -92,7 +92,7 @@ impl<S: 'static + Send + Sync + Clone> ListHeader<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let token = token();
         let system_color = SystemColor::new();
@@ -164,7 +164,7 @@ impl<S: 'static + Send + Sync + Clone> ListSubHeader<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let token = token();
 
@@ -237,11 +237,11 @@ impl<S: 'static + Send + Sync + Clone> From<ListSubHeader<S>> for ListItem<S> {
 }
 
 impl<S: 'static + Send + Sync + Clone> ListItem<S> {
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         match self {
-            ListItem::Entry(entry) => div().child(entry.render(cx)),
-            ListItem::Separator(separator) => div().child(separator.render(cx)),
-            ListItem::Header(header) => div().child(header.render(cx)),
+            ListItem::Entry(entry) => div().child(entry.render(view, cx)),
+            ListItem::Separator(separator) => div().child(separator.render(view, cx)),
+            ListItem::Header(header) => div().child(header.render(view, cx)),
         }
     }
 
@@ -346,7 +346,10 @@ impl<S: 'static + Send + Sync + Clone> ListEntry<S> {
         }
     }
 
-    fn disclosure_control(&mut self, cx: &mut ViewContext<S>) -> Option<impl Element<ViewState = S>> {
+    fn disclosure_control(
+        &mut self,
+        cx: &mut ViewContext<S>,
+    ) -> Option<impl Element<ViewState = S>> {
         let theme = theme(cx);
         let token = token();
 
@@ -369,7 +372,7 @@ impl<S: 'static + Send + Sync + Clone> ListEntry<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let token = token();
         let system_color = SystemColor::new();
@@ -437,7 +440,7 @@ impl<S: 'static + Send + Sync> ListSeparator<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let color = ThemeColor::new(cx);
 
         div().h_px().w_full().fill(color.border)
@@ -477,7 +480,7 @@ impl<S: 'static + Send + Sync + Clone> List<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let token = token();
         let is_toggleable = self.toggleable != Toggleable::NotToggleable;

crates/ui2/src/components/multi_buffer.rs 🔗

@@ -17,7 +17,7 @@ impl<S: 'static + Send + Sync + Clone> MultiBuffer<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         v_stack()
@@ -62,7 +62,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             let theme = theme(cx);
 
             Story::container(cx)

crates/ui2/src/components/palette.rs 🔗

@@ -47,7 +47,7 @@ impl<S: 'static + Send + Sync + Clone> Palette<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         v_stack()
@@ -134,7 +134,7 @@ impl<S: 'static + Send + Sync + Clone> PaletteItem<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         div()
@@ -172,7 +172,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, Palette<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/panel.rs 🔗

@@ -100,7 +100,7 @@ impl<S: 'static + Send + Sync> Panel<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let token = token();
         let theme = theme(cx);
 
@@ -165,7 +165,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, Panel<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/panes.rs 🔗

@@ -48,7 +48,7 @@ impl<S: 'static + Send + Sync> Pane<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         div()
@@ -89,7 +89,7 @@ impl<S: 'static + Send + Sync> PaneGroup<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         if !self.panes.is_empty() {
@@ -100,7 +100,7 @@ impl<S: 'static + Send + Sync> PaneGroup<S> {
                 .w_full()
                 .h_full()
                 .fill(theme.lowest.base.default.background)
-                .children(self.panes.iter_mut().map(|pane| pane.render(cx)));
+                .children(self.panes.iter_mut().map(|pane| pane.render(view, cx)));
 
             if self.split_direction == SplitDirection::Horizontal {
                 return el;
@@ -117,7 +117,7 @@ impl<S: 'static + Send + Sync> PaneGroup<S> {
                 .w_full()
                 .h_full()
                 .fill(theme.lowest.base.default.background)
-                .children(self.groups.iter_mut().map(|group| group.render(cx)));
+                .children(self.groups.iter_mut().map(|group| group.render(view, cx)));
 
             if self.split_direction == SplitDirection::Horizontal {
                 return el;

crates/ui2/src/components/player_stack.rs 🔗

@@ -17,7 +17,7 @@ impl<S: 'static + Send + Sync> PlayerStack<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let system_color = SystemColor::new();
         let player = self.player_with_call_status.get_player();
         self.player_with_call_status.get_call_status();

crates/ui2/src/components/project_panel.rs 🔗

@@ -20,7 +20,7 @@ impl<S: 'static + Send + Sync + Clone> ProjectPanel<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let color = ThemeColor::new(cx);
 
@@ -78,7 +78,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, ProjectPanel<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/recent_projects.rs 🔗

@@ -17,7 +17,7 @@ impl<S: 'static + Send + Sync + Clone> RecentProjects<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         div().child(
             Palette::new(self.scroll_state.clone())
                 .items(vec![
@@ -56,7 +56,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, RecentProjects<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/status_bar.rs 🔗

@@ -1,8 +1,7 @@
-use std::marker::PhantomData;
 use std::sync::Arc;
 
-use crate::prelude::*;
 use crate::{get_workspace_state, Button, Icon, IconButton, IconColor, ToolDivider};
+use crate::{prelude::*, Workspace};
 
 #[derive(Default, PartialEq)]
 pub enum Tool {
@@ -30,17 +29,17 @@ impl Default for ToolGroup {
 }
 
 #[derive(Element)]
-pub struct StatusBar<S: 'static + Send + Sync + Clone> {
-    state_type: PhantomData<S>,
+#[element(view_state = "Workspace")]
+pub struct StatusBar {
     left_tools: Option<ToolGroup>,
     right_tools: Option<ToolGroup>,
     bottom_tools: Option<ToolGroup>,
 }
 
-impl<S: 'static + Send + Sync + Clone> StatusBar<S> {
+impl StatusBar {
     pub fn new() -> Self {
         Self {
-            state_type: PhantomData,
+            // state_type: PhantomData,
             left_tools: None,
             right_tools: None,
             bottom_tools: None,
@@ -83,7 +82,11 @@ impl<S: 'static + Send + Sync + Clone> StatusBar<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(
+        &mut self,
+        view: &mut Workspace,
+        cx: &mut ViewContext<Workspace>,
+    ) -> impl Element<ViewState = Workspace> {
         let theme = theme(cx);
 
         div()
@@ -94,34 +97,35 @@ impl<S: 'static + Send + Sync + Clone> StatusBar<S> {
             .justify_between()
             .w_full()
             .fill(theme.lowest.base.default.background)
-            .child(self.left_tools(&theme))
+            .child(self.left_tools(view, &theme))
             .child(self.right_tools(&theme))
     }
 
-    fn left_tools(&self, theme: &Theme) -> impl Element<ViewState = S> {
-        let workspace_state = get_workspace_state();
-
-        div()
+    fn left_tools(
+        &self,
+        workspace: &mut Workspace,
+        theme: &Theme,
+    ) -> impl Element<ViewState = Workspace> {
+        div::<Workspace>()
             .flex()
             .items_center()
             .gap_1()
             .child(
-                IconButton::new(Icon::FileTree)
-                    .when(workspace_state.is_project_panel_open(), |this| {
+                IconButton::<Workspace>::new(Icon::FileTree)
+                    .when(workspace.is_project_panel_open(), |this| {
                         this.color(IconColor::Accent)
                     })
-                    .on_click(|_, cx| {
-                        workspace_state.toggle_project_panel();
-                        cx.notify();
+                    .on_click(|workspace, cx| {
+                        workspace.toggle_project_panel(cx);
                     }),
             )
             .child(
-                IconButton::new(Icon::Hash)
-                    .when(workspace_state.is_collab_panel_open(), |this| {
+                IconButton::<Workspace>::new(Icon::Hash)
+                    .when(workspace.is_collab_panel_open(), |this| {
                         this.color(IconColor::Accent)
                     })
-                    .on_click(|_, cx| {
-                        workspace_state.toggle_collab_panel();
+                    .on_click(|workspace, cx| {
+                        workspace.toggle_collab_panel();
                         cx.notify();
                     }),
             )
@@ -129,7 +133,7 @@ impl<S: 'static + Send + Sync + Clone> StatusBar<S> {
             .child(IconButton::new(Icon::XCircle))
     }
 
-    fn right_tools(&self, theme: &Theme) -> impl Element<ViewState = S> {
+    fn right_tools(&self, theme: &Theme) -> impl Element<ViewState = Workspace> {
         let workspace_state = get_workspace_state();
 
         div()

crates/ui2/src/components/tab.rs 🔗

@@ -74,7 +74,7 @@ impl<S: 'static + Send + Sync + Clone> Tab<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let has_fs_conflict = self.fs_status == FileSystemStatus::Conflict;
         let is_deleted = self.fs_status == FileSystemStatus::Deleted;
@@ -157,7 +157,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             let git_statuses = GitStatus::iter();
             let fs_statuses = FileSystemStatus::iter();
 

crates/ui2/src/components/tab_bar.rs 🔗

@@ -23,7 +23,7 @@ impl<S: 'static + Send + Sync + Clone> TabBar<S> {
         self.scroll_state = scroll_state;
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let can_navigate_back = true;
         let can_navigate_forward = false;
@@ -105,7 +105,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, TabBar<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/terminal.rs 🔗

@@ -18,7 +18,7 @@ impl<S: 'static + Send + Sync + Clone> Terminal<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         let can_navigate_back = true;
@@ -109,7 +109,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, Terminal<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/theme_selector.rs 🔗

@@ -17,7 +17,7 @@ impl<S: 'static + Send + Sync + Clone> ThemeSelector<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         div().child(
             Palette::new(self.scroll_state.clone())
                 .items(vec![
@@ -61,7 +61,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, ThemeSelector<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/title_bar.rs 🔗

@@ -46,7 +46,7 @@ impl<S: 'static + Send + Sync + Clone> TitleBar<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         // let has_focus = cx.window_is_active();
         let has_focus = true;
@@ -139,7 +139,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, TitleBar<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/toast.rs 🔗

@@ -41,7 +41,7 @@ impl<S: 'static + Send + Sync> Toast<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let color = ThemeColor::new(cx);
 
         let mut div = div();
@@ -89,7 +89,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, Toast<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/toolbar.rs 🔗

@@ -27,7 +27,7 @@ impl<S: 'static + Send + Sync> Toolbar<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         div()
@@ -74,7 +74,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             let theme = theme(cx);
 
             struct LeftItemsPayload {

crates/ui2/src/components/traffic_lights.rs 🔗

@@ -26,7 +26,7 @@ impl<S: 'static + Send + Sync> TrafficLight<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let system_color = SystemColor::new();
 
@@ -60,7 +60,7 @@ impl<S: 'static + Send + Sync> TrafficLights<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let token = token();
 
@@ -104,7 +104,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, TrafficLights<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/workspace.rs 🔗

@@ -3,7 +3,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::{Arc, OnceLock};
 
 use chrono::DateTime;
-use gpui3::{px, relative, rems, Size};
+use gpui3::{px, relative, rems, view, Context, Size, View};
 
 use crate::prelude::*;
 use crate::{
@@ -105,19 +105,26 @@ pub fn get_workspace_state() -> &'static WorkspaceState {
     state
 }
 
-#[derive(Element)]
-pub struct WorkspaceElement<S: 'static + Send + Sync + Clone> {
-    state_type: PhantomData<S>,
+// #[derive(Element)]
+#[derive(Clone)]
+pub struct Workspace {
+    show_project_panel: bool,
+    show_collab_panel: bool,
     left_panel_scroll_state: ScrollState,
     right_panel_scroll_state: ScrollState,
     tab_bar_scroll_state: ScrollState,
     bottom_panel_scroll_state: ScrollState,
 }
 
-impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
+fn workspace<P: 'static>(cx: &mut WindowContext) -> View<Workspace, P> {
+    view(cx.entity(|cx| Workspace::new()), Workspace::render)
+}
+
+impl Workspace {
     pub fn new() -> Self {
         Self {
-            state_type: PhantomData,
+            show_project_panel: true,
+            show_collab_panel: false,
             left_panel_scroll_state: ScrollState::default(),
             right_panel_scroll_state: ScrollState::default(),
             tab_bar_scroll_state: ScrollState::default(),
@@ -125,7 +132,31 @@ impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
         }
     }
 
-    pub fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    pub fn is_project_panel_open(&self) -> bool {
+        dbg!(self.show_project_panel)
+    }
+
+    pub fn toggle_project_panel(&mut self, cx: &mut ViewContext<Self>) {
+        self.show_project_panel = !self.show_project_panel;
+
+        self.show_collab_panel = false;
+
+        dbg!(self.show_project_panel);
+
+        cx.notify();
+    }
+
+    pub fn is_collab_panel_open(&self) -> bool {
+        self.show_collab_panel
+    }
+
+    pub fn toggle_collab_panel(&mut self) {
+        self.show_collab_panel = !self.show_collab_panel;
+
+        self.show_project_panel = false;
+    }
+
+    pub fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element<ViewState = Self> {
         let theme = theme(cx).clone();
 
         let workspace_state = get_workspace_state();
@@ -341,21 +372,23 @@ pub use stories::*;
 mod stories {
     use super::*;
 
-    #[derive(Element)]
-    pub struct WorkspaceStory<S: 'static + Send + Sync + Clone> {
-        state_type: PhantomData<S>,
-    }
+    // #[derive(Element)]
+    // pub struct WorkspaceStory<S: 'static + Send + Sync + Clone> {
+    //     state_type: PhantomData<S>,
+    // }
 
-    impl<S: 'static + Send + Sync + Clone> WorkspaceStory<S> {
-        pub fn new() -> Self {
-            Self {
-                state_type: PhantomData,
-            }
-        }
+    pub struct WorkspaceStory<P> {
+        workspace: View<Workspace, P>,
+    }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
-            // Just render the workspace without any story boilerplate.
-            WorkspaceElement::new()
-        }
+    pub fn workspace_story<P: 'static + Send + Sync>(cx: &mut WindowContext) -> View<WorkspaceStory<P>, P> {
+        todo!()
+        // let workspace = workspace::<P>(cx);
+        // view(
+        //     cx.entity(|cx| WorkspaceStory {
+        //         workspace,
+        //     }),
+        //     |view, cx| view.workspace.clone(),
+        // )
     }
 }

crates/ui2/src/element_ext.rs 🔗

@@ -13,6 +13,16 @@ pub trait ElementExt<S: 'static + Send + Sync>: Element<ViewState = S> {
         }
         self
     }
+
+    // fn when_some<T, U>(mut self, option: Option<T>, then: impl FnOnce(Self, T) -> U) -> U
+    // where
+    //     Self: Sized,
+    // {
+    //     if let Some(value) = option {
+    //         self = then(self, value);
+    //     }
+    //     self
+    // }
 }
 
 impl<S: 'static + Send + Sync, E: Element<ViewState = S>> ElementExt<S> for E {}

crates/ui2/src/elements/avatar.rs 🔗

@@ -26,7 +26,7 @@ impl<S: 'static + Send + Sync> Avatar<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         let mut img = img();
@@ -64,7 +64,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, Avatar<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/elements/button.rs 🔗

@@ -1,7 +1,7 @@
 use std::marker::PhantomData;
 use std::sync::Arc;
 
-use gpui3::{DefiniteLength, Hsla, Interactive, MouseButton, WindowContext};
+use gpui3::{DefiniteLength, Hsla, WindowContext};
 
 use crate::prelude::*;
 use crate::{h_stack, theme, Icon, IconColor, IconElement, Label, LabelColor, LabelSize};
@@ -160,7 +160,7 @@ impl<S: 'static + Send + Sync + Clone> Button<S> {
         self.icon.map(|i| IconElement::new(i).color(icon_color))
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let icon_color = self.icon_color();
         let system_color = SystemColor::new();
@@ -195,11 +195,20 @@ impl<S: 'static + Send + Sync + Clone> Button<S> {
             el = el.w(width).justify_center();
         }
 
-        if let Some(click_handler) = self.handlers.click.clone() {
-            // el = el.on_click(MouseButton::Left, move |state, event, cx| {
-            //     click_handler(state, cx);
-            // });
-        }
+        // el.when_some(self.handlers.click.clone(), |el, click_handler| {
+        //     el.id(0)
+        //         .on_click(MouseButton::Left, move |state, event, cx| {
+        //             click_handler(state, cx);
+        //         })
+        // });
+
+        // if let Some(click_handler) = self.handlers.click.clone() {
+        //     el = el
+        //         .id(0)
+        //         .on_click(MouseButton::Left, move |state, event, cx| {
+        //             click_handler(state, cx);
+        //         });
+        // }
 
         el
     }
@@ -229,7 +238,11 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(
+            &mut self,
+            _view: &mut S,
+            cx: &mut ViewContext<S>,
+        ) -> impl Element<ViewState = S> {
             let states = InteractionState::iter();
 
             Story::container(cx)

crates/ui2/src/elements/details.rs 🔗

@@ -24,7 +24,7 @@ impl<S: 'static + Send + Sync + Clone> Details<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         div()
@@ -60,7 +60,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, Details<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/elements/icon.rs 🔗

@@ -170,7 +170,7 @@ impl<S: 'static + Send + Sync> IconElement<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
         let fill = self.color.color(theme);
 
@@ -206,7 +206,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             let icons = Icon::iter();
 
             Story::container(cx)

crates/ui2/src/elements/input.rs 🔗

@@ -45,7 +45,7 @@ impl<S: 'static + Send + Sync> Input<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         let text_el;
@@ -128,7 +128,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, Input<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/elements/label.rs 🔗

@@ -90,7 +90,7 @@ impl<S: 'static + Send + Sync + Clone> Label<S> {
         self
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         let highlight_color = theme.lowest.accent.default.foreground;
@@ -185,7 +185,7 @@ mod stories {
             }
         }
 
-        fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, Label<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/elements/tool_divider.rs 🔗

@@ -15,7 +15,7 @@ impl<S: 'static + Send + Sync> ToolDivider<S> {
         }
     }
 
-    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
         let theme = theme(cx);
 
         div().w_px().h_3().fill(theme.lowest.base.default.border)