From 9cb8ce172d90248c3c50cd2fba64c528c7dbcf7c Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 3 Nov 2023 18:33:17 +0200 Subject: [PATCH 01/23] Refresh diagnostics inside the tab --- Cargo.lock | 1 + crates/diagnostics/Cargo.toml | 1 + crates/diagnostics/src/diagnostics.rs | 5 +++++ crates/editor/src/editor_tests.rs | 2 +- crates/editor/src/items.rs | 4 ++-- 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff2a43d99d39b55bf7c600cf4affefa61466c62b..e33edf29f0076a66e8c622558cfacdbb237c3b6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2461,6 +2461,7 @@ dependencies = [ "editor", "gpui", "language", + "log", "lsp", "postage", "project", diff --git a/crates/diagnostics/Cargo.toml b/crates/diagnostics/Cargo.toml index b0b2450f053fb9c8925b4bfe0131af24d5d24fa7..26a2a82999d2374e65ce5e061ee23ab91c366455 100644 --- a/crates/diagnostics/Cargo.toml +++ b/crates/diagnostics/Cargo.toml @@ -20,6 +20,7 @@ theme = { path = "../theme" } util = { path = "../util" } workspace = { path = "../workspace" } +log.workspace = true anyhow.workspace = true schemars.workspace = true serde.workspace = true diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 0b1c6f8470369cbe18538e15b362258756d1aaeb..865704275ba914b0fde572b8f77dbca0e35c032a 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -151,6 +151,7 @@ impl ProjectDiagnosticsEditor { ) -> Self { cx.subscribe(&project_handle, |this, _, event, cx| match event { project::Event::DiskBasedDiagnosticsFinished { language_server_id } => { + log::debug!("Disk based diagnostics finished for server {language_server_id}"); this.update_excerpts(Some(*language_server_id), cx); this.update_title(cx); } @@ -158,8 +159,11 @@ impl ProjectDiagnosticsEditor { language_server_id, path, } => { + log::debug!("Adding path {path:?} to update for server {language_server_id}"); this.paths_to_update .insert((path.clone(), *language_server_id)); + this.update_excerpts(Some(*language_server_id), cx); + this.update_title(cx); } _ => {} }) @@ -229,6 +233,7 @@ impl ProjectDiagnosticsEditor { language_server_id: Option, cx: &mut ViewContext, ) { + log::debug!("Updating excerpts for server {language_server_id:?}"); let mut paths = Vec::new(); self.paths_to_update.retain(|(path, server_id)| { if language_server_id diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index feca741737c26eb357b1188c0b09470b7768b180..fc16e52a1b27a2d2553b0cabe6cd023386e38477 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -34,7 +34,7 @@ use util::{ test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker}, }; use workspace::{ - item::{FollowableItem, Item, ItemHandle}, + item::{FollowableItem, Item}, NavigationEntry, ViewId, }; diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index c87606070e5660c90a7e53962098b4da923a2f1e..1b922848e061b8b162fc5c1f25babf5c3ce96c0e 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -33,9 +33,9 @@ use util::{ paths::{PathExt, FILE_ROW_COLUMN_DELIMITER}, ResultExt, TryFutureExt, }; -use workspace::item::{BreadcrumbText, FollowableItemHandle}; +use workspace::item::{BreadcrumbText, FollowableItemHandle, ItemHandle}; use workspace::{ - item::{FollowableItem, Item, ItemEvent, ItemHandle, ProjectItem}, + item::{FollowableItem, Item, ItemEvent, ProjectItem}, searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle}, ItemId, ItemNavHistory, Pane, StatusItemView, ToolbarItemLocation, ViewId, Workspace, WorkspaceId, From 6f8947a3d343a3cb8cc178fa7a95aef7ace6652b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 3 Nov 2023 18:42:37 +0200 Subject: [PATCH 02/23] Fix a compilation error --- crates/editor/src/editor_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index fc16e52a1b27a2d2553b0cabe6cd023386e38477..feca741737c26eb357b1188c0b09470b7768b180 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -34,7 +34,7 @@ use util::{ test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker}, }; use workspace::{ - item::{FollowableItem, Item}, + item::{FollowableItem, Item, ItemHandle}, NavigationEntry, ViewId, }; From 918d123284c71fc8f1989e862f7a96a41447fd24 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 3 Nov 2023 21:51:04 +0200 Subject: [PATCH 03/23] Fix the test --- crates/diagnostics/src/diagnostics.rs | 38 +++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 865704275ba914b0fde572b8f77dbca0e35c032a..a3d779531b5690be0dc60808085bc099768df6bd 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -1306,25 +1306,6 @@ mod tests { cx, ) .unwrap(); - project - .update_diagnostic_entries( - server_id_2, - PathBuf::from("/test/main.js"), - None, - vec![DiagnosticEntry { - range: Unclipped(PointUtf16::new(1, 0))..Unclipped(PointUtf16::new(1, 1)), - diagnostic: Diagnostic { - message: "warning 1".to_string(), - severity: DiagnosticSeverity::ERROR, - is_primary: true, - is_disk_based: true, - group_id: 2, - ..Default::default() - }, - }], - cx, - ) - .unwrap(); }); // The first language server finishes @@ -1358,6 +1339,25 @@ mod tests { // The second language server finishes project.update(cx, |project, cx| { + project + .update_diagnostic_entries( + server_id_2, + PathBuf::from("/test/main.js"), + None, + vec![DiagnosticEntry { + range: Unclipped(PointUtf16::new(1, 0))..Unclipped(PointUtf16::new(1, 1)), + diagnostic: Diagnostic { + message: "warning 1".to_string(), + severity: DiagnosticSeverity::ERROR, + is_primary: true, + is_disk_based: true, + group_id: 2, + ..Default::default() + }, + }], + cx, + ) + .unwrap(); project.disk_based_diagnostics_finished(server_id_2, cx); }); From 740e2cc5bfbf0e3b7b3796f70657dec28445727e Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 3 Nov 2023 16:28:54 -0400 Subject: [PATCH 04/23] Start on ui root doc Co-Authored-By: Marshall Bowers <1486634+maxdeviant@users.noreply.github.com> --- crates/ui2/src/lib.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/ui2/src/lib.rs b/crates/ui2/src/lib.rs index 5d0a57c6d90fca078982941193d87828e706f726..fb25d21bf0531b40bc90fc081277968168dad7e9 100644 --- a/crates/ui2/src/lib.rs +++ b/crates/ui2/src/lib.rs @@ -9,6 +9,37 @@ //! //! Expect some inconsistencies from component to component as we work out the best way to build these components. //! +//! ## Getting Started +//! +//! This is a quick primer to get you started using the UI components. +//! +//! You shouldn't need to construct an element from scratch very often. If you find +//! yourself manually styling things like hover, text colors, etc, you should +//! probably check that there isn't already a base component for whatever you are building. +//! +//! Here is an into to some of the most common elements: +//! +//! ### Text +//! +//! For generic UI text most frequently you will use a [`Label`] component. +//! +//! ```rust +//! use ui2::prelude::*; +//! use ui2::{Label, LabelColor}; +//! +//! pub fn render_some_ui_text() -> impl Component { +//! div().p_2().child( +//! Label::new("Hello World") +//! .color(LabelColor::Muted) +//! ) +//! } +//! ``` +//! +//! ### Interactive Elements +//! +//! - Icon: To make an icon interactive, use [`IconButton`]. +//! - Button: To make a button interactive, use [`Button`]. +//! //! ## Design Philosophy //! //! Work in Progress! From d500b01aed009a872e35f4abeed68c91f2d6973d Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 3 Nov 2023 16:37:22 -0400 Subject: [PATCH 05/23] Add docs burndown list Co-Authored-By: Marshall Bowers <1486634+maxdeviant@users.noreply.github.com> --- crates/ui2/src/lib.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/crates/ui2/src/lib.rs b/crates/ui2/src/lib.rs index fb25d21bf0531b40bc90fc081277968168dad7e9..d53469638a0a3f82520546a11edc0e0321d4a580 100644 --- a/crates/ui2/src/lib.rs +++ b/crates/ui2/src/lib.rs @@ -1,3 +1,29 @@ +// TODO: +// Document these: +// - [ ] - label +// - [ ] - button +// - [ ] - icon_button +// - [ ] - icon +// - [ ] - list +// - [ ] - avatar +// - [ ] - panel +// - [ ] - modal +// - [ ] - palette +// - [ ] - input +// - [ ] - facepile +// - [ ] - player +// - [ ] - stacks +// - [ ] - context menu +// - [ ] - input +// - [ ] - textarea (not built) +// - [ ] - indicator +// - [ ] - public actor +// - [ ] - keybinding +// - [ ] - tab +// - [ ] - toast +// - [ ] - status_toast (maybe not built?) +// - [ ] - notification_toast + //! # UI – Zed UI Primitives & Components //! //! This crate provides a set of UI primitives and components that are used to build all of the elements in Zed's UI. From 287ea0a6e466e5bc620b628ffe39771d4e819970 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 3 Nov 2023 22:21:00 +0100 Subject: [PATCH 06/23] Allow deriving `Serialize` and `Deserialize` on generated refinement (#3227) This PR adds support for deriving `Serialize` and `Deserialize` on the refinement type generated by `#[derive(Refineable)]`. Release Notes: - N/A --- .../src/derive_refineable.rs | 44 +++++++++++++++++-- crates/theme2/src/colors.rs | 16 ++++++- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/crates/refineable/derive_refineable/src/derive_refineable.rs b/crates/refineable/derive_refineable/src/derive_refineable.rs index ed233e1b0dfa1acc9d6508e9e6fa5e6e35bcada1..c2d001b287c7038359c8e98e4adb9fd7eeed6a70 100644 --- a/crates/refineable/derive_refineable/src/derive_refineable.rs +++ b/crates/refineable/derive_refineable/src/derive_refineable.rs @@ -16,9 +16,33 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream { .. } = parse_macro_input!(input); - let impl_debug_on_refinement = attrs - .iter() - .any(|attr| attr.path.is_ident("refineable") && attr.tokens.to_string().contains("debug")); + let refineable_attr = attrs.iter().find(|attr| attr.path.is_ident("refineable")); + + let mut impl_debug_on_refinement = false; + let mut derive_serialize_on_refinement = false; + let mut derive_deserialize_on_refinement = false; + + if let Some(refineable_attr) = refineable_attr { + if let Ok(syn::Meta::List(meta_list)) = refineable_attr.parse_meta() { + for nested in meta_list.nested { + let syn::NestedMeta::Meta(syn::Meta::Path(path)) = nested else { + continue; + }; + + if path.is_ident("debug") { + impl_debug_on_refinement = true; + } + + if path.is_ident("serialize") { + derive_serialize_on_refinement = true; + } + + if path.is_ident("deserialize") { + derive_deserialize_on_refinement = true; + } + } + } + } let refinement_ident = format_ident!("{}Refinement", ident); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); @@ -235,8 +259,22 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream { quote! {} }; + let derive_serialize = if derive_serialize_on_refinement { + quote! { #[derive(serde::Serialize)]} + } else { + quote! {} + }; + + let derive_deserialize = if derive_deserialize_on_refinement { + quote! { #[derive(serde::Deserialize)]} + } else { + quote! {} + }; + let gen = quote! { #[derive(Clone)] + #derive_serialize + #derive_deserialize pub struct #refinement_ident #impl_generics { #( #field_visibilities #field_names: #wrapped_types ),* } diff --git a/crates/theme2/src/colors.rs b/crates/theme2/src/colors.rs index 38ae1325a0e9c8d3b3527db8bd4dbb4dc3818dbc..b02a9c14dfa77a10146540ac8ec3baeb0e84c929 100644 --- a/crates/theme2/src/colors.rs +++ b/crates/theme2/src/colors.rs @@ -49,7 +49,7 @@ pub struct GitStatusColors { } #[derive(Refineable, Clone, Debug)] -#[refineable(debug)] +#[refineable(debug, deserialize)] pub struct ThemeColors { pub border: Hsla, pub border_variant: Hsla, @@ -105,6 +105,8 @@ pub struct ThemeStyles { #[cfg(test)] mod tests { + use serde_json::json; + use super::*; #[test] @@ -146,4 +148,16 @@ mod tests { assert_eq!(colors.text, magenta); assert_eq!(colors.background, green); } + + #[test] + fn deserialize_theme_colors_refinement_from_json() { + let colors: ThemeColorsRefinement = serde_json::from_value(json!({ + "background": "#ff00ff", + "text": "#ff0000" + })) + .unwrap(); + + assert_eq!(colors.background, Some(gpui::rgb(0xff00ff))); + assert_eq!(colors.text, Some(gpui::rgb(0xff0000))); + } } From 76db100d119c381e29eaeed0f57e5e144d9fa48c Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 3 Nov 2023 22:34:11 +0100 Subject: [PATCH 07/23] ui2: Reorganize components (#3228) This PR reorganizes the components in the `ui2` crate. The distinction between "elements" and "components" is now gone, with all of the reusable components living under `components/`. The components that we built while prototyping but will eventually live in other crates currently reside in the `to_extract/` module. Release Notes: - N/A --- crates/storybook2/src/stories/kitchen_sink.rs | 10 +-- crates/storybook2/src/story_selector.rs | 81 +++++++------------ crates/ui2/src/components.rs | 66 +++++---------- .../src/{elements => components}/avatar.rs | 0 .../src/{elements => components}/button.rs | 0 .../src/{elements => components}/details.rs | 0 .../ui2/src/{elements => components}/icon.rs | 0 .../src/{elements => components}/indicator.rs | 0 .../ui2/src/{elements => components}/input.rs | 0 .../ui2/src/{elements => components}/label.rs | 0 .../src/{elements => components}/player.rs | 0 .../ui2/src/{elements => components}/stack.rs | 0 .../{elements => components}/tool_divider.rs | 0 crates/ui2/src/elements.rs | 21 ----- crates/ui2/src/lib.rs | 4 +- crates/ui2/src/to_extract.rs | 47 +++++++++++ .../assistant_panel.rs | 0 .../{components => to_extract}/breadcrumb.rs | 0 .../src/{components => to_extract}/buffer.rs | 0 .../buffer_search.rs | 0 .../{components => to_extract}/chat_panel.rs | 0 .../collab_panel.rs | 0 .../command_palette.rs | 0 .../src/{components => to_extract}/copilot.rs | 0 .../{components => to_extract}/editor_pane.rs | 0 .../language_selector.rs | 0 .../multi_buffer.rs | 0 .../notifications_panel.rs | 0 .../src/{components => to_extract}/panes.rs | 0 .../project_panel.rs | 0 .../recent_projects.rs | 0 .../{components => to_extract}/status_bar.rs | 0 .../src/{components => to_extract}/tab_bar.rs | 0 .../{components => to_extract}/terminal.rs | 0 .../theme_selector.rs | 0 .../{components => to_extract}/title_bar.rs | 0 .../src/{components => to_extract}/toolbar.rs | 0 .../traffic_lights.rs | 0 .../{components => to_extract}/workspace.rs | 0 39 files changed, 99 insertions(+), 130 deletions(-) rename crates/ui2/src/{elements => components}/avatar.rs (100%) rename crates/ui2/src/{elements => components}/button.rs (100%) rename crates/ui2/src/{elements => components}/details.rs (100%) rename crates/ui2/src/{elements => components}/icon.rs (100%) rename crates/ui2/src/{elements => components}/indicator.rs (100%) rename crates/ui2/src/{elements => components}/input.rs (100%) rename crates/ui2/src/{elements => components}/label.rs (100%) rename crates/ui2/src/{elements => components}/player.rs (100%) rename crates/ui2/src/{elements => components}/stack.rs (100%) rename crates/ui2/src/{elements => components}/tool_divider.rs (100%) delete mode 100644 crates/ui2/src/elements.rs create mode 100644 crates/ui2/src/to_extract.rs rename crates/ui2/src/{components => to_extract}/assistant_panel.rs (100%) rename crates/ui2/src/{components => to_extract}/breadcrumb.rs (100%) rename crates/ui2/src/{components => to_extract}/buffer.rs (100%) rename crates/ui2/src/{components => to_extract}/buffer_search.rs (100%) rename crates/ui2/src/{components => to_extract}/chat_panel.rs (100%) rename crates/ui2/src/{components => to_extract}/collab_panel.rs (100%) rename crates/ui2/src/{components => to_extract}/command_palette.rs (100%) rename crates/ui2/src/{components => to_extract}/copilot.rs (100%) rename crates/ui2/src/{components => to_extract}/editor_pane.rs (100%) rename crates/ui2/src/{components => to_extract}/language_selector.rs (100%) rename crates/ui2/src/{components => to_extract}/multi_buffer.rs (100%) rename crates/ui2/src/{components => to_extract}/notifications_panel.rs (100%) rename crates/ui2/src/{components => to_extract}/panes.rs (100%) rename crates/ui2/src/{components => to_extract}/project_panel.rs (100%) rename crates/ui2/src/{components => to_extract}/recent_projects.rs (100%) rename crates/ui2/src/{components => to_extract}/status_bar.rs (100%) rename crates/ui2/src/{components => to_extract}/tab_bar.rs (100%) rename crates/ui2/src/{components => to_extract}/terminal.rs (100%) rename crates/ui2/src/{components => to_extract}/theme_selector.rs (100%) rename crates/ui2/src/{components => to_extract}/title_bar.rs (100%) rename crates/ui2/src/{components => to_extract}/toolbar.rs (100%) rename crates/ui2/src/{components => to_extract}/traffic_lights.rs (100%) rename crates/ui2/src/{components => to_extract}/workspace.rs (100%) diff --git a/crates/storybook2/src/stories/kitchen_sink.rs b/crates/storybook2/src/stories/kitchen_sink.rs index cfa91417b6de60f03284428e889d40c946a5a152..cf8277c4f451e0b3e9cf5d9b96781a0ce66d0085 100644 --- a/crates/storybook2/src/stories/kitchen_sink.rs +++ b/crates/storybook2/src/stories/kitchen_sink.rs @@ -1,7 +1,4 @@ -use crate::{ - story::Story, - story_selector::{ComponentStory, ElementStory}, -}; +use crate::{story::Story, story_selector::ComponentStory}; use gpui2::{Div, Render, StatefulInteraction, View, VisualContext}; use strum::IntoEnumIterator; use ui::prelude::*; @@ -18,9 +15,6 @@ impl Render for KitchenSinkStory { type Element = Div>; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - let element_stories = ElementStory::iter() - .map(|selector| selector.story(cx)) - .collect::>(); let component_stories = ComponentStory::iter() .map(|selector| selector.story(cx)) .collect::>(); @@ -29,8 +23,6 @@ impl Render for KitchenSinkStory { .id("kitchen-sink") .overflow_y_scroll() .child(Story::title(cx, "Kitchen Sink")) - .child(Story::label(cx, "Elements")) - .child(div().flex().flex_col().children(element_stories)) .child(Story::label(cx, "Components")) .child(div().flex().flex_col().children(component_stories)) // Add a bit of space at the bottom of the kitchen sink so elements diff --git a/crates/storybook2/src/story_selector.rs b/crates/storybook2/src/story_selector.rs index 968309bd8a0cee2f00cb005cf0a486c51940e31f..a78705c7bbfd9d68308c793809596e1ea3e729f2 100644 --- a/crates/storybook2/src/story_selector.rs +++ b/crates/storybook2/src/story_selector.rs @@ -7,55 +7,30 @@ use clap::builder::PossibleValue; use clap::ValueEnum; use gpui2::{AnyView, VisualContext}; use strum::{EnumIter, EnumString, IntoEnumIterator}; -use ui::{prelude::*, AvatarStory, ButtonStory, DetailsStory, IconStory, InputStory, LabelStory}; - -#[derive(Debug, PartialEq, Eq, Clone, Copy, strum::Display, EnumString, EnumIter)] -#[strum(serialize_all = "snake_case")] -pub enum ElementStory { - Avatar, - Button, - Colors, - Details, - Focus, - Icon, - Input, - Label, - Scroll, - Text, - ZIndex, -} - -impl ElementStory { - pub fn story(&self, cx: &mut WindowContext) -> AnyView { - match self { - Self::Colors => cx.build_view(|_| ColorsStory).into(), - Self::Avatar => cx.build_view(|_| AvatarStory).into(), - Self::Button => cx.build_view(|_| ButtonStory).into(), - Self::Details => cx.build_view(|_| DetailsStory).into(), - Self::Focus => FocusStory::view(cx).into(), - Self::Icon => cx.build_view(|_| IconStory).into(), - Self::Input => cx.build_view(|_| InputStory).into(), - Self::Label => cx.build_view(|_| LabelStory).into(), - Self::Scroll => ScrollStory::view(cx).into(), - Self::Text => TextStory::view(cx).into(), - Self::ZIndex => cx.build_view(|_| ZIndexStory).into(), - } - } -} +use ui::prelude::*; +use ui::{AvatarStory, ButtonStory, DetailsStory, IconStory, InputStory, LabelStory}; #[derive(Debug, PartialEq, Eq, Clone, Copy, strum::Display, EnumString, EnumIter)] #[strum(serialize_all = "snake_case")] pub enum ComponentStory { AssistantPanel, + Avatar, Breadcrumb, Buffer, + Button, ChatPanel, CollabPanel, + Colors, CommandPalette, - Copilot, ContextMenu, + Copilot, + Details, Facepile, + Focus, + Icon, + Input, Keybinding, + Label, LanguageSelector, MultiBuffer, NotificationsPanel, @@ -63,29 +38,41 @@ pub enum ComponentStory { Panel, ProjectPanel, RecentProjects, + Scroll, Tab, TabBar, Terminal, + Text, ThemeSelector, TitleBar, Toast, Toolbar, TrafficLights, Workspace, + ZIndex, } impl ComponentStory { pub fn story(&self, cx: &mut WindowContext) -> AnyView { match self { Self::AssistantPanel => cx.build_view(|_| ui::AssistantPanelStory).into(), - Self::Buffer => cx.build_view(|_| ui::BufferStory).into(), + Self::Avatar => cx.build_view(|_| AvatarStory).into(), Self::Breadcrumb => cx.build_view(|_| ui::BreadcrumbStory).into(), + Self::Buffer => cx.build_view(|_| ui::BufferStory).into(), + Self::Button => cx.build_view(|_| ButtonStory).into(), Self::ChatPanel => cx.build_view(|_| ui::ChatPanelStory).into(), Self::CollabPanel => cx.build_view(|_| ui::CollabPanelStory).into(), + Self::Colors => cx.build_view(|_| ColorsStory).into(), Self::CommandPalette => cx.build_view(|_| ui::CommandPaletteStory).into(), Self::ContextMenu => cx.build_view(|_| ui::ContextMenuStory).into(), + Self::Copilot => cx.build_view(|_| ui::CopilotModalStory).into(), + Self::Details => cx.build_view(|_| DetailsStory).into(), Self::Facepile => cx.build_view(|_| ui::FacepileStory).into(), + Self::Focus => FocusStory::view(cx).into(), + Self::Icon => cx.build_view(|_| IconStory).into(), + Self::Input => cx.build_view(|_| InputStory).into(), Self::Keybinding => cx.build_view(|_| ui::KeybindingStory).into(), + Self::Label => cx.build_view(|_| LabelStory).into(), Self::LanguageSelector => cx.build_view(|_| ui::LanguageSelectorStory).into(), Self::MultiBuffer => cx.build_view(|_| ui::MultiBufferStory).into(), Self::NotificationsPanel => cx.build_view(|cx| ui::NotificationsPanelStory).into(), @@ -93,23 +80,24 @@ impl ComponentStory { Self::Panel => cx.build_view(|cx| ui::PanelStory).into(), Self::ProjectPanel => cx.build_view(|_| ui::ProjectPanelStory).into(), Self::RecentProjects => cx.build_view(|_| ui::RecentProjectsStory).into(), + Self::Scroll => ScrollStory::view(cx).into(), Self::Tab => cx.build_view(|_| ui::TabStory).into(), Self::TabBar => cx.build_view(|_| ui::TabBarStory).into(), Self::Terminal => cx.build_view(|_| ui::TerminalStory).into(), + Self::Text => TextStory::view(cx).into(), Self::ThemeSelector => cx.build_view(|_| ui::ThemeSelectorStory).into(), + Self::TitleBar => ui::TitleBarStory::view(cx).into(), Self::Toast => cx.build_view(|_| ui::ToastStory).into(), Self::Toolbar => cx.build_view(|_| ui::ToolbarStory).into(), Self::TrafficLights => cx.build_view(|_| ui::TrafficLightsStory).into(), - Self::Copilot => cx.build_view(|_| ui::CopilotModalStory).into(), - Self::TitleBar => ui::TitleBarStory::view(cx).into(), Self::Workspace => ui::WorkspaceStory::view(cx).into(), + Self::ZIndex => cx.build_view(|_| ZIndexStory).into(), } } } #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum StorySelector { - Element(ElementStory), Component(ComponentStory), KitchenSink, } @@ -126,13 +114,6 @@ impl FromStr for StorySelector { return Ok(Self::KitchenSink); } - if let Some((_, story)) = story.split_once("elements/") { - let element_story = ElementStory::from_str(story) - .with_context(|| format!("story not found for element '{story}'"))?; - - return Ok(Self::Element(element_story)); - } - if let Some((_, story)) = story.split_once("components/") { let component_story = ComponentStory::from_str(story) .with_context(|| format!("story not found for component '{story}'"))?; @@ -147,7 +128,6 @@ impl FromStr for StorySelector { impl StorySelector { pub fn story(&self, cx: &mut WindowContext) -> AnyView { match self { - Self::Element(element_story) => element_story.story(cx), Self::Component(component_story) => component_story.story(cx), Self::KitchenSink => KitchenSinkStory::view(cx).into(), } @@ -160,11 +140,9 @@ static ALL_STORY_SELECTORS: OnceLock> = OnceLock::new(); impl ValueEnum for StorySelector { fn value_variants<'a>() -> &'a [Self] { let stories = ALL_STORY_SELECTORS.get_or_init(|| { - let element_stories = ElementStory::iter().map(StorySelector::Element); let component_stories = ComponentStory::iter().map(StorySelector::Component); - element_stories - .chain(component_stories) + component_stories .chain(std::iter::once(StorySelector::KitchenSink)) .collect::>() }); @@ -174,7 +152,6 @@ impl ValueEnum for StorySelector { fn to_possible_value(&self) -> Option { let value = match self { - Self::Element(story) => format!("elements/{story}"), Self::Component(story) => format!("components/{story}"), Self::KitchenSink => "kitchen_sink".to_string(), }; diff --git a/crates/ui2/src/components.rs b/crates/ui2/src/components.rs index 7a9cac01ca7c54999210b3220986062906196e1b..f7674c2bd4db5aa4a79ca9d0cc2ed6597ab36002 100644 --- a/crates/ui2/src/components.rs +++ b/crates/ui2/src/components.rs @@ -1,71 +1,45 @@ -mod assistant_panel; -mod breadcrumb; -mod buffer; -mod buffer_search; -mod chat_panel; -mod collab_panel; -mod command_palette; +mod avatar; +mod button; mod context_menu; -mod copilot; -mod editor_pane; +mod details; mod facepile; +mod icon; mod icon_button; +mod indicator; +mod input; mod keybinding; -mod language_selector; +mod label; mod list; mod modal; -mod multi_buffer; mod notification_toast; -mod notifications_panel; mod palette; mod panel; -mod panes; +mod player; mod player_stack; -mod project_panel; -mod recent_projects; -mod status_bar; +mod stack; mod tab; -mod tab_bar; -mod terminal; -mod theme_selector; -mod title_bar; mod toast; -mod toolbar; -mod traffic_lights; -mod workspace; +mod tool_divider; -pub use assistant_panel::*; -pub use breadcrumb::*; -pub use buffer::*; -pub use buffer_search::*; -pub use chat_panel::*; -pub use collab_panel::*; -pub use command_palette::*; +pub use avatar::*; +pub use button::*; pub use context_menu::*; -pub use copilot::*; -pub use editor_pane::*; +pub use details::*; pub use facepile::*; +pub use icon::*; pub use icon_button::*; +pub use indicator::*; +pub use input::*; pub use keybinding::*; -pub use language_selector::*; +pub use label::*; pub use list::*; pub use modal::*; -pub use multi_buffer::*; pub use notification_toast::*; -pub use notifications_panel::*; pub use palette::*; pub use panel::*; -pub use panes::*; +pub use player::*; pub use player_stack::*; -pub use project_panel::*; -pub use recent_projects::*; -pub use status_bar::*; +pub use stack::*; pub use tab::*; -pub use tab_bar::*; -pub use terminal::*; -pub use theme_selector::*; -pub use title_bar::*; pub use toast::*; -pub use toolbar::*; -pub use traffic_lights::*; -pub use workspace::*; +pub use tool_divider::*; diff --git a/crates/ui2/src/elements/avatar.rs b/crates/ui2/src/components/avatar.rs similarity index 100% rename from crates/ui2/src/elements/avatar.rs rename to crates/ui2/src/components/avatar.rs diff --git a/crates/ui2/src/elements/button.rs b/crates/ui2/src/components/button.rs similarity index 100% rename from crates/ui2/src/elements/button.rs rename to crates/ui2/src/components/button.rs diff --git a/crates/ui2/src/elements/details.rs b/crates/ui2/src/components/details.rs similarity index 100% rename from crates/ui2/src/elements/details.rs rename to crates/ui2/src/components/details.rs diff --git a/crates/ui2/src/elements/icon.rs b/crates/ui2/src/components/icon.rs similarity index 100% rename from crates/ui2/src/elements/icon.rs rename to crates/ui2/src/components/icon.rs diff --git a/crates/ui2/src/elements/indicator.rs b/crates/ui2/src/components/indicator.rs similarity index 100% rename from crates/ui2/src/elements/indicator.rs rename to crates/ui2/src/components/indicator.rs diff --git a/crates/ui2/src/elements/input.rs b/crates/ui2/src/components/input.rs similarity index 100% rename from crates/ui2/src/elements/input.rs rename to crates/ui2/src/components/input.rs diff --git a/crates/ui2/src/elements/label.rs b/crates/ui2/src/components/label.rs similarity index 100% rename from crates/ui2/src/elements/label.rs rename to crates/ui2/src/components/label.rs diff --git a/crates/ui2/src/elements/player.rs b/crates/ui2/src/components/player.rs similarity index 100% rename from crates/ui2/src/elements/player.rs rename to crates/ui2/src/components/player.rs diff --git a/crates/ui2/src/elements/stack.rs b/crates/ui2/src/components/stack.rs similarity index 100% rename from crates/ui2/src/elements/stack.rs rename to crates/ui2/src/components/stack.rs diff --git a/crates/ui2/src/elements/tool_divider.rs b/crates/ui2/src/components/tool_divider.rs similarity index 100% rename from crates/ui2/src/elements/tool_divider.rs rename to crates/ui2/src/components/tool_divider.rs diff --git a/crates/ui2/src/elements.rs b/crates/ui2/src/elements.rs deleted file mode 100644 index dfff2761a76e40deb84656f6c4ce6b6abe2b28f3..0000000000000000000000000000000000000000 --- a/crates/ui2/src/elements.rs +++ /dev/null @@ -1,21 +0,0 @@ -mod avatar; -mod button; -mod details; -mod icon; -mod indicator; -mod input; -mod label; -mod player; -mod stack; -mod tool_divider; - -pub use avatar::*; -pub use button::*; -pub use details::*; -pub use icon::*; -pub use indicator::*; -pub use input::*; -pub use label::*; -pub use player::*; -pub use stack::*; -pub use tool_divider::*; diff --git a/crates/ui2/src/lib.rs b/crates/ui2/src/lib.rs index 5d0a57c6d90fca078982941193d87828e706f726..0fd6eee0db4db1071515c41a740cfe516f65fad4 100644 --- a/crates/ui2/src/lib.rs +++ b/crates/ui2/src/lib.rs @@ -18,17 +18,17 @@ #![allow(dead_code, unused_variables)] mod components; -mod elements; mod elevation; pub mod prelude; pub mod settings; mod static_data; +mod to_extract; pub mod utils; pub use components::*; -pub use elements::*; pub use prelude::*; pub use static_data::*; +pub use to_extract::*; // This needs to be fully qualified with `crate::` otherwise we get a panic // at: diff --git a/crates/ui2/src/to_extract.rs b/crates/ui2/src/to_extract.rs new file mode 100644 index 0000000000000000000000000000000000000000..e786dd0f7e08ef377e6f483d248ae4eee90358e8 --- /dev/null +++ b/crates/ui2/src/to_extract.rs @@ -0,0 +1,47 @@ +mod assistant_panel; +mod breadcrumb; +mod buffer; +mod buffer_search; +mod chat_panel; +mod collab_panel; +mod command_palette; +mod copilot; +mod editor_pane; +mod language_selector; +mod multi_buffer; +mod notifications_panel; +mod panes; +mod project_panel; +mod recent_projects; +mod status_bar; +mod tab_bar; +mod terminal; +mod theme_selector; +mod title_bar; +mod toolbar; +mod traffic_lights; +mod workspace; + +pub use assistant_panel::*; +pub use breadcrumb::*; +pub use buffer::*; +pub use buffer_search::*; +pub use chat_panel::*; +pub use collab_panel::*; +pub use command_palette::*; +pub use copilot::*; +pub use editor_pane::*; +pub use language_selector::*; +pub use multi_buffer::*; +pub use notifications_panel::*; +pub use panes::*; +pub use project_panel::*; +pub use recent_projects::*; +pub use status_bar::*; +pub use tab_bar::*; +pub use terminal::*; +pub use theme_selector::*; +pub use title_bar::*; +pub use toolbar::*; +pub use traffic_lights::*; +pub use workspace::*; diff --git a/crates/ui2/src/components/assistant_panel.rs b/crates/ui2/src/to_extract/assistant_panel.rs similarity index 100% rename from crates/ui2/src/components/assistant_panel.rs rename to crates/ui2/src/to_extract/assistant_panel.rs diff --git a/crates/ui2/src/components/breadcrumb.rs b/crates/ui2/src/to_extract/breadcrumb.rs similarity index 100% rename from crates/ui2/src/components/breadcrumb.rs rename to crates/ui2/src/to_extract/breadcrumb.rs diff --git a/crates/ui2/src/components/buffer.rs b/crates/ui2/src/to_extract/buffer.rs similarity index 100% rename from crates/ui2/src/components/buffer.rs rename to crates/ui2/src/to_extract/buffer.rs diff --git a/crates/ui2/src/components/buffer_search.rs b/crates/ui2/src/to_extract/buffer_search.rs similarity index 100% rename from crates/ui2/src/components/buffer_search.rs rename to crates/ui2/src/to_extract/buffer_search.rs diff --git a/crates/ui2/src/components/chat_panel.rs b/crates/ui2/src/to_extract/chat_panel.rs similarity index 100% rename from crates/ui2/src/components/chat_panel.rs rename to crates/ui2/src/to_extract/chat_panel.rs diff --git a/crates/ui2/src/components/collab_panel.rs b/crates/ui2/src/to_extract/collab_panel.rs similarity index 100% rename from crates/ui2/src/components/collab_panel.rs rename to crates/ui2/src/to_extract/collab_panel.rs diff --git a/crates/ui2/src/components/command_palette.rs b/crates/ui2/src/to_extract/command_palette.rs similarity index 100% rename from crates/ui2/src/components/command_palette.rs rename to crates/ui2/src/to_extract/command_palette.rs diff --git a/crates/ui2/src/components/copilot.rs b/crates/ui2/src/to_extract/copilot.rs similarity index 100% rename from crates/ui2/src/components/copilot.rs rename to crates/ui2/src/to_extract/copilot.rs diff --git a/crates/ui2/src/components/editor_pane.rs b/crates/ui2/src/to_extract/editor_pane.rs similarity index 100% rename from crates/ui2/src/components/editor_pane.rs rename to crates/ui2/src/to_extract/editor_pane.rs diff --git a/crates/ui2/src/components/language_selector.rs b/crates/ui2/src/to_extract/language_selector.rs similarity index 100% rename from crates/ui2/src/components/language_selector.rs rename to crates/ui2/src/to_extract/language_selector.rs diff --git a/crates/ui2/src/components/multi_buffer.rs b/crates/ui2/src/to_extract/multi_buffer.rs similarity index 100% rename from crates/ui2/src/components/multi_buffer.rs rename to crates/ui2/src/to_extract/multi_buffer.rs diff --git a/crates/ui2/src/components/notifications_panel.rs b/crates/ui2/src/to_extract/notifications_panel.rs similarity index 100% rename from crates/ui2/src/components/notifications_panel.rs rename to crates/ui2/src/to_extract/notifications_panel.rs diff --git a/crates/ui2/src/components/panes.rs b/crates/ui2/src/to_extract/panes.rs similarity index 100% rename from crates/ui2/src/components/panes.rs rename to crates/ui2/src/to_extract/panes.rs diff --git a/crates/ui2/src/components/project_panel.rs b/crates/ui2/src/to_extract/project_panel.rs similarity index 100% rename from crates/ui2/src/components/project_panel.rs rename to crates/ui2/src/to_extract/project_panel.rs diff --git a/crates/ui2/src/components/recent_projects.rs b/crates/ui2/src/to_extract/recent_projects.rs similarity index 100% rename from crates/ui2/src/components/recent_projects.rs rename to crates/ui2/src/to_extract/recent_projects.rs diff --git a/crates/ui2/src/components/status_bar.rs b/crates/ui2/src/to_extract/status_bar.rs similarity index 100% rename from crates/ui2/src/components/status_bar.rs rename to crates/ui2/src/to_extract/status_bar.rs diff --git a/crates/ui2/src/components/tab_bar.rs b/crates/ui2/src/to_extract/tab_bar.rs similarity index 100% rename from crates/ui2/src/components/tab_bar.rs rename to crates/ui2/src/to_extract/tab_bar.rs diff --git a/crates/ui2/src/components/terminal.rs b/crates/ui2/src/to_extract/terminal.rs similarity index 100% rename from crates/ui2/src/components/terminal.rs rename to crates/ui2/src/to_extract/terminal.rs diff --git a/crates/ui2/src/components/theme_selector.rs b/crates/ui2/src/to_extract/theme_selector.rs similarity index 100% rename from crates/ui2/src/components/theme_selector.rs rename to crates/ui2/src/to_extract/theme_selector.rs diff --git a/crates/ui2/src/components/title_bar.rs b/crates/ui2/src/to_extract/title_bar.rs similarity index 100% rename from crates/ui2/src/components/title_bar.rs rename to crates/ui2/src/to_extract/title_bar.rs diff --git a/crates/ui2/src/components/toolbar.rs b/crates/ui2/src/to_extract/toolbar.rs similarity index 100% rename from crates/ui2/src/components/toolbar.rs rename to crates/ui2/src/to_extract/toolbar.rs diff --git a/crates/ui2/src/components/traffic_lights.rs b/crates/ui2/src/to_extract/traffic_lights.rs similarity index 100% rename from crates/ui2/src/components/traffic_lights.rs rename to crates/ui2/src/to_extract/traffic_lights.rs diff --git a/crates/ui2/src/components/workspace.rs b/crates/ui2/src/to_extract/workspace.rs similarity index 100% rename from crates/ui2/src/components/workspace.rs rename to crates/ui2/src/to_extract/workspace.rs From 6abdab7735f223462ff4bc0a607c7cd640e88e21 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 3 Nov 2023 17:52:19 -0400 Subject: [PATCH 08/23] Remove `theme.txt` --- theme.txt | 254 ------------------------------------------------------ 1 file changed, 254 deletions(-) delete mode 100644 theme.txt diff --git a/theme.txt b/theme.txt deleted file mode 100644 index 626d6b9fa91edeedee07148dea96defd194ebf31..0000000000000000000000000000000000000000 --- a/theme.txt +++ /dev/null @@ -1,254 +0,0 @@ - Finished dev [unoptimized + debuginfo] target(s) in 0.39s - Running `target/debug/storybook` -[crates/ui2/src/components/workspace.rs:182] color = [crates/ui2/src/color.rs:162] "ThemeColor debug" = "ThemeColor debug" -ThemeColor { - transparent: "rgba(0x00000000).into()", - mac_os_traffic_light_red: "rgba(0xec695eff).into()", - mac_os_traffic_light_yellow: "rgba(0xf4bf4eff).into()", - mac_os_traffic_light_green: "rgba(0x61c553ff).into()", - border: "rgba(0x464b57ff).into()", - border_variant: "rgba(0x464b57ff).into()", - border_focused: "rgba(0x293b5bff).into()", - border_transparent: "rgba(0x00000000).into()", - elevated_surface: "rgba(0x3b414dff).into()", - surface: "rgba(0x2f343eff).into()", - background: "rgba(0x3b414dff).into()", - filled_element: "rgba(0x3b414dff).into()", - filled_element_hover: "rgba(0xffffff1e).into()", - filled_element_active: "rgba(0xffffff28).into()", - filled_element_selected: "rgba(0x18243dff).into()", - filled_element_disabled: "rgba(0x00000000).into()", - ghost_element: "rgba(0x00000000).into()", - ghost_element_hover: "rgba(0xffffff14).into()", - ghost_element_active: "rgba(0xffffff1e).into()", - ghost_element_selected: "rgba(0x18243dff).into()", - ghost_element_disabled: "rgba(0x00000000).into()", - text: "rgba(0xc8ccd4ff).into()", - text_muted: "rgba(0x838994ff).into()", - text_placeholder: "rgba(0xd07277ff).into()", - text_disabled: "rgba(0x555a63ff).into()", - text_accent: "rgba(0x74ade8ff).into()", - icon_muted: "rgba(0x838994ff).into()", - syntax: SyntaxColor { - comment: "rgba(0x5d636fff).into()", - string: "rgba(0xa1c181ff).into()", - function: "rgba(0x73ade9ff).into()", - keyword: "rgba(0xb477cfff).into()", - }, - status_bar: "rgba(0x3b414dff).into()", - title_bar: "rgba(0x3b414dff).into()", - toolbar: "rgba(0x282c33ff).into()", - tab_bar: "rgba(0x2f343eff).into()", - editor_subheader: "rgba(0x2f343eff).into()", - editor_active_line: "rgba(0x2f343eff).into()", - terminal: "rgba(0x282c33ff).into()", - image_fallback_background: "rgba(0x3b414dff).into()", - git_created: "rgba(0xa1c181ff).into()", - git_modified: "rgba(0x74ade8ff).into()", - git_deleted: "rgba(0xd07277ff).into()", - git_conflict: "rgba(0xdec184ff).into()", - git_ignored: "rgba(0x555a63ff).into()", - git_renamed: "rgba(0xdec184ff).into()", - player: [ - PlayerThemeColors { - cursor: "rgba(0x74ade8ff).into()", - selection: "rgba(0x74ade83d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xa1c181ff).into()", - selection: "rgba(0xa1c1813d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xbe5046ff).into()", - selection: "rgba(0xbe50463d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xbf956aff).into()", - selection: "rgba(0xbf956a3d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xb477cfff).into()", - selection: "rgba(0xb477cf3d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0x6eb4bfff).into()", - selection: "rgba(0x6eb4bf3d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xd07277ff).into()", - selection: "rgba(0xd072773d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xdec184ff).into()", - selection: "rgba(0xdec1843d).into()", - }, - ], -} -[crates/ui2/src/components/workspace.rs:182] color = [crates/ui2/src/color.rs:162] "ThemeColor debug" = "ThemeColor debug" -ThemeColor { - transparent: "rgba(0x00000000).into()", - mac_os_traffic_light_red: "rgba(0xec695eff).into()", - mac_os_traffic_light_yellow: "rgba(0xf4bf4eff).into()", - mac_os_traffic_light_green: "rgba(0x61c553ff).into()", - border: "rgba(0x464b57ff).into()", - border_variant: "rgba(0x464b57ff).into()", - border_focused: "rgba(0x293b5bff).into()", - border_transparent: "rgba(0x00000000).into()", - elevated_surface: "rgba(0x3b414dff).into()", - surface: "rgba(0x2f343eff).into()", - background: "rgba(0x3b414dff).into()", - filled_element: "rgba(0x3b414dff).into()", - filled_element_hover: "rgba(0xffffff1e).into()", - filled_element_active: "rgba(0xffffff28).into()", - filled_element_selected: "rgba(0x18243dff).into()", - filled_element_disabled: "rgba(0x00000000).into()", - ghost_element: "rgba(0x00000000).into()", - ghost_element_hover: "rgba(0xffffff14).into()", - ghost_element_active: "rgba(0xffffff1e).into()", - ghost_element_selected: "rgba(0x18243dff).into()", - ghost_element_disabled: "rgba(0x00000000).into()", - text: "rgba(0xc8ccd4ff).into()", - text_muted: "rgba(0x838994ff).into()", - text_placeholder: "rgba(0xd07277ff).into()", - text_disabled: "rgba(0x555a63ff).into()", - text_accent: "rgba(0x74ade8ff).into()", - icon_muted: "rgba(0x838994ff).into()", - syntax: SyntaxColor { - comment: "rgba(0x5d636fff).into()", - string: "rgba(0xa1c181ff).into()", - function: "rgba(0x73ade9ff).into()", - keyword: "rgba(0xb477cfff).into()", - }, - status_bar: "rgba(0x3b414dff).into()", - title_bar: "rgba(0x3b414dff).into()", - toolbar: "rgba(0x282c33ff).into()", - tab_bar: "rgba(0x2f343eff).into()", - editor_subheader: "rgba(0x2f343eff).into()", - editor_active_line: "rgba(0x2f343eff).into()", - terminal: "rgba(0x282c33ff).into()", - image_fallback_background: "rgba(0x3b414dff).into()", - git_created: "rgba(0xa1c181ff).into()", - git_modified: "rgba(0x74ade8ff).into()", - git_deleted: "rgba(0xd07277ff).into()", - git_conflict: "rgba(0xdec184ff).into()", - git_ignored: "rgba(0x555a63ff).into()", - git_renamed: "rgba(0xdec184ff).into()", - player: [ - PlayerThemeColors { - cursor: "rgba(0x74ade8ff).into()", - selection: "rgba(0x74ade83d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xa1c181ff).into()", - selection: "rgba(0xa1c1813d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xbe5046ff).into()", - selection: "rgba(0xbe50463d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xbf956aff).into()", - selection: "rgba(0xbf956a3d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xb477cfff).into()", - selection: "rgba(0xb477cf3d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0x6eb4bfff).into()", - selection: "rgba(0x6eb4bf3d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xd07277ff).into()", - selection: "rgba(0xd072773d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xdec184ff).into()", - selection: "rgba(0xdec1843d).into()", - }, - ], -} -[crates/ui2/src/components/workspace.rs:182] color = [crates/ui2/src/color.rs:162] "ThemeColor debug" = "ThemeColor debug" -ThemeColor { - transparent: "rgba(0x00000000).into()", - mac_os_traffic_light_red: "rgba(0xec695eff).into()", - mac_os_traffic_light_yellow: "rgba(0xf4bf4eff).into()", - mac_os_traffic_light_green: "rgba(0x61c553ff).into()", - border: "rgba(0x464b57ff).into()", - border_variant: "rgba(0x464b57ff).into()", - border_focused: "rgba(0x293b5bff).into()", - border_transparent: "rgba(0x00000000).into()", - elevated_surface: "rgba(0x3b414dff).into()", - surface: "rgba(0x2f343eff).into()", - background: "rgba(0x3b414dff).into()", - filled_element: "rgba(0x3b414dff).into()", - filled_element_hover: "rgba(0xffffff1e).into()", - filled_element_active: "rgba(0xffffff28).into()", - filled_element_selected: "rgba(0x18243dff).into()", - filled_element_disabled: "rgba(0x00000000).into()", - ghost_element: "rgba(0x00000000).into()", - ghost_element_hover: "rgba(0xffffff14).into()", - ghost_element_active: "rgba(0xffffff1e).into()", - ghost_element_selected: "rgba(0x18243dff).into()", - ghost_element_disabled: "rgba(0x00000000).into()", - text: "rgba(0xc8ccd4ff).into()", - text_muted: "rgba(0x838994ff).into()", - text_placeholder: "rgba(0xd07277ff).into()", - text_disabled: "rgba(0x555a63ff).into()", - text_accent: "rgba(0x74ade8ff).into()", - icon_muted: "rgba(0x838994ff).into()", - syntax: SyntaxColor { - comment: "rgba(0x5d636fff).into()", - string: "rgba(0xa1c181ff).into()", - function: "rgba(0x73ade9ff).into()", - keyword: "rgba(0xb477cfff).into()", - }, - status_bar: "rgba(0x3b414dff).into()", - title_bar: "rgba(0x3b414dff).into()", - toolbar: "rgba(0x282c33ff).into()", - tab_bar: "rgba(0x2f343eff).into()", - editor_subheader: "rgba(0x2f343eff).into()", - editor_active_line: "rgba(0x2f343eff).into()", - terminal: "rgba(0x282c33ff).into()", - image_fallback_background: "rgba(0x3b414dff).into()", - git_created: "rgba(0xa1c181ff).into()", - git_modified: "rgba(0x74ade8ff).into()", - git_deleted: "rgba(0xd07277ff).into()", - git_conflict: "rgba(0xdec184ff).into()", - git_ignored: "rgba(0x555a63ff).into()", - git_renamed: "rgba(0xdec184ff).into()", - player: [ - PlayerThemeColors { - cursor: "rgba(0x74ade8ff).into()", - selection: "rgba(0x74ade83d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xa1c181ff).into()", - selection: "rgba(0xa1c1813d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xbe5046ff).into()", - selection: "rgba(0xbe50463d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xbf956aff).into()", - selection: "rgba(0xbf956a3d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xb477cfff).into()", - selection: "rgba(0xb477cf3d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0x6eb4bfff).into()", - selection: "rgba(0x6eb4bf3d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xd07277ff).into()", - selection: "rgba(0xd072773d).into()", - }, - PlayerThemeColors { - cursor: "rgba(0xdec184ff).into()", - selection: "rgba(0xdec1843d).into()", - }, - ], -} From 5d36331942634031a44146fb99e4d84d8c2b8590 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 3 Nov 2023 23:12:21 +0100 Subject: [PATCH 09/23] storybook2: Remove unreferenced `components` module (#3229) This PR removes the `components` module from `storybook2` as it was dead, unreferenced code. Release Notes: - N/A --- crates/storybook2/src/components.rs | 97 ----------------------------- 1 file changed, 97 deletions(-) delete mode 100644 crates/storybook2/src/components.rs diff --git a/crates/storybook2/src/components.rs b/crates/storybook2/src/components.rs deleted file mode 100644 index a3dca51adc44050e31473a3e3e526d7f2a4b381e..0000000000000000000000000000000000000000 --- a/crates/storybook2/src/components.rs +++ /dev/null @@ -1,97 +0,0 @@ -use gpui2::{ - div, ArcCow, Element, EventContext, Interactive, IntoElement, MouseButton, ParentElement, - StyleHelpers, ViewContext, -}; -use std::{marker::PhantomData, rc::Rc}; - -struct ButtonHandlers { - click: Option)>>, -} - -impl Default for ButtonHandlers { - fn default() -> Self { - Self { click: None } - } -} - -#[derive(Component)] -pub struct Button { - handlers: ButtonHandlers, - label: Option>, - icon: Option>, - data: Rc, - view_type: PhantomData, -} - -// Impl block for buttons without data. -// See below for an impl block for any button. -impl Button { - fn new() -> Self { - Self { - handlers: ButtonHandlers::default(), - label: None, - icon: None, - data: Rc::new(()), - view_type: PhantomData, - } - } - - pub fn data(self, data: D) -> Button { - Button { - handlers: ButtonHandlers::default(), - label: self.label, - icon: self.icon, - data: Rc::new(data), - view_type: PhantomData, - } - } -} - -// Impl block for button regardless of its data type. -impl Button { - pub fn label(mut self, label: impl Into>) -> Self { - self.label = Some(label.into()); - self - } - - pub fn icon(mut self, icon: impl Into>) -> Self { - self.icon = Some(icon.into()); - self - } - - pub fn on_click( - mut self, - handler: impl Fn(&mut V, &D, &mut EventContext) + 'static, - ) -> Self { - self.handlers.click = Some(Rc::new(handler)); - self - } -} - -pub fn button() -> Button { - Button::new() -} - -impl Button { - fn render( - &mut self, - view: &mut V, - cx: &mut ViewContext, - ) -> impl IntoElement + Interactive { - // let colors = &cx.theme::().colors; - - let button = div() - // .fill(colors.error(0.5)) - .h_4() - .children(self.label.clone()); - - if let Some(handler) = self.handlers.click.clone() { - let data = self.data.clone(); - button.on_mouse_down(MouseButton::Left, move |view, event, cx| { - handler(view, data.as_ref(), cx) - }) - } else { - button - } - } -} From 9ce7199d2dea638e18916d53fa6680db84371a77 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 3 Nov 2023 18:19:54 -0400 Subject: [PATCH 10/23] Add some initial docs --- crates/ui2/docs/building-ui.md | 39 ++++++++ crates/ui2/docs/elevation.md | 57 ------------ crates/ui2/docs/hello-world.md | 160 +++++++++++++++++++++++++++++++++ crates/ui2/docs/todo.md | 25 ++++++ crates/ui2/src/lib.rs | 66 +------------- 5 files changed, 227 insertions(+), 120 deletions(-) create mode 100644 crates/ui2/docs/building-ui.md delete mode 100644 crates/ui2/docs/elevation.md create mode 100644 crates/ui2/docs/hello-world.md create mode 100644 crates/ui2/docs/todo.md diff --git a/crates/ui2/docs/building-ui.md b/crates/ui2/docs/building-ui.md new file mode 100644 index 0000000000000000000000000000000000000000..a2a3ff697b1a6a69d7c2a216912dd62a86f0b4c3 --- /dev/null +++ b/crates/ui2/docs/building-ui.md @@ -0,0 +1,39 @@ +# Building UI with GPUI + +## Common patterns + +### Using the Label Component to Create UI Text + +The `Label` component helps in displaying text on user interfaces. It creates an interface where specific parameters such as label color, line height style, and strikethrough can be set. + +Firstly, to create a `Label` instance, use the `Label::new()` function. This function takes a string that will be displayed as text in the interface. + +```rust +Label::new("Hello, world!"); +``` + +Now let's dive a bit deeper into how to customize `Label` instances: + +- **Setting Color:** To set the color of the label using various predefined color options such as `Default`, `Muted`, `Created`, `Modified`, `Deleted`, etc, the `color()` function is called on the `Label` instance: + + ```rust + Label::new("Hello, world!").color(LabelColor::Default); + ``` + +- **Setting Line Height Style:** To set the line height style, the `line_height_style()` function is utilized: + + ```rust + Label::new("Hello, world!").line_height_style(LineHeightStyle::TextLabel); + ``` + +- **Adding a Strikethrough:** To add a strikethrough in a `Label`, the `set_strikethrough()` function is used: + + ```rust + Label::new("Hello, world!").set_strikethrough(true); + ``` + +That's it! Now you can use the `Label` component to create and customize text on your application's interface. + +## Building a new component + +TODO diff --git a/crates/ui2/docs/elevation.md b/crates/ui2/docs/elevation.md deleted file mode 100644 index bd34de3396dea1f1042bb267f8a23abe6a45441f..0000000000000000000000000000000000000000 --- a/crates/ui2/docs/elevation.md +++ /dev/null @@ -1,57 +0,0 @@ -# Elevation - -Elevation in Zed applies to all surfaces and components. Elevation is categorized into levels. - -Elevation accomplishes the following: -- Allows surfaces to move in front of or behind others, such as content scrolling beneath app top bars. -- Reflects spatial relationships, for instance, how a floating action button’s shadow intimates its disconnection from a collection of cards. -- Directs attention to structures at the highest elevation, like a temporary dialog arising in front of other surfaces. - -Elevations are the initial elevation values assigned to components by default. - -Components may transition to a higher elevation in some cases, like user interations. - -On such occasions, components transition to predetermined dynamic elevation offsets. These are the typical elevations to which components move when they are not at rest. - -## Understanding Elevation - -Elevation can be thought of as the physical closeness of an element to the user. Elements with lower elevations are physically further away from the user on the z-axis and appear to be underneath elements with higher elevations. - -Material Design 3 has a some great visualizations of elevation that may be helpful to understanding the mental modal of elevation. [Material Design – Elevation](https://m3.material.io/styles/elevation/overview) - -## Elevation Levels - -Zed integrates six unique elevation levels in its design system. The elevation of a surface is expressed as a whole number ranging from 0 to 5, both numbers inclusive. A component’s elevation is ascertained by combining the component’s resting elevation with any dynamic elevation offsets. - -The levels are detailed as follows: - -0. App Background -1. UI Surface -2. Elevated Elements -3. Wash -4. Focused Element -5. Dragged Element - -### 0. App Background - -The app background constitutes the lowest elevation layer, appearing behind all other surfaces and components. It is predominantly used for the background color of the app. - -### 1. UI Surface - -The UI Surface is the standard elevation for components and is placed above the app background. It is generally used for the background color of the app bar, card, and sheet. - -### 2. Elevated Elements - -Elevated elements appear above the UI surface layer surfaces and components. Elevated elements are predominantly used for creating popovers, context menus, and tooltips. - -### 3. Wash - -Wash denotes a distinct elevation reserved to isolate app UI layers from high elevation components such as modals, notifications, and overlaid panels. The wash may not consistently be visible when these components are active. This layer is often referred to as a scrim or overlay and the background color of the wash is typically deployed in its design. - -### 4. Focused Element - -Focused elements obtain a higher elevation above surfaces and components at wash elevation. They are often used for modals, notifications, and overlaid panels and indicate that they are the sole element the user is interacting with at the moment. - -### 5. Dragged Element - -Dragged elements gain the highest elevation, thus appearing above surfaces and components at the elevation of focused elements. These are typically used for elements that are being dragged, following the cursor diff --git a/crates/ui2/docs/hello-world.md b/crates/ui2/docs/hello-world.md new file mode 100644 index 0000000000000000000000000000000000000000..c6ded9ce34144495e911736669b2e07d56acc346 --- /dev/null +++ b/crates/ui2/docs/hello-world.md @@ -0,0 +1,160 @@ +# Hello World + +Let's work through the prototypical "Build a todo app" example to showcase how we might build a simple component from scratch. + +## Setup + +We'll create a headline, a list of todo items, and a form to add new items. + +~~~rust +struct TodoList { + headline: SharedString, + items: Vec, + submit_form: ClickHandler +} + +struct TodoItem { + text: SharedString, + completed: bool, + delete: ClickHandler +} + +impl TodoList { + pub fn new( + // Here we impl Into + headline: impl Into, + items: Vec, + submit_form: ClickHandler + ) -> Self { + Self { + // and here we call .into() so we can simply pass a string + // when creating the headline. This pattern is used throughout + // outr components + headline: headline.into(), + items: Vec::new(), + submit_form, + } + } +} +~~~ + +All of this is relatively straightforward. + +We use [gpui2::SharedString] in components instead of [std::string::String]. This allows us to [TODO: someone who actually knows please explain why we use SharedString]. + +When we want to pass an action we pass a `ClickHandler`. Whenever we want to add an action, the struct it belongs to needs to be generic over the view type `V`. + +~~~rust +use gpui2::hsla + +impl TodoList { + // ... + fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { + div().size_4().bg(hsla(50.0/360.0, 1.0, 0.5, 1.0)) + } +} +~~~ + +Every component needs a render method, and it should return `impl Component`. This basic component will render a 16x16px yellow square on the screen. + +A couple of questions might come to mind: + +**Why is `size_4()` 16px, not 4px?** + +gpui's style system is based on conventions created by [Tailwind CSS](https://tailwindcss.com/). Here is an example of the list of sizes for `width`: [Width - TailwindCSS Docs](https://tailwindcss.com/docs/width). + +I'll quote from the Tailwind [Core Concepts](https://tailwindcss.com/docs/utility-first) docs here: + +> Now I know what you’re thinking, “this is an atrocity, what a horrible mess!” +> and you’re right, it’s kind of ugly. In fact it’s just about impossible to +> think this is a good idea the first time you see it — +> you have to actually try it. + +As you start using the Tailwind-style conventions you will be surprised how quick it makes it to build out UIs. + +**Why `50.0/360.0` in `hsla()`?** + +gpui [gpui2::Hsla] use `0.0-1.0` for all it's values, but it is common for tools to use `0-360` for hue. + +This may change in the future, but this is a little trick that let's you use familiar looking values. + +## Building out the container + +Let's grab our [theme2::colors::ThemeColors] from the theme and start building out a basic container. + +We can access the current theme's colors like this: + +~~~rust +impl TodoList { + // ... + fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { + let color = cx.theme().colors() + + div().size_4().hsla(50.0/360.0, 1.0, 0.5, 1.0) + } +} +~~~ + +Now we have access to the complete set of colors defined in the theme. + +~~~rust +use gpui2::hsla + +impl TodoList { + // ... + fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { + let color = cx.theme().colors() + + div().size_4().bg(color.surface) + } +} +~~~ + +Let's finish up some basic styles for the container then move on to adding the other elements. + +~~~rust +use gpui2::hsla + +impl TodoList { + // ... + fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { + let color = cx.theme().colors() + + div() + // Flex properties + .flex() + .flex_col() // Stack elements vertically + .gap_2() // Add 8px of space between elements + // Size properties + .w_96() // Set width to 384px + .p_4() // Add 16px of padding on all sides + // Color properties + .bg(color.surface) // Set background color + .text_color(color.text) // Set text color + // Border properties + .rounded_md() // Add 4px of border radius + .border() // Add a 1px border + .border_color(color.border) + .child( + "Hello, world!" + ) + } +} +~~~ + +### Headline + +TODO + +### List of todo items + +TODO + +### Input + +TODO + + +### End result + +TODO diff --git a/crates/ui2/docs/todo.md b/crates/ui2/docs/todo.md new file mode 100644 index 0000000000000000000000000000000000000000..e7a053ecf47d212e9527733a629482c57a2359eb --- /dev/null +++ b/crates/ui2/docs/todo.md @@ -0,0 +1,25 @@ +## Documentation priorities: + +These are the priorities to get documented, in a rough stack rank order: + +- [ ] label +- [ ] button +- [ ] icon_button +- [ ] icon +- [ ] list +- [ ] avatar +- [ ] panel +- [ ] modal +- [ ] palette +- [ ] input +- [ ] facepile +- [ ] player +- [ ] stacks +- [ ] context menu +- [ ] input +- [ ] textarea/multiline input (not built - not an editor) +- [ ] indicator +- [ ] public actor +- [ ] keybinding +- [ ] tab +- [ ] toast diff --git a/crates/ui2/src/lib.rs b/crates/ui2/src/lib.rs index d53469638a0a3f82520546a11edc0e0321d4a580..61551a198e296c4a6a1aa632c91bd64da6ba49b2 100644 --- a/crates/ui2/src/lib.rs +++ b/crates/ui2/src/lib.rs @@ -1,29 +1,3 @@ -// TODO: -// Document these: -// - [ ] - label -// - [ ] - button -// - [ ] - icon_button -// - [ ] - icon -// - [ ] - list -// - [ ] - avatar -// - [ ] - panel -// - [ ] - modal -// - [ ] - palette -// - [ ] - input -// - [ ] - facepile -// - [ ] - player -// - [ ] - stacks -// - [ ] - context menu -// - [ ] - input -// - [ ] - textarea (not built) -// - [ ] - indicator -// - [ ] - public actor -// - [ ] - keybinding -// - [ ] - tab -// - [ ] - toast -// - [ ] - status_toast (maybe not built?) -// - [ ] - notification_toast - //! # UI – Zed UI Primitives & Components //! //! This crate provides a set of UI primitives and components that are used to build all of the elements in Zed's UI. @@ -33,44 +7,10 @@ //! This crate is still a work in progress. The initial primitives and components are built for getting all the UI on the screen, //! much of the state and functionality is mocked or hard codeded, and performance has not been a focus. //! -//! Expect some inconsistencies from component to component as we work out the best way to build these components. -//! -//! ## Getting Started -//! -//! This is a quick primer to get you started using the UI components. -//! -//! You shouldn't need to construct an element from scratch very often. If you find -//! yourself manually styling things like hover, text colors, etc, you should -//! probably check that there isn't already a base component for whatever you are building. -//! -//! Here is an into to some of the most common elements: -//! -//! ### Text -//! -//! For generic UI text most frequently you will use a [`Label`] component. -//! -//! ```rust -//! use ui2::prelude::*; -//! use ui2::{Label, LabelColor}; -//! -//! pub fn render_some_ui_text() -> impl Component { -//! div().p_2().child( -//! Label::new("Hello World") -//! .color(LabelColor::Muted) -//! ) -//! } -//! ``` -//! -//! ### Interactive Elements -//! -//! - Icon: To make an icon interactive, use [`IconButton`]. -//! - Button: To make a button interactive, use [`Button`]. -//! -//! ## Design Philosophy -//! -//! Work in Progress! -//! +#![doc = include_str!("../docs/hello-world.md")] +#![doc = include_str!("../docs/building-ui.md")] +#![doc = include_str!("../docs/todo.md")] // TODO: Fix warnings instead of supressing. #![allow(dead_code, unused_variables)] From 2dd32dbe870fcd09e89172d87983be8feeef9473 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 3 Nov 2023 15:53:54 -0700 Subject: [PATCH 11/23] Allow language injection in markdown code blocks in channel notes --- crates/collab_ui/src/channel_view.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/collab_ui/src/channel_view.rs b/crates/collab_ui/src/channel_view.rs index 1bdcebd01855e00948505fa48011ccccde7565f7..fe46f3bb3e5dfc40720ca45c2873c17c9db7cd7a 100644 --- a/crates/collab_ui/src/channel_view.rs +++ b/crates/collab_ui/src/channel_view.rs @@ -75,23 +75,23 @@ impl ChannelView { let workspace = workspace.read(cx); let project = workspace.project().to_owned(); let channel_store = ChannelStore::global(cx); - let markdown = workspace - .app_state() - .languages - .language_for_name("Markdown"); + let language_registry = workspace.app_state().languages.clone(); + let markdown = language_registry.language_for_name("Markdown"); let channel_buffer = channel_store.update(cx, |store, cx| store.open_channel_buffer(channel_id, cx)); cx.spawn(|mut cx| async move { let channel_buffer = channel_buffer.await?; + let markdown = markdown.await.log_err(); - if let Some(markdown) = markdown.await.log_err() { - channel_buffer.update(&mut cx, |buffer, cx| { - buffer.buffer().update(cx, |buffer, cx| { + channel_buffer.update(&mut cx, |buffer, cx| { + buffer.buffer().update(cx, |buffer, cx| { + buffer.set_language_registry(language_registry); + if let Some(markdown) = markdown { buffer.set_language(Some(markdown), cx); - }) - }); - } + } + }) + }); pane.update(&mut cx, |pane, cx| { let buffer_id = channel_buffer.read(cx).remote_id(cx); From 9f40a5c53f29e6a5c2902cab4a62af3d9154d2d9 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 4 Nov 2023 13:54:34 +0200 Subject: [PATCH 12/23] Suppress unused vars warning generated by gpui macro --- crates/gpui_macros/src/gpui_macros.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/gpui_macros/src/gpui_macros.rs b/crates/gpui_macros/src/gpui_macros.rs index aa55c27eaad9069fd8964ea2f2b4f64195bd458c..62fba3b61237bb0cc31b28211f2680d105b559d1 100644 --- a/crates/gpui_macros/src/gpui_macros.rs +++ b/crates/gpui_macros/src/gpui_macros.rs @@ -170,6 +170,8 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream { #max_retries, #detect_nondeterminism, &mut |cx, foreground_platform, deterministic, seed| { + // some of the macro contents do not use all variables, silence the warnings + let _ = (&cx, &foreground_platform, &deterministic, &seed); #cx_vars cx.foreground().run(#inner_fn_name(#inner_fn_args)); #cx_teardowns @@ -247,6 +249,8 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream { #max_retries, #detect_nondeterminism, &mut |cx, foreground_platform, deterministic, seed| { + // some of the macro contents do not use all variables, silence the warnings + let _ = (&cx, &foreground_platform, &deterministic, &seed); #cx_vars #inner_fn_name(#inner_fn_args); #cx_teardowns From b125cc279f5cbcb2042d7383322119fcddc2e00c Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Sat, 4 Nov 2023 11:24:31 -0400 Subject: [PATCH 13/23] Simplify toggle, do some reorganization --- crates/ui2/src/components.rs | 4 + crates/ui2/src/components/button.rs | 21 +- crates/ui2/src/components/context_menu.rs | 17 +- crates/ui2/src/components/list.rs | 324 +++--------------- crates/ui2/src/components/player.rs | 18 + crates/ui2/src/components/slot.rs | 14 + crates/ui2/src/components/toggle.rs | 61 ++++ crates/ui2/src/prelude.rs | 76 ---- crates/ui2/src/static_data.rs | 125 ++----- crates/ui2/src/to_extract/collab_panel.rs | 21 +- .../ui2/src/to_extract/notifications_panel.rs | 29 +- crates/ui2/src/to_extract/project_panel.rs | 13 +- 12 files changed, 224 insertions(+), 499 deletions(-) create mode 100644 crates/ui2/src/components/slot.rs create mode 100644 crates/ui2/src/components/toggle.rs diff --git a/crates/ui2/src/components.rs b/crates/ui2/src/components.rs index f7674c2bd4db5aa4a79ca9d0cc2ed6597ab36002..692cd55e8ec065831c2e85d8a564e90713c3c798 100644 --- a/crates/ui2/src/components.rs +++ b/crates/ui2/src/components.rs @@ -16,9 +16,11 @@ mod palette; mod panel; mod player; mod player_stack; +mod slot; mod stack; mod tab; mod toast; +mod toggle; mod tool_divider; pub use avatar::*; @@ -39,7 +41,9 @@ pub use palette::*; pub use panel::*; pub use player::*; pub use player_stack::*; +pub use slot::*; pub use stack::*; pub use tab::*; pub use toast::*; +pub use toggle::*; pub use tool_divider::*; diff --git a/crates/ui2/src/components/button.rs b/crates/ui2/src/components/button.rs index 073bcdbb4589ed9fc87e4b63dd6acd0bfd3176f4..381db20a8336ccf02694537f3760d5e10a23989a 100644 --- a/crates/ui2/src/components/button.rs +++ b/crates/ui2/src/components/button.rs @@ -2,8 +2,27 @@ use std::sync::Arc; use gpui2::{div, rems, DefiniteLength, Hsla, MouseButton, WindowContext}; -use crate::prelude::*; use crate::{h_stack, Icon, IconColor, IconElement, Label, LabelColor, LineHeightStyle}; +use crate::{prelude::*, IconButton}; + +/// Provides the flexibility to use either a standard +/// button or an icon button in a given context. +pub enum ButtonOrIconButton { + Button(Button), + IconButton(IconButton), +} + +impl From> for ButtonOrIconButton { + fn from(value: Button) -> Self { + Self::Button(value) + } +} + +impl From> for ButtonOrIconButton { + fn from(value: IconButton) -> Self { + Self::IconButton(value) + } +} #[derive(Default, PartialEq, Clone, Copy)] pub enum IconPosition { diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 8345be1b3577724f3967205c3f493abf5945bc2d..4f265a376dec5847e89be537064a843515607341 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -8,7 +8,7 @@ pub enum ContextMenuItem { } impl ContextMenuItem { - fn to_list_item(self) -> ListItem { + fn to_list_item(self) -> ListItem { match self { ContextMenuItem::Header(label) => ListSubHeader::new(label).into(), ContextMenuItem::Entry(label) => { @@ -49,15 +49,12 @@ impl ContextMenu { .bg(cx.theme().colors().elevated_surface) .border() .border_color(cx.theme().colors().border) - .child( - List::new( - self.items - .into_iter() - .map(ContextMenuItem::to_list_item) - .collect(), - ) - .toggle(ToggleState::Toggled), - ) + .child(List::new( + self.items + .into_iter() + .map(ContextMenuItem::to_list_item::) + .collect(), + )) } } diff --git a/crates/ui2/src/components/list.rs b/crates/ui2/src/components/list.rs index 50a86ff256b7a4e9e6f7992acd6f2178c8c32c6a..543432a8935a5392e96e5e1a8ca074adf5388d54 100644 --- a/crates/ui2/src/components/list.rs +++ b/crates/ui2/src/components/list.rs @@ -1,11 +1,11 @@ -use gpui2::{div, px, relative, Div}; +use gpui2::div; use crate::settings::user_settings; use crate::{ - h_stack, v_stack, Avatar, ClickHandler, Icon, IconColor, IconElement, IconSize, Label, - LabelColor, + disclosure_control, h_stack, v_stack, Avatar, Icon, IconColor, IconElement, IconSize, Label, + LabelColor, Toggle, }; -use crate::{prelude::*, Button}; +use crate::{prelude::*, GraphicSlot}; #[derive(Clone, Copy, Default, Debug, PartialEq)] pub enum ListItemVariant { @@ -29,7 +29,7 @@ pub struct ListHeader { left_icon: Option, meta: Option, variant: ListItemVariant, - toggleable: Toggleable, + toggle: Toggle, } impl ListHeader { @@ -39,17 +39,12 @@ impl ListHeader { left_icon: None, meta: None, variant: ListItemVariant::default(), - toggleable: Toggleable::NotToggleable, + toggle: Toggle::NotToggleable, } } - pub fn toggle(mut self, toggle: ToggleState) -> Self { - self.toggleable = toggle.into(); - self - } - - pub fn toggleable(mut self, toggleable: Toggleable) -> Self { - self.toggleable = toggleable; + pub fn toggle(mut self, toggle: Toggle) -> Self { + self.toggle = toggle; self } @@ -63,30 +58,8 @@ impl ListHeader { self } - fn disclosure_control(&self) -> Div { - let is_toggleable = self.toggleable != Toggleable::NotToggleable; - let is_toggled = Toggleable::is_toggled(&self.toggleable); - - match (is_toggleable, is_toggled) { - (false, _) => div(), - (_, true) => div().child( - IconElement::new(Icon::ChevronDown) - .color(IconColor::Muted) - .size(IconSize::Small), - ), - (_, false) => div().child( - IconElement::new(Icon::ChevronRight) - .color(IconColor::Muted) - .size(IconSize::Small), - ), - } - } - fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { - let is_toggleable = self.toggleable != Toggleable::NotToggleable; - let is_toggled = self.toggleable.is_toggled(); - - let disclosure_control = self.disclosure_control(); + let disclosure_control = disclosure_control(self.toggle); let meta = match self.meta { Some(ListHeaderMeta::Tools(icons)) => div().child( @@ -193,12 +166,6 @@ impl ListSubHeader { } } -#[derive(Clone)] -pub enum LeftContent { - Icon(Icon), - Avatar(SharedString), -} - #[derive(Default, PartialEq, Copy, Clone)] pub enum ListEntrySize { #[default] @@ -207,44 +174,36 @@ pub enum ListEntrySize { } #[derive(Component)] -pub enum ListItem { +pub enum ListItem { Entry(ListEntry), - Details(ListDetailsEntry), Separator(ListSeparator), Header(ListSubHeader), } -impl From for ListItem { +impl From for ListItem { fn from(entry: ListEntry) -> Self { Self::Entry(entry) } } -impl From> for ListItem { - fn from(entry: ListDetailsEntry) -> Self { - Self::Details(entry) - } -} - -impl From for ListItem { +impl From for ListItem { fn from(entry: ListSeparator) -> Self { Self::Separator(entry) } } -impl From for ListItem { +impl From for ListItem { fn from(entry: ListSubHeader) -> Self { Self::Header(entry) } } -impl ListItem { - fn render(self, view: &mut V, cx: &mut ViewContext) -> impl Component { +impl ListItem { + fn render(self, view: &mut V, cx: &mut ViewContext) -> impl Component { match self { 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)), - ListItem::Details(details) => div().child(details.render(view, cx)), } } @@ -263,31 +222,29 @@ impl ListItem { #[derive(Component)] pub struct ListEntry { - disclosure_control_style: DisclosureControlVisibility, + disabled: bool, + // TODO: Reintroduce this + // disclosure_control_style: DisclosureControlVisibility, indent_level: u32, label: Label, - left_content: Option, - variant: ListItemVariant, - size: ListEntrySize, - state: InteractionState, - toggle: Option, + left_slot: Option, overflow: OverflowStyle, + size: ListEntrySize, + toggle: Toggle, + variant: ListItemVariant, } impl ListEntry { pub fn new(label: Label) -> Self { Self { - disclosure_control_style: DisclosureControlVisibility::default(), + disabled: false, indent_level: 0, label, - variant: ListItemVariant::default(), - left_content: None, - size: ListEntrySize::default(), - state: InteractionState::default(), - // TODO: Should use Toggleable::NotToggleable - // or remove Toggleable::NotToggleable from the system - toggle: None, + left_slot: None, overflow: OverflowStyle::Hidden, + size: ListEntrySize::default(), + toggle: Toggle::NotToggleable, + variant: ListItemVariant::default(), } } @@ -301,28 +258,23 @@ impl ListEntry { self } - pub fn toggle(mut self, toggle: ToggleState) -> Self { - self.toggle = Some(toggle); + pub fn toggle(mut self, toggle: Toggle) -> Self { + self.toggle = toggle; self } - pub fn left_content(mut self, left_content: LeftContent) -> Self { - self.left_content = Some(left_content); + pub fn left_content(mut self, left_content: GraphicSlot) -> Self { + self.left_slot = Some(left_content); self } pub fn left_icon(mut self, left_icon: Icon) -> Self { - self.left_content = Some(LeftContent::Icon(left_icon)); + self.left_slot = Some(GraphicSlot::Icon(left_icon)); self } pub fn left_avatar(mut self, left_avatar: impl Into) -> Self { - self.left_content = Some(LeftContent::Avatar(left_avatar.into())); - self - } - - pub fn state(mut self, state: InteractionState) -> Self { - self.state = state; + self.left_slot = Some(GraphicSlot::Avatar(left_avatar.into())); self } @@ -331,63 +283,19 @@ impl ListEntry { self } - pub fn disclosure_control_style( - mut self, - disclosure_control_style: DisclosureControlVisibility, - ) -> Self { - self.disclosure_control_style = disclosure_control_style; - self - } - - fn label_color(&self) -> LabelColor { - match self.state { - InteractionState::Disabled => LabelColor::Disabled, - _ => Default::default(), - } - } - - fn icon_color(&self) -> IconColor { - match self.state { - InteractionState::Disabled => IconColor::Disabled, - _ => Default::default(), - } - } - - fn disclosure_control( - &mut self, - cx: &mut ViewContext, - ) -> Option> { - let disclosure_control_icon = if let Some(ToggleState::Toggled) = self.toggle { - IconElement::new(Icon::ChevronDown) - } else { - IconElement::new(Icon::ChevronRight) - } - .color(IconColor::Muted) - .size(IconSize::Small); - - match (self.toggle, self.disclosure_control_style) { - (Some(_), DisclosureControlVisibility::OnHover) => { - Some(div().absolute().neg_left_5().child(disclosure_control_icon)) - } - (Some(_), DisclosureControlVisibility::Always) => { - Some(div().child(disclosure_control_icon)) - } - (None, _) => None, - } - } - - fn render(mut self, _view: &mut V, cx: &mut ViewContext) -> impl Component { + fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { let settings = user_settings(cx); - let left_content = match self.left_content.clone() { - Some(LeftContent::Icon(i)) => Some( + let left_content = match self.left_slot.clone() { + Some(GraphicSlot::Icon(i)) => Some( h_stack().child( IconElement::new(i) .size(IconSize::Small) .color(IconColor::Muted), ), ), - Some(LeftContent::Avatar(src)) => Some(h_stack().child(Avatar::new(src))), + Some(GraphicSlot::Avatar(src)) => Some(h_stack().child(Avatar::new(src))), + Some(GraphicSlot::PublicActor(src)) => Some(h_stack().child(Avatar::new(src))), None => None, }; @@ -400,10 +308,7 @@ impl ListEntry { .relative() .group("") .bg(cx.theme().colors().surface) - .when(self.state == InteractionState::Focused, |this| { - this.border() - .border_color(cx.theme().colors().border_focused) - }) + // TODO: Add focus state .child( sized_item .when(self.variant == ListItemVariant::Inset, |this| this.px_2()) @@ -425,131 +330,13 @@ impl ListEntry { .gap_1() .items_center() .relative() - .children(self.disclosure_control(cx)) + .child(disclosure_control(self.toggle)) .children(left_content) .child(self.label), ) } } -struct ListDetailsEntryHandlers { - click: Option>, -} - -impl Default for ListDetailsEntryHandlers { - fn default() -> Self { - Self { click: None } - } -} - -#[derive(Component)] -pub struct ListDetailsEntry { - label: SharedString, - meta: Option, - left_content: Option, - handlers: ListDetailsEntryHandlers, - actions: Option>>, - // TODO: make this more generic instead of - // specifically for notifications - seen: bool, -} - -impl ListDetailsEntry { - pub fn new(label: impl Into) -> Self { - Self { - label: label.into(), - meta: None, - left_content: None, - handlers: ListDetailsEntryHandlers::default(), - actions: None, - seen: false, - } - } - - pub fn meta(mut self, meta: impl Into) -> Self { - self.meta = Some(meta.into()); - self - } - - pub fn seen(mut self, seen: bool) -> Self { - self.seen = seen; - self - } - - pub fn on_click(mut self, handler: ClickHandler) -> Self { - self.handlers.click = Some(handler); - self - } - - pub fn actions(mut self, actions: Vec>) -> Self { - self.actions = Some(actions); - self - } - - fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { - let settings = user_settings(cx); - - let (item_bg, item_bg_hover, item_bg_active) = ( - cx.theme().colors().ghost_element, - cx.theme().colors().ghost_element_hover, - cx.theme().colors().ghost_element_active, - ); - - let label_color = match self.seen { - true => LabelColor::Muted, - false => LabelColor::Default, - }; - - div() - .relative() - .group("") - .bg(item_bg) - .px_2() - .py_1p5() - .w_full() - .z_index(1) - .when(!self.seen, |this| { - this.child( - div() - .absolute() - .left(px(3.0)) - .top_3() - .rounded_full() - .border_2() - .border_color(cx.theme().colors().surface) - .w(px(9.0)) - .h(px(9.0)) - .z_index(2) - .bg(cx.theme().status().info), - ) - }) - .child( - v_stack() - .w_full() - .line_height(relative(1.2)) - .gap_1() - .child( - div() - .w_5() - .h_5() - .rounded_full() - .bg(cx.theme().colors().icon_accent), - ) - .child(Label::new(self.label.clone()).color(label_color)) - .children( - self.meta - .map(|meta| Label::new(meta).color(LabelColor::Muted)), - ) - .child( - h_stack() - .gap_1() - .justify_end() - .children(self.actions.unwrap_or_default()), - ), - ) - } -} - #[derive(Clone, Component)] pub struct ListSeparator; @@ -564,20 +351,22 @@ impl ListSeparator { } #[derive(Component)] -pub struct List { - items: Vec>, +pub struct List { + items: Vec, + /// Message to display when the list is empty + /// Defaults to "No items" empty_message: SharedString, header: Option, - toggleable: Toggleable, + toggle: Toggle, } -impl List { - pub fn new(items: Vec>) -> Self { +impl List { + pub fn new(items: Vec) -> Self { Self { items, empty_message: "No items".into(), header: None, - toggleable: Toggleable::default(), + toggle: Toggle::NotToggleable, } } @@ -591,19 +380,16 @@ impl List { self } - pub fn toggle(mut self, toggle: ToggleState) -> Self { - self.toggleable = toggle.into(); + pub fn toggle(mut self, toggle: Toggle) -> Self { + self.toggle = toggle; self } - fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { - let is_toggleable = self.toggleable != Toggleable::NotToggleable; - let is_toggled = Toggleable::is_toggled(&self.toggleable); - - let list_content = match (self.items.is_empty(), is_toggled) { + fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { + let list_content = match (self.items.is_empty(), self.toggle) { (false, _) => div().children(self.items), - (true, false) => div(), - (true, true) => { + (true, Toggle::Toggled(false)) => div(), + (true, _) => { div().child(Label::new(self.empty_message.clone()).color(LabelColor::Muted)) } }; @@ -611,7 +397,7 @@ impl List { v_stack() .w_full() .py_1() - .children(self.header.map(|header| header.toggleable(self.toggleable))) + .children(self.header.map(|header| header)) .child(list_content) } } diff --git a/crates/ui2/src/components/player.rs b/crates/ui2/src/components/player.rs index c7b7ade1c13c62878e8ae72ce828bde30ab9d375..b6c80400cf373dd716cc9cb1686a7aee8af05cc0 100644 --- a/crates/ui2/src/components/player.rs +++ b/crates/ui2/src/components/player.rs @@ -2,6 +2,24 @@ use gpui2::{Hsla, ViewContext}; use crate::prelude::*; +/// Represents a person with a Zed account's public profile. +/// All data in this struct should be considered public. +pub struct PublicPlayer { + pub username: SharedString, + pub avatar: SharedString, + pub is_contact: bool, +} + +impl PublicPlayer { + pub fn new(username: impl Into, avatar: impl Into) -> Self { + Self { + username: username.into(), + avatar: avatar.into(), + is_contact: false, + } + } +} + #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] pub enum PlayerStatus { #[default] diff --git a/crates/ui2/src/components/slot.rs b/crates/ui2/src/components/slot.rs new file mode 100644 index 0000000000000000000000000000000000000000..f980e2fbda51a3b86ae5d677ac5838cb94ea09d2 --- /dev/null +++ b/crates/ui2/src/components/slot.rs @@ -0,0 +1,14 @@ +use gpui2::SharedString; + +use crate::Icon; + +#[derive(Debug, Clone)] +/// A slot utility that provides a way to to pass either +/// an icon or an image to a component. +/// +/// Can be filled with a [] +pub enum GraphicSlot { + Icon(Icon), + Avatar(SharedString), + PublicActor(SharedString), +} diff --git a/crates/ui2/src/components/toggle.rs b/crates/ui2/src/components/toggle.rs new file mode 100644 index 0000000000000000000000000000000000000000..adde36758159cf6a1ea93ec2f152f0dfcf904f6b --- /dev/null +++ b/crates/ui2/src/components/toggle.rs @@ -0,0 +1,61 @@ +use gpui2::{div, Component, ParentElement}; + +use crate::{Icon, IconColor, IconElement, IconSize}; + +/// Whether the entry is toggleable, and if so, whether it is currently toggled. +/// +/// To make an element toggleable, simply add a `Toggle::Toggled(_)` and handle it's cases. +/// +/// You can check if an element is toggleable with `.is_toggleable()` +/// +/// Possible values: +/// - `Toggle::NotToggleable` - The entry is not toggleable +/// - `Toggle::Toggled(true)` - The entry is toggleable and toggled +/// - `Toggle::Toggled(false)` - The entry is toggleable and not toggled +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum Toggle { + NotToggleable, + Toggled(bool), +} + +impl Toggle { + /// Returns true if the entry is toggled (or is not toggleable.) + /// + /// As element that isn't toggleable is always "expanded" or "enabled" + /// returning true in that case makes sense. + pub fn is_toggled(&self) -> bool { + match self { + Self::Toggled(false) => false, + _ => true, + } + } + + pub fn is_toggleable(&self) -> bool { + match self { + Self::Toggled(_) => true, + _ => false, + } + } +} + +impl From for Toggle { + fn from(toggled: bool) -> Self { + Toggle::Toggled(toggled) + } +} + +pub fn disclosure_control(toggle: Toggle) -> impl Component { + match (toggle.is_toggleable(), toggle.is_toggled()) { + (false, _) => div(), + (_, true) => div().child( + IconElement::new(Icon::ChevronDown) + .color(IconColor::Muted) + .size(IconSize::Small), + ), + (_, false) => div().child( + IconElement::new(Icon::ChevronRight) + .color(IconColor::Muted) + .size(IconSize::Small), + ), + } +} diff --git a/crates/ui2/src/prelude.rs b/crates/ui2/src/prelude.rs index fbb7ccc528107de3d0eef115ca7fc4ba536a68e2..8ba74cce95cdf59c79d2d323ffe25e9abb22dfff 100644 --- a/crates/ui2/src/prelude.rs +++ b/crates/ui2/src/prelude.rs @@ -10,24 +10,6 @@ pub use theme2::ActiveTheme; use gpui2::Hsla; use strum::EnumIter; -/// Represents a person with a Zed account's public profile. -/// All data in this struct should be considered public. -pub struct PublicActor { - pub username: SharedString, - pub avatar: SharedString, - pub is_contact: bool, -} - -impl PublicActor { - pub fn new(username: impl Into, avatar: impl Into) -> Self { - Self { - username: username.into(), - avatar: avatar.into(), - is_contact: false, - } - } -} - #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)] pub enum FileSystemStatus { #[default] @@ -179,61 +161,3 @@ pub enum SelectedState { PartiallySelected, Selected, } - -#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] -pub enum Toggleable { - Toggleable(ToggleState), - #[default] - NotToggleable, -} - -impl Toggleable { - pub fn is_toggled(&self) -> bool { - match self { - Self::Toggleable(ToggleState::Toggled) => true, - _ => false, - } - } -} - -impl From for Toggleable { - fn from(state: ToggleState) -> Self { - Self::Toggleable(state) - } -} - -#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] -pub enum ToggleState { - /// The "on" state of a toggleable element. - /// - /// Example: - /// - A collasable list that is currently expanded - /// - A toggle button that is currently on. - Toggled, - /// The "off" state of a toggleable element. - /// - /// Example: - /// - A collasable list that is currently collapsed - /// - A toggle button that is currently off. - #[default] - NotToggled, -} - -impl From for ToggleState { - fn from(toggleable: Toggleable) -> Self { - match toggleable { - Toggleable::Toggleable(state) => state, - Toggleable::NotToggleable => ToggleState::NotToggled, - } - } -} - -impl From for ToggleState { - fn from(toggled: bool) -> Self { - if toggled { - ToggleState::Toggled - } else { - ToggleState::NotToggled - } - } -} diff --git a/crates/ui2/src/static_data.rs b/crates/ui2/src/static_data.rs index 68f625c75d6f2ac24e7caf8e97469a0c082effad..5342e1fb165606a8316fbb542aad2b78104ec4ea 100644 --- a/crates/ui2/src/static_data.rs +++ b/crates/ui2/src/static_data.rs @@ -7,13 +7,13 @@ use gpui2::{AppContext, ViewContext}; use rand::Rng; use theme2::ActiveTheme; +use crate::HighlightedText; use crate::{ Buffer, BufferRow, BufferRows, Button, EditorPane, FileSystemStatus, GitStatus, - HighlightedLine, Icon, Keybinding, Label, LabelColor, ListEntry, ListEntrySize, ListSubHeader, - Livestream, MicStatus, ModifierKeys, Notification, PaletteItem, Player, PlayerCallStatus, - PlayerWithCallStatus, PublicActor, ScreenShareStatus, Symbol, Tab, ToggleState, VideoStatus, + HighlightedLine, Icon, Keybinding, Label, LabelColor, ListEntry, ListEntrySize, Livestream, + MicStatus, ModifierKeys, Notification, PaletteItem, Player, PlayerCallStatus, + PlayerWithCallStatus, PublicPlayer, ScreenShareStatus, Symbol, Tab, Toggle, VideoStatus, }; -use crate::{HighlightedText, ListDetailsEntry}; use crate::{ListItem, NotificationAction}; pub fn static_tabs_example() -> Vec { @@ -345,7 +345,7 @@ pub fn static_new_notification_items_2() -> Vec> { DateTime::parse_from_rfc3339("2023-11-02T12:09:07Z") .unwrap() .naive_local(), - PublicActor::new("as-cii", "http://github.com/as-cii.png?s=50"), + PublicPlayer::new("as-cii", "http://github.com/as-cii.png?s=50"), [ NotificationAction::new( Button::new("Decline"), @@ -374,7 +374,7 @@ pub fn static_new_notification_items_2() -> Vec> { DateTime::parse_from_rfc3339("2023-11-01T12:09:07Z") .unwrap() .naive_local(), - PublicActor::new("as-cii", "http://github.com/as-cii.png?s=50"), + PublicPlayer::new("as-cii", "http://github.com/as-cii.png?s=50"), [ NotificationAction::new( Button::new("Decline"), @@ -403,7 +403,7 @@ pub fn static_new_notification_items_2() -> Vec> { DateTime::parse_from_rfc3339("2022-10-25T12:09:07Z") .unwrap() .naive_local(), - PublicActor::new("as-cii", "http://github.com/as-cii.png?s=50"), + PublicPlayer::new("as-cii", "http://github.com/as-cii.png?s=50"), [ NotificationAction::new( Button::new("Decline"), @@ -432,7 +432,7 @@ pub fn static_new_notification_items_2() -> Vec> { DateTime::parse_from_rfc3339("2021-10-12T12:09:07Z") .unwrap() .naive_local(), - PublicActor::new("as-cii", "http://github.com/as-cii.png?s=50"), + PublicPlayer::new("as-cii", "http://github.com/as-cii.png?s=50"), [ NotificationAction::new( Button::new("Decline"), @@ -461,7 +461,7 @@ pub fn static_new_notification_items_2() -> Vec> { DateTime::parse_from_rfc3339("1969-07-20T00:00:00Z") .unwrap() .naive_local(), - PublicActor::new("as-cii", "http://github.com/as-cii.png?s=50"), + PublicPlayer::new("as-cii", "http://github.com/as-cii.png?s=50"), [ NotificationAction::new( Button::new("Decline"), @@ -478,89 +478,12 @@ pub fn static_new_notification_items_2() -> Vec> { ] } -pub fn static_new_notification_items() -> Vec> { - vec![ - ListItem::Header(ListSubHeader::new("New")), - ListItem::Details( - ListDetailsEntry::new("maxdeviant invited you to join a stream in #design.") - .meta("4 people in stream."), - ), - ListItem::Details(ListDetailsEntry::new( - "nathansobo accepted your contact request.", - )), - ListItem::Header(ListSubHeader::new("Earlier")), - ListItem::Details( - ListDetailsEntry::new("mikaylamaki added you as a contact.").actions(vec![ - Button::new("Decline"), - Button::new("Accept").variant(crate::ButtonVariant::Filled), - ]), - ), - ListItem::Details( - ListDetailsEntry::new("maxdeviant invited you to a stream in #design.") - .seen(true) - .meta("This stream has ended."), - ), - ListItem::Details(ListDetailsEntry::new( - "as-cii accepted your contact request.", - )), - ListItem::Details( - ListDetailsEntry::new("You were added as an admin on the #gpui2 channel.").seen(true), - ), - ListItem::Details(ListDetailsEntry::new( - "osiewicz accepted your contact request.", - )), - ListItem::Details(ListDetailsEntry::new( - "ConradIrwin accepted your contact request.", - )), - ListItem::Details( - ListDetailsEntry::new("nathansobo invited you to a stream in #gpui2.") - .seen(true) - .meta("This stream has ended."), - ), - ListItem::Details(ListDetailsEntry::new( - "nathansobo accepted your contact request.", - )), - ListItem::Header(ListSubHeader::new("Earlier")), - ListItem::Details( - ListDetailsEntry::new("mikaylamaki added you as a contact.").actions(vec![ - Button::new("Decline"), - Button::new("Accept").variant(crate::ButtonVariant::Filled), - ]), - ), - ListItem::Details( - ListDetailsEntry::new("maxdeviant invited you to a stream in #design.") - .seen(true) - .meta("This stream has ended."), - ), - ListItem::Details(ListDetailsEntry::new( - "as-cii accepted your contact request.", - )), - ListItem::Details( - ListDetailsEntry::new("You were added as an admin on the #gpui2 channel.").seen(true), - ), - ListItem::Details(ListDetailsEntry::new( - "osiewicz accepted your contact request.", - )), - ListItem::Details(ListDetailsEntry::new( - "ConradIrwin accepted your contact request.", - )), - ListItem::Details( - ListDetailsEntry::new("nathansobo invited you to a stream in #gpui2.") - .seen(true) - .meta("This stream has ended."), - ), - ] - .into_iter() - .map(From::from) - .collect() -} - -pub fn static_project_panel_project_items() -> Vec> { +pub fn static_project_panel_project_items() -> Vec { vec![ ListEntry::new(Label::new("zed")) .left_icon(Icon::FolderOpen.into()) .indent_level(0) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ListEntry::new(Label::new(".cargo")) .left_icon(Icon::Folder.into()) .indent_level(1), @@ -579,14 +502,14 @@ pub fn static_project_panel_project_items() -> Vec> { ListEntry::new(Label::new("assets")) .left_icon(Icon::Folder.into()) .indent_level(1) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ListEntry::new(Label::new("cargo-target").color(LabelColor::Hidden)) .left_icon(Icon::Folder.into()) .indent_level(1), ListEntry::new(Label::new("crates")) .left_icon(Icon::FolderOpen.into()) .indent_level(1) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ListEntry::new(Label::new("activity_indicator")) .left_icon(Icon::Folder.into()) .indent_level(2), @@ -608,38 +531,38 @@ pub fn static_project_panel_project_items() -> Vec> { ListEntry::new(Label::new("sqlez").color(LabelColor::Modified)) .left_icon(Icon::Folder.into()) .indent_level(2) - .toggle(ToggleState::NotToggled), + .toggle(Toggle::Toggled(false)), ListEntry::new(Label::new("gpui2")) .left_icon(Icon::FolderOpen.into()) .indent_level(2) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ListEntry::new(Label::new("src")) .left_icon(Icon::FolderOpen.into()) .indent_level(3) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ListEntry::new(Label::new("derive_element.rs")) .left_icon(Icon::FileRust.into()) .indent_level(4), ListEntry::new(Label::new("storybook").color(LabelColor::Modified)) .left_icon(Icon::FolderOpen.into()) .indent_level(1) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ListEntry::new(Label::new("docs").color(LabelColor::Default)) .left_icon(Icon::Folder.into()) .indent_level(2) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ListEntry::new(Label::new("src").color(LabelColor::Modified)) .left_icon(Icon::FolderOpen.into()) .indent_level(3) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ListEntry::new(Label::new("ui").color(LabelColor::Modified)) .left_icon(Icon::FolderOpen.into()) .indent_level(4) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ListEntry::new(Label::new("component").color(LabelColor::Created)) .left_icon(Icon::FolderOpen.into()) .indent_level(5) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ListEntry::new(Label::new("facepile.rs").color(LabelColor::Default)) .left_icon(Icon::FileRust.into()) .indent_level(6), @@ -682,7 +605,7 @@ pub fn static_project_panel_project_items() -> Vec> { .collect() } -pub fn static_project_panel_single_items() -> Vec> { +pub fn static_project_panel_single_items() -> Vec { vec![ ListEntry::new(Label::new("todo.md")) .left_icon(Icon::FileDoc.into()) @@ -699,7 +622,7 @@ pub fn static_project_panel_single_items() -> Vec> { .collect() } -pub fn static_collab_panel_current_call() -> Vec> { +pub fn static_collab_panel_current_call() -> Vec { vec![ ListEntry::new(Label::new("as-cii")).left_avatar("http://github.com/as-cii.png?s=50"), ListEntry::new(Label::new("nathansobo")) @@ -712,7 +635,7 @@ pub fn static_collab_panel_current_call() -> Vec> { .collect() } -pub fn static_collab_panel_channels() -> Vec> { +pub fn static_collab_panel_channels() -> Vec { vec![ ListEntry::new(Label::new("zed")) .left_icon(Icon::Hash.into()) diff --git a/crates/ui2/src/to_extract/collab_panel.rs b/crates/ui2/src/to_extract/collab_panel.rs index a0e3b55f63c43c57c37645ae7c4c7492e92f3d03..9019456dd131800efecbd68ac1d8bcabae704090 100644 --- a/crates/ui2/src/to_extract/collab_panel.rs +++ b/crates/ui2/src/to_extract/collab_panel.rs @@ -1,7 +1,6 @@ -use crate::prelude::*; +use crate::{prelude::*, Toggle}; use crate::{ - static_collab_panel_channels, static_collab_panel_current_call, v_stack, Icon, List, - ListHeader, ToggleState, + static_collab_panel_channels, static_collab_panel_current_call, v_stack, Icon, List, ListHeader, }; #[derive(Component)] @@ -34,17 +33,17 @@ impl CollabPanel { .header( ListHeader::new("CRDB") .left_icon(Icon::Hash.into()) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ), ) .child( v_stack().id("channels").py_1().child( List::new(static_collab_panel_channels()) - .header(ListHeader::new("CHANNELS").toggle(ToggleState::Toggled)) + .header(ListHeader::new("CHANNELS").toggle(Toggle::Toggled(true))) .empty_message("No channels yet. Add a channel to get started.") - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ), ) .child( @@ -52,9 +51,9 @@ impl CollabPanel { List::new(static_collab_panel_current_call()) .header( ListHeader::new("CONTACTS – ONLINE") - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ) - .toggle(ToggleState::Toggled), + .toggle(Toggle::Toggled(true)), ), ) .child( @@ -62,9 +61,9 @@ impl CollabPanel { List::new(static_collab_panel_current_call()) .header( ListHeader::new("CONTACTS – OFFLINE") - .toggle(ToggleState::NotToggled), + .toggle(Toggle::Toggled(false)), ) - .toggle(ToggleState::NotToggled), + .toggle(Toggle::Toggled(false)), ), ), ) diff --git a/crates/ui2/src/to_extract/notifications_panel.rs b/crates/ui2/src/to_extract/notifications_panel.rs index 74f015ac068706cd09242dd04f30d8b09e285842..789aa2b0aa11d5f2dded289e1d99ddc433cfae2f 100644 --- a/crates/ui2/src/to_extract/notifications_panel.rs +++ b/crates/ui2/src/to_extract/notifications_panel.rs @@ -1,8 +1,8 @@ use crate::utils::naive_format_distance_from_now; use crate::{ - h_stack, prelude::*, static_new_notification_items_2, v_stack, Avatar, Button, Icon, - IconButton, IconElement, Label, LabelColor, LineHeightStyle, ListHeaderMeta, ListSeparator, - UnreadIndicator, + h_stack, prelude::*, static_new_notification_items_2, v_stack, Avatar, ButtonOrIconButton, + Icon, IconElement, Label, LabelColor, LineHeightStyle, ListHeaderMeta, ListSeparator, + PublicPlayer, UnreadIndicator, }; use crate::{ClickHandler, ListHeader}; @@ -57,23 +57,6 @@ impl NotificationsPanel { } } -pub enum ButtonOrIconButton { - Button(Button), - IconButton(IconButton), -} - -impl From> for ButtonOrIconButton { - fn from(value: Button) -> Self { - Self::Button(value) - } -} - -impl From> for ButtonOrIconButton { - fn from(value: IconButton) -> Self { - Self::IconButton(value) - } -} - pub struct NotificationAction { button: ButtonOrIconButton, tooltip: SharedString, @@ -102,7 +85,7 @@ impl NotificationAction { } pub enum ActorOrIcon { - Actor(PublicActor), + Actor(PublicPlayer), Icon(Icon), } @@ -171,7 +154,7 @@ impl Notification { id: impl Into, message: impl Into, date_received: NaiveDateTime, - actor: PublicActor, + actor: PublicPlayer, click_action: ClickHandler, ) -> Self { Self::new( @@ -210,7 +193,7 @@ impl Notification { id: impl Into, message: impl Into, date_received: NaiveDateTime, - actor: PublicActor, + actor: PublicPlayer, actions: [NotificationAction; 2], ) -> Self { Self::new( diff --git a/crates/ui2/src/to_extract/project_panel.rs b/crates/ui2/src/to_extract/project_panel.rs index 76fa50d3380188b6945fa95e5426071d0baec69c..807768427b21729f1b1bfd6f3cc107cddb67423d 100644 --- a/crates/ui2/src/to_extract/project_panel.rs +++ b/crates/ui2/src/to_extract/project_panel.rs @@ -18,8 +18,7 @@ impl ProjectPanel { .id(self.id.clone()) .flex() .flex_col() - .w_full() - .h_full() + .size_full() .bg(cx.theme().colors().surface) .child( div() @@ -30,15 +29,13 @@ impl ProjectPanel { .overflow_y_scroll() .child( List::new(static_project_panel_single_items()) - .header(ListHeader::new("FILES").toggle(ToggleState::Toggled)) - .empty_message("No files in directory") - .toggle(ToggleState::Toggled), + .header(ListHeader::new("FILES")) + .empty_message("No files in directory"), ) .child( List::new(static_project_panel_project_items()) - .header(ListHeader::new("PROJECT").toggle(ToggleState::Toggled)) - .empty_message("No folders in directory") - .toggle(ToggleState::Toggled), + .header(ListHeader::new("PROJECT")) + .empty_message("No folders in directory"), ), ) .child( From 1bce5dcc69b4b89b9be06142ac7fe843c4bcdf06 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Sun, 5 Nov 2023 01:06:41 -0500 Subject: [PATCH 14/23] Add checkboxes and their stories --- assets/icons/dash.svg | 1 + crates/storybook2/src/story_selector.rs | 2 + crates/theme2/src/colors.rs | 2 + crates/theme2/src/default_colors.rs | 4 + crates/ui2/docs/building-ui.md | 10 ++ crates/ui2/src/components.rs | 2 + crates/ui2/src/components/checkbox.rs | 217 ++++++++++++++++++++++++ crates/ui2/src/components/icon.rs | 4 + crates/ui2/src/prelude.rs | 6 +- 9 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 assets/icons/dash.svg create mode 100644 crates/ui2/src/components/checkbox.rs diff --git a/assets/icons/dash.svg b/assets/icons/dash.svg new file mode 100644 index 0000000000000000000000000000000000000000..efff9eab5e82ac7dfbc9263081fc25fc1eae2551 --- /dev/null +++ b/assets/icons/dash.svg @@ -0,0 +1 @@ + diff --git a/crates/storybook2/src/story_selector.rs b/crates/storybook2/src/story_selector.rs index a78705c7bbfd9d68308c793809596e1ea3e729f2..2adf2956d33512930bf8e829a3845d7ba5522dbc 100644 --- a/crates/storybook2/src/story_selector.rs +++ b/crates/storybook2/src/story_selector.rs @@ -19,6 +19,7 @@ pub enum ComponentStory { Buffer, Button, ChatPanel, + Checkbox, CollabPanel, Colors, CommandPalette, @@ -61,6 +62,7 @@ impl ComponentStory { Self::Buffer => cx.build_view(|_| ui::BufferStory).into(), Self::Button => cx.build_view(|_| ButtonStory).into(), Self::ChatPanel => cx.build_view(|_| ui::ChatPanelStory).into(), + Self::Checkbox => cx.build_view(|_| ui::CheckboxStory).into(), Self::CollabPanel => cx.build_view(|_| ui::CollabPanelStory).into(), Self::Colors => cx.build_view(|_| ColorsStory).into(), Self::CommandPalette => cx.build_view(|_| ui::CommandPaletteStory).into(), diff --git a/crates/theme2/src/colors.rs b/crates/theme2/src/colors.rs index b02a9c14dfa77a10146540ac8ec3baeb0e84c929..b9f8804205da9afb4dd8a9c348276c53063fbc30 100644 --- a/crates/theme2/src/colors.rs +++ b/crates/theme2/src/colors.rs @@ -54,7 +54,9 @@ pub struct ThemeColors { pub border: Hsla, pub border_variant: Hsla, pub border_focused: Hsla, + pub border_selected: Hsla, pub border_transparent: Hsla, + pub border_disabled: Hsla, pub elevated_surface: Hsla, pub surface: Hsla, pub background: Hsla, diff --git a/crates/theme2/src/default_colors.rs b/crates/theme2/src/default_colors.rs index 802392d2963389bdf7ef95d66d4022e49cf0760f..4ecae43b1559c223559dce98546310f0b5afc3aa 100644 --- a/crates/theme2/src/default_colors.rs +++ b/crates/theme2/src/default_colors.rs @@ -205,6 +205,8 @@ impl ThemeColors { border: neutral().light().step_6(), border_variant: neutral().light().step_5(), border_focused: blue().light().step_5(), + border_disabled: neutral().light().step_3(), + border_selected: blue().light().step_5(), border_transparent: system.transparent, elevated_surface: neutral().light().step_2(), surface: neutral().light().step_2(), @@ -250,6 +252,8 @@ impl ThemeColors { border: neutral().dark().step_6(), border_variant: neutral().dark().step_5(), border_focused: blue().dark().step_5(), + border_disabled: neutral().dark().step_3(), + border_selected: blue().dark().step_5(), border_transparent: system.transparent, elevated_surface: neutral().dark().step_2(), surface: neutral().dark().step_2(), diff --git a/crates/ui2/docs/building-ui.md b/crates/ui2/docs/building-ui.md index a2a3ff697b1a6a69d7c2a216912dd62a86f0b4c3..e0160e336ed36df3a4354c8e7ba186a035502227 100644 --- a/crates/ui2/docs/building-ui.md +++ b/crates/ui2/docs/building-ui.md @@ -2,6 +2,16 @@ ## Common patterns +### Method ordering + +- id +- Flex properties +- Position properties +- Size properties +- Style properties +- Handlers +- State properties + ### Using the Label Component to Create UI Text The `Label` component helps in displaying text on user interfaces. It creates an interface where specific parameters such as label color, line height style, and strikethrough can be set. diff --git a/crates/ui2/src/components.rs b/crates/ui2/src/components.rs index 692cd55e8ec065831c2e85d8a564e90713c3c798..a8a7ddfd46f803cd9760438edb89a62cc334dfc5 100644 --- a/crates/ui2/src/components.rs +++ b/crates/ui2/src/components.rs @@ -1,5 +1,6 @@ mod avatar; mod button; +mod checkbox; mod context_menu; mod details; mod facepile; @@ -25,6 +26,7 @@ mod tool_divider; pub use avatar::*; pub use button::*; +pub use checkbox::*; pub use context_menu::*; pub use details::*; pub use facepile::*; diff --git a/crates/ui2/src/components/checkbox.rs b/crates/ui2/src/components/checkbox.rs new file mode 100644 index 0000000000000000000000000000000000000000..3add6cebaccc07847310ce1445dc6ecf0a6f635b --- /dev/null +++ b/crates/ui2/src/components/checkbox.rs @@ -0,0 +1,217 @@ +///! # Checkbox +///! +///! Checkboxes are used for multiple choices, not for mutually exclusive choices. +///! Each checkbox works independently from other checkboxes in the list, +///! therefore checking an additional box does not affect any other selections. +use gpui2::{ + div, Component, ParentElement, SharedString, StatelessInteractive, Styled, ViewContext, +}; +use theme2::ActiveTheme; + +use crate::{Icon, IconColor, IconElement, Selected}; + +#[derive(Component)] +pub struct Checkbox { + id: SharedString, + checked: Selected, + disabled: bool, +} + +impl Checkbox { + pub fn new(id: impl Into) -> Self { + Self { + id: id.into(), + checked: Selected::Unselected, + disabled: false, + } + } + + pub fn toggle(mut self) -> Self { + self.checked = match self.checked { + Selected::Selected => Selected::Unselected, + Selected::Unselected => Selected::Selected, + Selected::Indeterminate => Selected::Selected, + }; + self + } + + pub fn set_indeterminate(mut self) -> Self { + self.checked = Selected::Indeterminate; + self + } + + pub fn set_disabled(mut self, disabled: bool) -> Self { + self.disabled = disabled; + self + } + + pub fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { + let group_id = format!("checkbox_group_{}", self.id); + + // The icon is different depending on the state of the checkbox. + // + // We need the match to return all the same type, + // so we wrap the eatch result in a div. + // + // We are still exploring the best way to handle this. + let icon = match self.checked { + // When selected, we show a checkmark. + Selected::Selected => { + div().child( + IconElement::new(Icon::Check) + .size(crate::IconSize::Small) + .color( + // If the checkbox is disabled we change the color of the icon. + if self.disabled { + IconColor::Disabled + } else { + IconColor::Selected + }, + ), + ) + } + // In an indeterminate state, we show a dash. + Selected::Indeterminate => { + div().child( + IconElement::new(Icon::Dash) + .size(crate::IconSize::Small) + .color( + // If the checkbox is disabled we change the color of the icon. + if self.disabled { + IconColor::Disabled + } else { + IconColor::Selected + }, + ), + ) + } + // When unselected, we show nothing. + Selected::Unselected => div(), + }; + + // A checkbox could be in an indeterminate state, + // for example the indeterminate state could represent: + // - a group of options of which only some are selected + // - an enabled option that is no longer available + // - a previously agreed to license that has been updated + // + // For the sake of styles we treat the indeterminate state as selected, + // but it's icon will be different. + let selected = + self.checked == Selected::Selected || self.checked == Selected::Indeterminate; + + // We could use something like this to make the checkbox background when selected: + // + // ~~~rust + // ... + // .when(selected, |this| { + // this.bg(cx.theme().colors().element_selected) + // }) + // ~~~ + // + // But we use a match instead here because the checkbox might be disabled, + // and it could be disabled _while_ it is selected, as well as while it is not selected. + let (bg_color, border_color) = match (self.disabled, selected) { + (true, _) => ( + cx.theme().colors().ghost_element_disabled, + cx.theme().colors().border_disabled, + ), + (false, true) => ( + cx.theme().colors().element_selected, + cx.theme().colors().border, + ), + (false, false) => (cx.theme().colors().element, cx.theme().colors().border), + }; + + div() + // Rather than adding `px_1()` to add some space around the checkbox, + // we use a larger parent element to create a slightly larger + // click area for the checkbox. + .size_5() + // Because we've enlarged the click area, we need to create a + // `group` to pass down interaction events to the checkbox. + .group(group_id.clone()) + .child( + div() + .flex() + // This prevent the flex element from growing + // or shrinking in response to any size changes + .flex_none() + // The combo of `justify_center()` and `items_center()` + // is used frequently to center elements in a flex container. + // + // We use this to center the icon in the checkbox. + .justify_center() + .items_center() + .m_1() + .size_4() + .rounded_sm() + .bg(bg_color) + .border() + .border_color(border_color) + // We only want the interaction states to fire when we + // are in a checkbox that isn't disabled. + .when(!self.disabled, |this| { + // Here instead of `hover()` we use `group_hover()` + // to pass it the group id. + this.group_hover(group_id.clone(), |el| { + el.bg(cx.theme().colors().element_hover) + }) + }) + .child(icon), + ) + } +} + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use super::*; + use crate::{h_stack, Story}; + use gpui2::{Div, Render}; + + pub struct CheckboxStory; + + impl Render for CheckboxStory { + type Element = Div; + + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + Story::container(cx) + .child(Story::title_for::<_, Checkbox>(cx)) + .child(Story::label(cx, "Default")) + .child( + h_stack() + .p_2() + .gap_2() + .rounded_md() + .border() + .border_color(cx.theme().colors().border) + .child(Checkbox::new("checkbox-enabled")) + .child(Checkbox::new("checkbox-intermediate").set_indeterminate()) + .child(Checkbox::new("checkbox-selected").toggle()), + ) + .child(Story::label(cx, "Disabled")) + .child( + h_stack() + .p_2() + .gap_2() + .rounded_md() + .border() + .border_color(cx.theme().colors().border) + .child(Checkbox::new("checkbox-disabled").set_disabled(true)) + .child( + Checkbox::new("checkbox-disabled-intermediate") + .set_disabled(true) + .set_indeterminate(), + ) + .child( + Checkbox::new("checkbox-disabled-selected") + .set_disabled(true) + .toggle(), + ), + ) + } + } +} diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index 5885d76101f18ce332e418423afb0f2d1f3d0da8..8075352b303dbea0a14f6764f60338138116a83f 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -22,6 +22,7 @@ pub enum IconColor { Warning, Success, Info, + Selected, } impl IconColor { @@ -36,6 +37,7 @@ impl IconColor { IconColor::Warning => cx.theme().status().warning, IconColor::Success => cx.theme().status().success, IconColor::Info => cx.theme().status().info, + IconColor::Selected => cx.theme().colors().icon_accent, } } } @@ -55,6 +57,7 @@ pub enum Icon { ChevronRight, ChevronUp, Close, + Dash, Exit, ExclamationTriangle, File, @@ -112,6 +115,7 @@ impl Icon { Icon::ChevronRight => "icons/chevron_right.svg", Icon::ChevronUp => "icons/chevron_up.svg", Icon::Close => "icons/x.svg", + Icon::Dash => "icons/dash.svg", Icon::Exit => "icons/exit.svg", Icon::ExclamationTriangle => "icons/warning.svg", Icon::File => "icons/file.svg", diff --git a/crates/ui2/src/prelude.rs b/crates/ui2/src/prelude.rs index 8ba74cce95cdf59c79d2d323ffe25e9abb22dfff..072ed0006052c402b58b422e918442829f7d8b88 100644 --- a/crates/ui2/src/prelude.rs +++ b/crates/ui2/src/prelude.rs @@ -154,10 +154,10 @@ impl InteractionState { } } -#[derive(Default, PartialEq)] -pub enum SelectedState { +#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)] +pub enum Selected { #[default] Unselected, - PartiallySelected, + Indeterminate, Selected, } From 660c3371e4fbaceb2d9916b4e988a75999bc8763 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 5 Nov 2023 14:43:54 +0200 Subject: [PATCH 15/23] Refresh all possibly stale diagnostics pat --- crates/diagnostics/src/diagnostics.rs | 134 ++++++++++++++++---------- 1 file changed, 81 insertions(+), 53 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index a3d779531b5690be0dc60808085bc099768df6bd..dc3dc0e061dd1beb4c9927a0ecdd753a8a4b3c7d 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -3,7 +3,7 @@ mod project_diagnostics_settings; mod toolbar_controls; use anyhow::Result; -use collections::{BTreeSet, HashSet}; +use collections::{BTreeSet, HashMap, HashSet}; use editor::{ diagnostic_block_renderer, display_map::{BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock}, @@ -13,7 +13,7 @@ use editor::{ }; use gpui::{ actions, elements::*, fonts::TextStyle, serde_json, AnyViewHandle, AppContext, Entity, - ModelHandle, Task, View, ViewContext, ViewHandle, WeakViewHandle, + ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use language::{ Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, @@ -28,6 +28,7 @@ use std::{ any::{Any, TypeId}, borrow::Cow, cmp::Ordering, + mem, ops::Range, path::PathBuf, sync::Arc, @@ -61,7 +62,9 @@ struct ProjectDiagnosticsEditor { excerpts: ModelHandle, path_states: Vec, paths_to_update: BTreeSet<(ProjectPath, LanguageServerId)>, + current_diagnostics: HashMap>, include_warnings: bool, + _subscriptions: Vec, } struct PathState { @@ -149,25 +152,22 @@ impl ProjectDiagnosticsEditor { workspace: WeakViewHandle, cx: &mut ViewContext, ) -> Self { - cx.subscribe(&project_handle, |this, _, event, cx| match event { - project::Event::DiskBasedDiagnosticsFinished { language_server_id } => { - log::debug!("Disk based diagnostics finished for server {language_server_id}"); - this.update_excerpts(Some(*language_server_id), cx); - this.update_title(cx); - } - project::Event::DiagnosticsUpdated { - language_server_id, - path, - } => { - log::debug!("Adding path {path:?} to update for server {language_server_id}"); - this.paths_to_update - .insert((path.clone(), *language_server_id)); - this.update_excerpts(Some(*language_server_id), cx); - this.update_title(cx); - } - _ => {} - }) - .detach(); + let project_event_subscription = + cx.subscribe(&project_handle, |this, _, event, cx| match event { + project::Event::DiskBasedDiagnosticsFinished { language_server_id } => { + log::debug!("Disk based diagnostics finished for server {language_server_id}"); + this.update_excerpts(Some(*language_server_id), cx); + } + project::Event::DiagnosticsUpdated { + language_server_id, + path, + } => { + log::debug!("Adding path {path:?} to update for server {language_server_id}"); + this.paths_to_update + .insert((path.clone(), *language_server_id)); + } + _ => {} + }); let excerpts = cx.add_model(|cx| MultiBuffer::new(project_handle.read(cx).replica_id())); let editor = cx.add_view(|cx| { @@ -176,19 +176,14 @@ impl ProjectDiagnosticsEditor { editor.set_vertical_scroll_margin(5, cx); editor }); - cx.subscribe(&editor, |this, _, event, cx| { + let editor_event_subscription = cx.subscribe(&editor, |this, _, event, cx| { cx.emit(event.clone()); if event == &editor::Event::Focused && this.path_states.is_empty() { cx.focus_self() } - }) - .detach(); + }); let project = project_handle.read(cx); - let paths_to_update = project - .diagnostic_summaries(cx) - .map(|(path, server_id, _)| (path, server_id)) - .collect(); let summary = project.diagnostic_summary(cx); let mut this = Self { project: project_handle, @@ -197,8 +192,10 @@ impl ProjectDiagnosticsEditor { excerpts, editor, path_states: Default::default(), - paths_to_update, + paths_to_update: BTreeSet::new(), include_warnings: settings::get::(cx).include_warnings, + current_diagnostics: HashMap::default(), + _subscriptions: vec![project_event_subscription, editor_event_subscription], }; this.update_excerpts(None, cx); this @@ -218,12 +215,6 @@ impl ProjectDiagnosticsEditor { fn toggle_warnings(&mut self, _: &ToggleWarnings, cx: &mut ViewContext) { self.include_warnings = !self.include_warnings; - self.paths_to_update = self - .project - .read(cx) - .diagnostic_summaries(cx) - .map(|(path, server_id, _)| (path, server_id)) - .collect(); self.update_excerpts(None, cx); cx.notify(); } @@ -234,29 +225,71 @@ impl ProjectDiagnosticsEditor { cx: &mut ViewContext, ) { log::debug!("Updating excerpts for server {language_server_id:?}"); - let mut paths = Vec::new(); - self.paths_to_update.retain(|(path, server_id)| { - if language_server_id - .map_or(true, |language_server_id| language_server_id == *server_id) - { - paths.push(path.clone()); - false - } else { - true + let mut paths_to_recheck = HashSet::default(); + let mut new_summaries: HashMap> = self + .project + .read(cx) + .diagnostic_summaries(cx) + .fold(HashMap::default(), |mut summaries, (path, server_id, _)| { + summaries.entry(server_id).or_default().insert(path); + summaries + }); + let mut old_diagnostics = + mem::replace(&mut self.current_diagnostics, new_summaries.clone()); + if let Some(language_server_id) = language_server_id { + new_summaries.retain(|server_id, _| server_id == &language_server_id); + old_diagnostics.retain(|server_id, _| server_id == &language_server_id); + self.paths_to_update.retain(|(path, server_id)| { + if server_id == &language_server_id { + paths_to_recheck.insert(path.clone()); + false + } else { + true + } + }); + } else { + paths_to_recheck.extend( + mem::replace(&mut self.paths_to_update, BTreeSet::new()) + .into_iter() + .map(|(path, _)| path), + ); + } + + for (server_id, new_paths) in new_summaries { + match old_diagnostics.remove(&server_id) { + Some(mut old_paths) => { + paths_to_recheck.extend( + new_paths + .into_iter() + .filter(|new_path| !old_paths.remove(new_path)), + ); + paths_to_recheck.extend(old_paths); + } + None => paths_to_recheck.extend(new_paths), } - }); + } + paths_to_recheck.extend(old_diagnostics.into_iter().flat_map(|(_, paths)| paths)); + let project = self.project.clone(); cx.spawn(|this, mut cx| { async move { - for path in paths { + let mut changed = false; + for path in paths_to_recheck { let buffer = project .update(&mut cx, |project, cx| project.open_buffer(path.clone(), cx)) .await?; this.update(&mut cx, |this, cx| { - this.populate_excerpts(path, language_server_id, buffer, cx) + this.populate_excerpts(path, language_server_id, buffer, cx); + changed = true; + })?; + } + if changed { + this.update(&mut cx, |this, cx| { + this.summary = this.project.read(cx).diagnostic_summary(cx); + cx.emit(Event::TitleChanged); })?; } - Result::<_, anyhow::Error>::Ok(()) + anyhow::Ok(()) } .log_err() }) @@ -559,11 +592,6 @@ impl ProjectDiagnosticsEditor { } cx.notify(); } - - fn update_title(&mut self, cx: &mut ViewContext) { - self.summary = self.project.read(cx).diagnostic_summary(cx); - cx.emit(Event::TitleChanged); - } } impl Item for ProjectDiagnosticsEditor { From 7145fabb6d3f727fd260eb33be0220d9cc848c63 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 5 Nov 2023 14:44:22 +0200 Subject: [PATCH 16/23] Eagerly refresh diagnostics that do not intercept with user input --- crates/diagnostics/src/diagnostics.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index dc3dc0e061dd1beb4c9927a0ecdd753a8a4b3c7d..4f66513f0f92d8b06b1f90aa6f5000b076fa5d35 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -165,6 +165,12 @@ impl ProjectDiagnosticsEditor { log::debug!("Adding path {path:?} to update for server {language_server_id}"); this.paths_to_update .insert((path.clone(), *language_server_id)); + let no_multiselections = this.editor.update(cx, |editor, cx| { + editor.selections.all::(cx).len() <= 1 + }); + if no_multiselections && !this.is_dirty(cx) { + this.update_excerpts(Some(*language_server_id), cx); + } } _ => {} }); From ff1d692e4602df3e0459330e793e6ee744a0c544 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 5 Nov 2023 14:53:13 +0200 Subject: [PATCH 17/23] Restructure inner path data --- crates/diagnostics/src/diagnostics.rs | 29 ++++++++++++++------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 4f66513f0f92d8b06b1f90aa6f5000b076fa5d35..a3d4bc958980603808099a21ca4379f782981575 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -3,7 +3,7 @@ mod project_diagnostics_settings; mod toolbar_controls; use anyhow::Result; -use collections::{BTreeSet, HashMap, HashSet}; +use collections::{HashMap, HashSet}; use editor::{ diagnostic_block_renderer, display_map::{BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock}, @@ -61,7 +61,7 @@ struct ProjectDiagnosticsEditor { summary: DiagnosticSummary, excerpts: ModelHandle, path_states: Vec, - paths_to_update: BTreeSet<(ProjectPath, LanguageServerId)>, + paths_to_update: HashMap>, current_diagnostics: HashMap>, include_warnings: bool, _subscriptions: Vec, @@ -128,9 +128,12 @@ impl View for ProjectDiagnosticsEditor { "summary": project.diagnostic_summary(cx), }), "summary": self.summary, - "paths_to_update": self.paths_to_update.iter().map(|(path, server_id)| - (path.path.to_string_lossy(), server_id.0) - ).collect::>(), + "paths_to_update": self.paths_to_update.iter().map(|(server_id, paths)| + (server_id.0, paths.into_iter().map(|path| path.path.to_string_lossy()).collect::>()) + ).collect::>(), + "current_diagnostics": self.current_diagnostics.iter().map(|(server_id, paths)| + (server_id.0, paths.into_iter().map(|path| path.path.to_string_lossy()).collect::>()) + ).collect::>(), "paths_states": self.path_states.iter().map(|state| json!({ "path": state.path.path.to_string_lossy(), @@ -164,7 +167,9 @@ impl ProjectDiagnosticsEditor { } => { log::debug!("Adding path {path:?} to update for server {language_server_id}"); this.paths_to_update - .insert((path.clone(), *language_server_id)); + .entry(*language_server_id) + .or_default() + .insert(path.clone()); let no_multiselections = this.editor.update(cx, |editor, cx| { editor.selections.all::(cx).len() <= 1 }); @@ -198,7 +203,7 @@ impl ProjectDiagnosticsEditor { excerpts, editor, path_states: Default::default(), - paths_to_update: BTreeSet::new(), + paths_to_update: HashMap::default(), include_warnings: settings::get::(cx).include_warnings, current_diagnostics: HashMap::default(), _subscriptions: vec![project_event_subscription, editor_event_subscription], @@ -245,20 +250,16 @@ impl ProjectDiagnosticsEditor { if let Some(language_server_id) = language_server_id { new_summaries.retain(|server_id, _| server_id == &language_server_id); old_diagnostics.retain(|server_id, _| server_id == &language_server_id); - self.paths_to_update.retain(|(path, server_id)| { + self.paths_to_update.retain(|server_id, paths| { if server_id == &language_server_id { - paths_to_recheck.insert(path.clone()); + paths_to_recheck.extend(paths.drain()); false } else { true } }); } else { - paths_to_recheck.extend( - mem::replace(&mut self.paths_to_update, BTreeSet::new()) - .into_iter() - .map(|(path, _)| path), - ); + paths_to_recheck.extend(self.paths_to_update.drain().flat_map(|(_, paths)| paths)); } for (server_id, new_paths) in new_summaries { From fdcb907644e598716c061c1c20edcab19ea79b51 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 5 Nov 2023 15:06:39 +0200 Subject: [PATCH 18/23] Parallelize diagnostics filling, add more logs --- Cargo.lock | 1 + crates/diagnostics/Cargo.toml | 1 + crates/diagnostics/src/diagnostics.rs | 50 ++++++++++++++++++--------- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e33edf29f0076a66e8c622558cfacdbb237c3b6c..b63c46ce987aba6ea2845747d92713c247cd72cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2459,6 +2459,7 @@ dependencies = [ "client", "collections", "editor", + "futures 0.3.28", "gpui", "language", "log", diff --git a/crates/diagnostics/Cargo.toml b/crates/diagnostics/Cargo.toml index 26a2a82999d2374e65ce5e061ee23ab91c366455..0f9d108831b76a370dd1af25d93a533a1dfa46f8 100644 --- a/crates/diagnostics/Cargo.toml +++ b/crates/diagnostics/Cargo.toml @@ -22,6 +22,7 @@ workspace = { path = "../workspace" } log.workspace = true anyhow.workspace = true +futures.workspace = true schemars.workspace = true serde.workspace = true serde_derive.workspace = true diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index a3d4bc958980603808099a21ca4379f782981575..dec26f12c43b3782012d7a49168604ae7aa9dbf1 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -2,7 +2,7 @@ pub mod items; mod project_diagnostics_settings; mod toolbar_controls; -use anyhow::Result; +use anyhow::{Context, Result}; use collections::{HashMap, HashSet}; use editor::{ diagnostic_block_renderer, @@ -11,6 +11,7 @@ use editor::{ scroll::autoscroll::Autoscroll, Editor, ExcerptId, ExcerptRange, MultiBuffer, ToOffset, }; +use futures::future::try_join_all; use gpui::{ actions, elements::*, fonts::TextStyle, serde_json, AnyViewHandle, AppContext, Entity, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, @@ -277,25 +278,40 @@ impl ProjectDiagnosticsEditor { } paths_to_recheck.extend(old_diagnostics.into_iter().flat_map(|(_, paths)| paths)); + if paths_to_recheck.is_empty() { + log::debug!("No paths to recheck for language server {language_server_id:?}"); + return; + } + + log::debug!( + "Rechecking {} paths for language server {:?}", + paths_to_recheck.len(), + language_server_id + ); let project = self.project.clone(); cx.spawn(|this, mut cx| { async move { - let mut changed = false; - for path in paths_to_recheck { - let buffer = project - .update(&mut cx, |project, cx| project.open_buffer(path.clone(), cx)) - .await?; - this.update(&mut cx, |this, cx| { - this.populate_excerpts(path, language_server_id, buffer, cx); - changed = true; - })?; - } - if changed { - this.update(&mut cx, |this, cx| { - this.summary = this.project.read(cx).diagnostic_summary(cx); - cx.emit(Event::TitleChanged); - })?; - } + let _ = try_join_all(paths_to_recheck.into_iter().map(|path| { + let mut cx = cx.clone(); + let project = project.clone(); + async move { + let buffer = project + .update(&mut cx, |project, cx| project.open_buffer(path.clone(), cx)) + .await + .with_context(|| format!("opening buffer for path {path:?}"))?; + this.update(&mut cx, |this, cx| { + this.populate_excerpts(path, language_server_id, buffer, cx); + }) + .context("missing project")?; + anyhow::Ok(()) + } + })) + .await?; + + this.update(&mut cx, |this, cx| { + this.summary = this.project.read(cx).diagnostic_summary(cx); + cx.emit(Event::TitleChanged); + })?; anyhow::Ok(()) } .log_err() From ad93d9132f03ad398018332f450c541142ba0a75 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 5 Nov 2023 15:37:11 +0200 Subject: [PATCH 19/23] Correctly update old diagnostics --- crates/diagnostics/src/diagnostics.rs | 29 ++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index dec26f12c43b3782012d7a49168604ae7aa9dbf1..1ec4105fbdaf9c02fbadea88c02263c953795371 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -246,11 +246,8 @@ impl ProjectDiagnosticsEditor { summaries.entry(server_id).or_default().insert(path); summaries }); - let mut old_diagnostics = - mem::replace(&mut self.current_diagnostics, new_summaries.clone()); - if let Some(language_server_id) = language_server_id { + let mut old_diagnostics = if let Some(language_server_id) = language_server_id { new_summaries.retain(|server_id, _| server_id == &language_server_id); - old_diagnostics.retain(|server_id, _| server_id == &language_server_id); self.paths_to_update.retain(|server_id, paths| { if server_id == &language_server_id { paths_to_recheck.extend(paths.drain()); @@ -259,10 +256,24 @@ impl ProjectDiagnosticsEditor { true } }); + let mut old_diagnostics = HashMap::default(); + if let Some(new_paths) = new_summaries.get(&language_server_id) { + if let Some(old_paths) = self + .current_diagnostics + .insert(language_server_id, new_paths.clone()) + { + old_diagnostics.insert(language_server_id, old_paths); + } + } else { + if let Some(old_paths) = self.current_diagnostics.remove(&language_server_id) { + old_diagnostics.insert(language_server_id, old_paths); + } + } + old_diagnostics } else { paths_to_recheck.extend(self.paths_to_update.drain().flat_map(|(_, paths)| paths)); - } - + mem::replace(&mut self.current_diagnostics, new_summaries.clone()) + }; for (server_id, new_paths) in new_summaries { match old_diagnostics.remove(&server_id) { Some(mut old_paths) => { @@ -282,7 +293,6 @@ impl ProjectDiagnosticsEditor { log::debug!("No paths to recheck for language server {language_server_id:?}"); return; } - log::debug!( "Rechecking {} paths for language server {:?}", paths_to_recheck.len(), @@ -291,7 +301,7 @@ impl ProjectDiagnosticsEditor { let project = self.project.clone(); cx.spawn(|this, mut cx| { async move { - let _ = try_join_all(paths_to_recheck.into_iter().map(|path| { + let _: Vec<()> = try_join_all(paths_to_recheck.into_iter().map(|path| { let mut cx = cx.clone(); let project = project.clone(); async move { @@ -306,7 +316,8 @@ impl ProjectDiagnosticsEditor { anyhow::Ok(()) } })) - .await?; + .await + .context("rechecking diagnostics for paths")?; this.update(&mut cx, |this, cx| { this.summary = this.project.read(cx).diagnostic_summary(cx); From 7374ca999bbb792d72f76c69b63979d92026afc3 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Sun, 5 Nov 2023 22:56:35 +0100 Subject: [PATCH 20/23] chore: Update vue.js parser (fixes wonky HTML parsing) Vue.js defined a bunch of symbols in it's scanner that collided with those defined in HTML Tree-sitter grammar. I simply removed them as they were meant for consumption by the external parties interested in HTML parser with Vue support - since we handle that ourselves this is not really necessary to preserve anymore. cc was firing up a bunch of warnings about unused symbols, so yeah. --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e33edf29f0076a66e8c622558cfacdbb237c3b6c..5c0b98c6e48ed5e74b797d68e07f1bc49fba1f81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9728,7 +9728,7 @@ dependencies = [ [[package]] name = "tree-sitter-vue" version = "0.0.1" -source = "git+https://github.com/zed-industries/tree-sitter-vue?rev=95b2890#95b28908d90e928c308866f7631e73ef6e1d4b5f" +source = "git+https://github.com/zed-industries/tree-sitter-vue?rev=9b6cb221ccb8d0b956fcb17e9a1efac2feefeb58#9b6cb221ccb8d0b956fcb17e9a1efac2feefeb58" dependencies = [ "cc", "tree-sitter", diff --git a/Cargo.toml b/Cargo.toml index 772773c977b4f56b5d6cf0ce3206ef5b31b26c16..6245889530bcefc9ea01a42efb49c1365859eb1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -176,7 +176,7 @@ tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", tree-sitter-lua = "0.0.14" tree-sitter-nix = { git = "https://github.com/nix-community/tree-sitter-nix", rev = "66e3e9ce9180ae08fc57372061006ef83f0abde7" } tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "786689b0562b9799ce53e824cb45a1a2a04dc673"} -tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", rev = "95b2890"} +tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", rev = "9b6cb221ccb8d0b956fcb17e9a1efac2feefeb58"} [patch.crates-io] tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "35a6052fbcafc5e5fc0f9415b8652be7dcaf7222" } async-task = { git = "https://github.com/zed-industries/async-task", rev = "341b57d6de98cdfd7b418567b8de2022ca993a6e" } From dbdb5f65190a3a2fd787c22a59ad5d77c8ef6ca3 Mon Sep 17 00:00:00 2001 From: Julia Date: Mon, 30 Oct 2023 13:31:21 -0400 Subject: [PATCH 21/23] Actually find downloaded binary in Elixir cached binary method --- crates/zed/src/languages/elixir.rs | 32 +++++++++++++----------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/crates/zed/src/languages/elixir.rs b/crates/zed/src/languages/elixir.rs index df438d89eef7b7c5c89a376670d7d270db4fa413..e2c79570bcbb444cc056712dfcc45c9ecbf4ea49 100644 --- a/crates/zed/src/languages/elixir.rs +++ b/crates/zed/src/languages/elixir.rs @@ -140,8 +140,8 @@ impl LspAdapter for ElixirLspAdapter { ) -> Result { let version = version.downcast::().unwrap(); let zip_path = container_dir.join(format!("elixir-ls_{}.zip", version.name)); - let version_dir = container_dir.join(format!("elixir-ls_{}", version.name)); - let binary_path = version_dir.join("language_server.sh"); + let folder_path = container_dir.join("elixir-ls"); + let binary_path = folder_path.join("language_server.sh"); if fs::metadata(&binary_path).await.is_err() { let mut response = delegate @@ -160,13 +160,13 @@ impl LspAdapter for ElixirLspAdapter { } futures::io::copy(response.body_mut(), &mut file).await?; - fs::create_dir_all(&version_dir) + fs::create_dir_all(&folder_path) .await - .with_context(|| format!("failed to create directory {}", version_dir.display()))?; + .with_context(|| format!("failed to create directory {}", folder_path.display()))?; let unzip_status = smol::process::Command::new("unzip") .arg(&zip_path) .arg("-d") - .arg(&version_dir) + .arg(&folder_path) .output() .await? .status; @@ -174,7 +174,7 @@ impl LspAdapter for ElixirLspAdapter { Err(anyhow!("failed to unzip elixir-ls archive"))?; } - remove_matching(&container_dir, |entry| entry != version_dir).await; + remove_matching(&container_dir, |entry| entry != folder_path).await; } Ok(LanguageServerBinary { @@ -285,20 +285,16 @@ impl LspAdapter for ElixirLspAdapter { async fn get_cached_server_binary_elixir_ls( container_dir: PathBuf, ) -> Option { - (|| async move { - let mut last = None; - let mut entries = fs::read_dir(&container_dir).await?; - while let Some(entry) = entries.next().await { - last = Some(entry?.path()); - } - last.map(|path| LanguageServerBinary { - path, + let server_path = container_dir.join("elixir-ls/language_server.sh"); + if server_path.exists() { + Some(LanguageServerBinary { + path: server_path, arguments: vec![], }) - .ok_or_else(|| anyhow!("no cached binary")) - })() - .await - .log_err() + } else { + log::error!("missing executable in directory {:?}", server_path); + None + } } pub struct NextLspAdapter; From 66b967532ff730ef778d9bc0a25fa82b465fa3f9 Mon Sep 17 00:00:00 2001 From: Julia Date: Mon, 6 Nov 2023 11:31:31 -0500 Subject: [PATCH 22/23] zed2: Actually find downloaded binary in Elixir cached binary method --- crates/zed2/src/languages/elixir.rs | 32 +++++++++++++---------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/crates/zed2/src/languages/elixir.rs b/crates/zed2/src/languages/elixir.rs index bd38377c99c17f9fc11e8a2f44044c5d44126c6f..90352c78b49874ab1f76ad73b17f2687baeee8f3 100644 --- a/crates/zed2/src/languages/elixir.rs +++ b/crates/zed2/src/languages/elixir.rs @@ -140,8 +140,8 @@ impl LspAdapter for ElixirLspAdapter { ) -> Result { let version = version.downcast::().unwrap(); let zip_path = container_dir.join(format!("elixir-ls_{}.zip", version.name)); - let version_dir = container_dir.join(format!("elixir-ls_{}", version.name)); - let binary_path = version_dir.join("language_server.sh"); + let folder_path = container_dir.join("elixir-ls"); + let binary_path = folder_path.join("language_server.sh"); if fs::metadata(&binary_path).await.is_err() { let mut response = delegate @@ -160,13 +160,13 @@ impl LspAdapter for ElixirLspAdapter { } futures::io::copy(response.body_mut(), &mut file).await?; - fs::create_dir_all(&version_dir) + fs::create_dir_all(&folder_path) .await - .with_context(|| format!("failed to create directory {}", version_dir.display()))?; + .with_context(|| format!("failed to create directory {}", folder_path.display()))?; let unzip_status = smol::process::Command::new("unzip") .arg(&zip_path) .arg("-d") - .arg(&version_dir) + .arg(&folder_path) .output() .await? .status; @@ -174,7 +174,7 @@ impl LspAdapter for ElixirLspAdapter { Err(anyhow!("failed to unzip elixir-ls archive"))?; } - remove_matching(&container_dir, |entry| entry != version_dir).await; + remove_matching(&container_dir, |entry| entry != folder_path).await; } Ok(LanguageServerBinary { @@ -285,20 +285,16 @@ impl LspAdapter for ElixirLspAdapter { async fn get_cached_server_binary_elixir_ls( container_dir: PathBuf, ) -> Option { - (|| async move { - let mut last = None; - let mut entries = fs::read_dir(&container_dir).await?; - while let Some(entry) = entries.next().await { - last = Some(entry?.path()); - } - last.map(|path| LanguageServerBinary { - path, + let server_path = container_dir.join("elixir-ls/language_server.sh"); + if server_path.exists() { + Some(LanguageServerBinary { + path: server_path, arguments: vec![], }) - .ok_or_else(|| anyhow!("no cached binary")) - })() - .await - .log_err() + } else { + log::error!("missing executable in directory {:?}", server_path); + None + } } pub struct NextLspAdapter; From bf80c1da5bb7405008f73596a270c539d0e41a94 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 6 Nov 2023 17:53:27 +0100 Subject: [PATCH 23/23] Rename fields in `ThemeColors` (#3242) This PR applies a number of field renames in the `ThemeColors` struct from the `import-theme` branch. This will help prevent this branch from diverging too far from `main`. Release Notes: - N/A --------- Co-authored-by: Nate Butler Co-authored-by: Marshall Bowers <1486634+maxdeviant@users.noreply.github.com> --- crates/theme2/src/colors.rs | 41 +++++++--- crates/theme2/src/default_colors.rs | 82 +++++++++++++------ crates/theme2/src/theme2.rs | 2 +- crates/theme2/src/themes/.gitkeep | 0 crates/ui2/src/components/button.rs | 4 +- crates/ui2/src/components/checkbox.rs | 5 +- crates/ui2/src/components/context_menu.rs | 2 +- crates/ui2/src/components/icon_button.rs | 4 +- crates/ui2/src/components/indicator.rs | 2 +- crates/ui2/src/components/input.rs | 4 +- crates/ui2/src/components/keybinding.rs | 2 +- crates/ui2/src/components/list.rs | 4 +- .../ui2/src/components/notification_toast.rs | 2 +- crates/ui2/src/components/palette.rs | 9 +- crates/ui2/src/components/panel.rs | 2 +- crates/ui2/src/components/tab.rs | 4 +- crates/ui2/src/components/toast.rs | 2 +- crates/ui2/src/to_extract/buffer.rs | 2 +- crates/ui2/src/to_extract/buffer_search.rs | 21 +++-- crates/ui2/src/to_extract/collab_panel.rs | 2 +- crates/ui2/src/to_extract/multi_buffer.rs | 2 +- .../ui2/src/to_extract/notifications_panel.rs | 4 +- crates/ui2/src/to_extract/panes.rs | 2 +- crates/ui2/src/to_extract/project_panel.rs | 2 +- crates/ui2/src/to_extract/status_bar.rs | 2 +- crates/ui2/src/to_extract/tab_bar.rs | 2 +- crates/ui2/src/to_extract/terminal.rs | 2 +- crates/ui2/src/to_extract/toolbar.rs | 2 +- crates/ui2/src/to_extract/traffic_lights.rs | 2 +- crates/workspace2/src/pane.rs | 6 +- crates/workspace2/src/status_bar.rs | 2 +- crates/workspace2/src/workspace2.rs | 2 +- 32 files changed, 144 insertions(+), 82 deletions(-) create mode 100644 crates/theme2/src/themes/.gitkeep diff --git a/crates/theme2/src/colors.rs b/crates/theme2/src/colors.rs index b9f8804205da9afb4dd8a9c348276c53063fbc30..1a1fd2e99ec5f568b06cec93cbdb86ea8ae91296 100644 --- a/crates/theme2/src/colors.rs +++ b/crates/theme2/src/colors.rs @@ -57,17 +57,17 @@ pub struct ThemeColors { pub border_selected: Hsla, pub border_transparent: Hsla, pub border_disabled: Hsla, - pub elevated_surface: Hsla, - pub surface: Hsla, + pub elevated_surface_background: Hsla, + pub surface_background: Hsla, pub background: Hsla, - pub element: Hsla, + pub element_background: Hsla, pub element_hover: Hsla, pub element_active: Hsla, pub element_selected: Hsla, pub element_disabled: Hsla, pub element_placeholder: Hsla, pub element_drop_target: Hsla, - pub ghost_element: Hsla, + pub ghost_element_background: Hsla, pub ghost_element_hover: Hsla, pub ghost_element_active: Hsla, pub ghost_element_selected: Hsla, @@ -82,15 +82,32 @@ pub struct ThemeColors { pub icon_disabled: Hsla, pub icon_placeholder: Hsla, pub icon_accent: Hsla, - pub status_bar: Hsla, - pub title_bar: Hsla, - pub toolbar: Hsla, - pub tab_bar: Hsla, - pub tab_inactive: Hsla, - pub tab_active: Hsla, - pub editor: Hsla, - pub editor_subheader: Hsla, + pub status_bar_background: Hsla, + pub title_bar_background: Hsla, + pub toolbar_background: Hsla, + pub tab_bar_background: Hsla, + pub tab_inactive_background: Hsla, + pub tab_active_background: Hsla, + pub editor_background: Hsla, + pub editor_subheader_background: Hsla, pub editor_active_line: Hsla, + pub terminal_background: Hsla, + pub terminal_ansi_bright_black: Hsla, + pub terminal_ansi_bright_red: Hsla, + pub terminal_ansi_bright_green: Hsla, + pub terminal_ansi_bright_yellow: Hsla, + pub terminal_ansi_bright_blue: Hsla, + pub terminal_ansi_bright_magenta: Hsla, + pub terminal_ansi_bright_cyan: Hsla, + pub terminal_ansi_bright_white: Hsla, + pub terminal_ansi_black: Hsla, + pub terminal_ansi_red: Hsla, + pub terminal_ansi_green: Hsla, + pub terminal_ansi_yellow: Hsla, + pub terminal_ansi_blue: Hsla, + pub terminal_ansi_magenta: Hsla, + pub terminal_ansi_cyan: Hsla, + pub terminal_ansi_white: Hsla, } #[derive(Refineable, Clone)] diff --git a/crates/theme2/src/default_colors.rs b/crates/theme2/src/default_colors.rs index 4ecae43b1559c223559dce98546310f0b5afc3aa..53e34acf1608003d20760ee750e6d449fbd11b43 100644 --- a/crates/theme2/src/default_colors.rs +++ b/crates/theme2/src/default_colors.rs @@ -208,17 +208,17 @@ impl ThemeColors { border_disabled: neutral().light().step_3(), border_selected: blue().light().step_5(), border_transparent: system.transparent, - elevated_surface: neutral().light().step_2(), - surface: neutral().light().step_2(), + elevated_surface_background: neutral().light().step_2(), + surface_background: neutral().light().step_2(), background: neutral().light().step_1(), - element: neutral().light().step_3(), + element_background: neutral().light().step_3(), element_hover: neutral().light().step_4(), element_active: neutral().light().step_5(), element_selected: neutral().light().step_5(), element_disabled: neutral().light_alpha().step_3(), element_placeholder: neutral().light().step_11(), element_drop_target: blue().light_alpha().step_2(), - ghost_element: system.transparent, + ghost_element_background: system.transparent, ghost_element_hover: neutral().light().step_4(), ghost_element_active: neutral().light().step_5(), ghost_element_selected: neutral().light().step_5(), @@ -233,15 +233,32 @@ impl ThemeColors { icon_disabled: neutral().light().step_9(), icon_placeholder: neutral().light().step_10(), icon_accent: blue().light().step_11(), - status_bar: neutral().light().step_2(), - title_bar: neutral().light().step_2(), - toolbar: neutral().light().step_1(), - tab_bar: neutral().light().step_2(), - tab_active: neutral().light().step_1(), - tab_inactive: neutral().light().step_2(), - editor: neutral().light().step_1(), - editor_subheader: neutral().light().step_2(), + status_bar_background: neutral().light().step_2(), + title_bar_background: neutral().light().step_2(), + toolbar_background: neutral().light().step_1(), + tab_bar_background: neutral().light().step_2(), + tab_active_background: neutral().light().step_1(), + tab_inactive_background: neutral().light().step_2(), + editor_background: neutral().light().step_1(), + editor_subheader_background: neutral().light().step_2(), editor_active_line: neutral().light_alpha().step_3(), + terminal_background: neutral().light().step_1(), + terminal_ansi_black: black().light().step_12(), + terminal_ansi_red: red().light().step_11(), + terminal_ansi_green: green().light().step_11(), + terminal_ansi_yellow: yellow().light().step_11(), + terminal_ansi_blue: blue().light().step_11(), + terminal_ansi_magenta: violet().light().step_11(), + terminal_ansi_cyan: cyan().light().step_11(), + terminal_ansi_white: neutral().light().step_12(), + terminal_ansi_bright_black: black().light().step_11(), + terminal_ansi_bright_red: red().light().step_10(), + terminal_ansi_bright_green: green().light().step_10(), + terminal_ansi_bright_yellow: yellow().light().step_10(), + terminal_ansi_bright_blue: blue().light().step_10(), + terminal_ansi_bright_magenta: violet().light().step_10(), + terminal_ansi_bright_cyan: cyan().light().step_10(), + terminal_ansi_bright_white: neutral().light().step_11(), } } @@ -255,17 +272,17 @@ impl ThemeColors { border_disabled: neutral().dark().step_3(), border_selected: blue().dark().step_5(), border_transparent: system.transparent, - elevated_surface: neutral().dark().step_2(), - surface: neutral().dark().step_2(), + elevated_surface_background: neutral().dark().step_2(), + surface_background: neutral().dark().step_2(), background: neutral().dark().step_1(), - element: neutral().dark().step_3(), + element_background: neutral().dark().step_3(), element_hover: neutral().dark().step_4(), element_active: neutral().dark().step_5(), element_selected: neutral().dark().step_5(), element_disabled: neutral().dark_alpha().step_3(), element_placeholder: neutral().dark().step_11(), element_drop_target: blue().dark_alpha().step_2(), - ghost_element: system.transparent, + ghost_element_background: system.transparent, ghost_element_hover: neutral().dark().step_4(), ghost_element_active: neutral().dark().step_5(), ghost_element_selected: neutral().dark().step_5(), @@ -280,15 +297,32 @@ impl ThemeColors { icon_disabled: neutral().dark().step_9(), icon_placeholder: neutral().dark().step_10(), icon_accent: blue().dark().step_11(), - status_bar: neutral().dark().step_2(), - title_bar: neutral().dark().step_2(), - toolbar: neutral().dark().step_1(), - tab_bar: neutral().dark().step_2(), - tab_active: neutral().dark().step_1(), - tab_inactive: neutral().dark().step_2(), - editor: neutral().dark().step_1(), - editor_subheader: neutral().dark().step_2(), + status_bar_background: neutral().dark().step_2(), + title_bar_background: neutral().dark().step_2(), + toolbar_background: neutral().dark().step_1(), + tab_bar_background: neutral().dark().step_2(), + tab_active_background: neutral().dark().step_1(), + tab_inactive_background: neutral().dark().step_2(), + editor_background: neutral().dark().step_1(), + editor_subheader_background: neutral().dark().step_2(), editor_active_line: neutral().dark_alpha().step_3(), + terminal_background: neutral().dark().step_1(), + terminal_ansi_black: black().dark().step_12(), + terminal_ansi_red: red().dark().step_11(), + terminal_ansi_green: green().dark().step_11(), + terminal_ansi_yellow: yellow().dark().step_11(), + terminal_ansi_blue: blue().dark().step_11(), + terminal_ansi_magenta: violet().dark().step_11(), + terminal_ansi_cyan: cyan().dark().step_11(), + terminal_ansi_white: neutral().dark().step_12(), + terminal_ansi_bright_black: black().dark().step_11(), + terminal_ansi_bright_red: red().dark().step_10(), + terminal_ansi_bright_green: green().dark().step_10(), + terminal_ansi_bright_yellow: yellow().dark().step_10(), + terminal_ansi_bright_blue: blue().dark().step_10(), + terminal_ansi_bright_magenta: violet().dark().step_10(), + terminal_ansi_bright_cyan: cyan().dark().step_10(), + terminal_ansi_bright_white: neutral().dark().step_11(), } } } diff --git a/crates/theme2/src/theme2.rs b/crates/theme2/src/theme2.rs index faf252e2e5d071b700d7f672cafa17a04e60f0cd..b8e22f8319a523e123c15915a5990fdf69ac6121 100644 --- a/crates/theme2/src/theme2.rs +++ b/crates/theme2/src/theme2.rs @@ -17,7 +17,7 @@ pub use syntax::*; use gpui::{AppContext, Hsla, SharedString}; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum Appearance { Light, Dark, diff --git a/crates/theme2/src/themes/.gitkeep b/crates/theme2/src/themes/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/crates/ui2/src/components/button.rs b/crates/ui2/src/components/button.rs index 381db20a8336ccf02694537f3760d5e10a23989a..c13460aadd92645b449c53f4d15c4c225b7d3083 100644 --- a/crates/ui2/src/components/button.rs +++ b/crates/ui2/src/components/button.rs @@ -41,8 +41,8 @@ pub enum ButtonVariant { impl ButtonVariant { pub fn bg_color(&self, cx: &mut WindowContext) -> Hsla { match self { - ButtonVariant::Ghost => cx.theme().colors().ghost_element, - ButtonVariant::Filled => cx.theme().colors().element, + ButtonVariant::Ghost => cx.theme().colors().ghost_element_background, + ButtonVariant::Filled => cx.theme().colors().element_background, } } diff --git a/crates/ui2/src/components/checkbox.rs b/crates/ui2/src/components/checkbox.rs index 3add6cebaccc07847310ce1445dc6ecf0a6f635b..4b6a6240bbe057ba59ee47460d1a00888f42e9be 100644 --- a/crates/ui2/src/components/checkbox.rs +++ b/crates/ui2/src/components/checkbox.rs @@ -120,7 +120,10 @@ impl Checkbox { cx.theme().colors().element_selected, cx.theme().colors().border, ), - (false, false) => (cx.theme().colors().element, cx.theme().colors().border), + (false, false) => ( + cx.theme().colors().element_background, + cx.theme().colors().border, + ), }; div() diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 4f265a376dec5847e89be537064a843515607341..87be445c1990c486345d96263976080b1d96b157 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -46,7 +46,7 @@ impl ContextMenu { fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { v_stack() .flex() - .bg(cx.theme().colors().elevated_surface) + .bg(cx.theme().colors().elevated_surface_background) .border() .border_color(cx.theme().colors().border) .child(List::new( diff --git a/crates/ui2/src/components/icon_button.rs b/crates/ui2/src/components/icon_button.rs index 101c845a76ed490e051bb02416c1f4bd05b4c1a5..8fe1a1fa9bc37d08002ed07e07bb167e05a2bd2e 100644 --- a/crates/ui2/src/components/icon_button.rs +++ b/crates/ui2/src/components/icon_button.rs @@ -73,12 +73,12 @@ impl IconButton { let (bg_color, bg_hover_color, bg_active_color) = match self.variant { ButtonVariant::Filled => ( - cx.theme().colors().element, + cx.theme().colors().element_background, cx.theme().colors().element_hover, cx.theme().colors().element_active, ), ButtonVariant::Ghost => ( - cx.theme().colors().ghost_element, + cx.theme().colors().ghost_element_background, cx.theme().colors().ghost_element_hover, cx.theme().colors().ghost_element_active, ), diff --git a/crates/ui2/src/components/indicator.rs b/crates/ui2/src/components/indicator.rs index 1f6e00e621ad02132f85540db985a1a2abd40c31..94398ab7f6016640d55e20a69d8e6939ca75c51a 100644 --- a/crates/ui2/src/components/indicator.rs +++ b/crates/ui2/src/components/indicator.rs @@ -14,7 +14,7 @@ impl UnreadIndicator { div() .rounded_full() .border_2() - .border_color(cx.theme().colors().surface) + .border_color(cx.theme().colors().surface_background) .w(px(9.0)) .h(px(9.0)) .z_index(2) diff --git a/crates/ui2/src/components/input.rs b/crates/ui2/src/components/input.rs index 2884470ce21193085e165cc1b0b92fb710c585a0..f288f3ca563d861bfb9b17e38d9ea7b9a2bea40a 100644 --- a/crates/ui2/src/components/input.rs +++ b/crates/ui2/src/components/input.rs @@ -59,12 +59,12 @@ impl Input { fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { let (input_bg, input_hover_bg, input_active_bg) = match self.variant { InputVariant::Ghost => ( - cx.theme().colors().ghost_element, + cx.theme().colors().ghost_element_background, cx.theme().colors().ghost_element_hover, cx.theme().colors().ghost_element_active, ), InputVariant::Filled => ( - cx.theme().colors().element, + cx.theme().colors().element_background, cx.theme().colors().element_hover, cx.theme().colors().element_active, ), diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index 88cabbdc88bbd45fffb34d14682a3e8d546a68bc..8b8fba8c08d2da0ab097a82adc0a852925f1c30f 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -66,7 +66,7 @@ impl Key { .rounded_md() .text_sm() .text_color(cx.theme().colors().text) - .bg(cx.theme().colors().element) + .bg(cx.theme().colors().element_background) .child(self.key.clone()) } } diff --git a/crates/ui2/src/components/list.rs b/crates/ui2/src/components/list.rs index 543432a8935a5392e96e5e1a8ca074adf5388d54..b30beacd9837af2bf6fa83e5810425cde600c010 100644 --- a/crates/ui2/src/components/list.rs +++ b/crates/ui2/src/components/list.rs @@ -79,7 +79,7 @@ impl ListHeader { h_stack() .w_full() - .bg(cx.theme().colors().surface) + .bg(cx.theme().colors().surface_background) // TODO: Add focus state // .when(self.state == InteractionState::Focused, |this| { // this.border() @@ -307,7 +307,7 @@ impl ListEntry { div() .relative() .group("") - .bg(cx.theme().colors().surface) + .bg(cx.theme().colors().surface_background) // TODO: Add focus state .child( sized_item diff --git a/crates/ui2/src/components/notification_toast.rs b/crates/ui2/src/components/notification_toast.rs index 59078c98f43d2a079c5de75b428eae1073c8803e..e8739b925c7e03c2a4fb2eb77cf005ea72ec665e 100644 --- a/crates/ui2/src/components/notification_toast.rs +++ b/crates/ui2/src/components/notification_toast.rs @@ -34,7 +34,7 @@ impl NotificationToast { .px_1p5() .rounded_lg() .shadow_md() - .bg(cx.theme().colors().elevated_surface) + .bg(cx.theme().colors().elevated_surface_background) .child(div().size_full().child(self.label.clone())) } } diff --git a/crates/ui2/src/components/palette.rs b/crates/ui2/src/components/palette.rs index a1f3eb7e1c4a9f044ac6a4b810643a044fc578b4..269b39d86d5bc4fbbfa34fa20f9418a335b47641 100644 --- a/crates/ui2/src/components/palette.rs +++ b/crates/ui2/src/components/palette.rs @@ -47,7 +47,7 @@ impl Palette { .id(self.id.clone()) .w_96() .rounded_lg() - .bg(cx.theme().colors().elevated_surface) + .bg(cx.theme().colors().elevated_surface_background) .border() .border_color(cx.theme().colors().border) .child( @@ -56,7 +56,12 @@ impl Palette { .child(v_stack().py_0p5().px_1().child(div().px_2().py_0p5().child( Label::new(self.input_placeholder.clone()).color(LabelColor::Placeholder), ))) - .child(div().h_px().w_full().bg(cx.theme().colors().element)) + .child( + div() + .h_px() + .w_full() + .bg(cx.theme().colors().element_background), + ) .child( v_stack() .id("items") diff --git a/crates/ui2/src/components/panel.rs b/crates/ui2/src/components/panel.rs index 5d941eb50ea3e7c8084b73c7792a2b6dcd0c378a..ba88abb337259e2e56d1b9b5e1eabb169fc0827c 100644 --- a/crates/ui2/src/components/panel.rs +++ b/crates/ui2/src/components/panel.rs @@ -107,7 +107,7 @@ impl Panel { PanelSide::Right => this.border_l(), PanelSide::Bottom => this.border_b().w_full().h(current_size), }) - .bg(cx.theme().colors().surface) + .bg(cx.theme().colors().surface_background) .border_color(cx.theme().colors().border) .children(self.children) } diff --git a/crates/ui2/src/components/tab.rs b/crates/ui2/src/components/tab.rs index e8b0ee3be59b19fd8307f3485971b2fafb2a89f4..47de0541f1d6287a0e800c298e45c76486c3ef57 100644 --- a/crates/ui2/src/components/tab.rs +++ b/crates/ui2/src/components/tab.rs @@ -109,12 +109,12 @@ impl Tab { let (tab_bg, tab_hover_bg, tab_active_bg) = match self.current { false => ( - cx.theme().colors().tab_inactive, + cx.theme().colors().tab_inactive_background, cx.theme().colors().ghost_element_hover, cx.theme().colors().ghost_element_active, ), true => ( - cx.theme().colors().tab_active, + cx.theme().colors().tab_active_background, cx.theme().colors().element_hover, cx.theme().colors().element_active, ), diff --git a/crates/ui2/src/components/toast.rs b/crates/ui2/src/components/toast.rs index 3b81ac42b44abf45fac20337b8f1392d9d529941..4ab6625dbaed89311a78227610b27434f91f7925 100644 --- a/crates/ui2/src/components/toast.rs +++ b/crates/ui2/src/components/toast.rs @@ -54,7 +54,7 @@ impl Toast { .rounded_lg() .shadow_md() .overflow_hidden() - .bg(cx.theme().colors().elevated_surface) + .bg(cx.theme().colors().elevated_surface_background) .children(self.children) } } diff --git a/crates/ui2/src/to_extract/buffer.rs b/crates/ui2/src/to_extract/buffer.rs index 2b3db676ce795dac12a930f1ad48b8c3724751af..e12beff2fce5e8c8d081c44e832c3a19465e7b3f 100644 --- a/crates/ui2/src/to_extract/buffer.rs +++ b/crates/ui2/src/to_extract/buffer.rs @@ -220,7 +220,7 @@ impl Buffer { .flex_1() .w_full() .h_full() - .bg(cx.theme().colors().editor) + .bg(cx.theme().colors().editor_background) .children(rows) } } diff --git a/crates/ui2/src/to_extract/buffer_search.rs b/crates/ui2/src/to_extract/buffer_search.rs index 5d7de1b408a90159269fc7edc11d634a62c607d8..02f689ca3e009bca7dbedc6fc015b185321e8f90 100644 --- a/crates/ui2/src/to_extract/buffer_search.rs +++ b/crates/ui2/src/to_extract/buffer_search.rs @@ -30,14 +30,17 @@ impl Render for BufferSearch { type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Div { - h_stack().bg(cx.theme().colors().toolbar).p_2().child( - h_stack().child(Input::new("Search")).child( - IconButton::::new("replace", Icon::Replace) - .when(self.is_replace_open, |this| this.color(IconColor::Accent)) - .on_click(|buffer_search, cx| { - buffer_search.toggle_replace(cx); - }), - ), - ) + h_stack() + .bg(cx.theme().colors().toolbar_background) + .p_2() + .child( + h_stack().child(Input::new("Search")).child( + IconButton::::new("replace", Icon::Replace) + .when(self.is_replace_open, |this| this.color(IconColor::Accent)) + .on_click(|buffer_search, cx| { + buffer_search.toggle_replace(cx); + }), + ), + ) } } diff --git a/crates/ui2/src/to_extract/collab_panel.rs b/crates/ui2/src/to_extract/collab_panel.rs index 9019456dd131800efecbd68ac1d8bcabae704090..9d9dc861e2a1c2ce073040334e6ccaaf5ab2562e 100644 --- a/crates/ui2/src/to_extract/collab_panel.rs +++ b/crates/ui2/src/to_extract/collab_panel.rs @@ -17,7 +17,7 @@ impl CollabPanel { v_stack() .id(self.id.clone()) .h_full() - .bg(cx.theme().colors().surface) + .bg(cx.theme().colors().surface_background) .child( v_stack() .id("crdb") diff --git a/crates/ui2/src/to_extract/multi_buffer.rs b/crates/ui2/src/to_extract/multi_buffer.rs index ea130f20bd447a2e31ea3f6e04e3e2ff08470dae..1334703015b1373255ba5113bcce143ee790413b 100644 --- a/crates/ui2/src/to_extract/multi_buffer.rs +++ b/crates/ui2/src/to_extract/multi_buffer.rs @@ -24,7 +24,7 @@ impl MultiBuffer { .items_center() .justify_between() .p_4() - .bg(cx.theme().colors().editor_subheader) + .bg(cx.theme().colors().editor_subheader_background) .child(Label::new("main.rs")) .child(IconButton::new("arrow_up_right", Icon::ArrowUpRight)), ) diff --git a/crates/ui2/src/to_extract/notifications_panel.rs b/crates/ui2/src/to_extract/notifications_panel.rs index 789aa2b0aa11d5f2dded289e1d99ddc433cfae2f..84794b71b21993cf1c41e9e15d8d388c39d5a140 100644 --- a/crates/ui2/src/to_extract/notifications_panel.rs +++ b/crates/ui2/src/to_extract/notifications_panel.rs @@ -22,7 +22,7 @@ impl NotificationsPanel { .flex() .flex_col() .size_full() - .bg(cx.theme().colors().surface) + .bg(cx.theme().colors().surface_background) .child( ListHeader::new("Notifications").meta(Some(ListHeaderMeta::Tools(vec![ Icon::AtSign, @@ -43,7 +43,7 @@ impl NotificationsPanel { .p_1() // TODO: Add cursor style // .cursor(Cursor::IBeam) - .bg(cx.theme().colors().element) + .bg(cx.theme().colors().element_background) .border() .border_color(cx.theme().colors().border_variant) .child( diff --git a/crates/ui2/src/to_extract/panes.rs b/crates/ui2/src/to_extract/panes.rs index bf0f27d43f32742abfe61c527c67dd6d8fd0f96a..a1e040b0cad9a5365548feb150f1084f4fa3404e 100644 --- a/crates/ui2/src/to_extract/panes.rs +++ b/crates/ui2/src/to_extract/panes.rs @@ -113,7 +113,7 @@ impl PaneGroup { .gap_px() .w_full() .h_full() - .bg(cx.theme().colors().editor) + .bg(cx.theme().colors().editor_background) .children(self.groups.into_iter().map(|group| group.render(view, cx))); if self.split_direction == SplitDirection::Horizontal { diff --git a/crates/ui2/src/to_extract/project_panel.rs b/crates/ui2/src/to_extract/project_panel.rs index 807768427b21729f1b1bfd6f3cc107cddb67423d..a34a30bcbcf0ae71a19caff2884039933d1bcce4 100644 --- a/crates/ui2/src/to_extract/project_panel.rs +++ b/crates/ui2/src/to_extract/project_panel.rs @@ -19,7 +19,7 @@ impl ProjectPanel { .flex() .flex_col() .size_full() - .bg(cx.theme().colors().surface) + .bg(cx.theme().colors().surface_background) .child( div() .id("project-panel-contents") diff --git a/crates/ui2/src/to_extract/status_bar.rs b/crates/ui2/src/to_extract/status_bar.rs index 136472f605abc71600137ef567e43d45c8129e45..34a5993e69da552d9045a7ab23c5fa30d3d218e3 100644 --- a/crates/ui2/src/to_extract/status_bar.rs +++ b/crates/ui2/src/to_extract/status_bar.rs @@ -93,7 +93,7 @@ impl StatusBar { .items_center() .justify_between() .w_full() - .bg(cx.theme().colors().status_bar) + .bg(cx.theme().colors().status_bar_background) .child(self.left_tools(view, cx)) .child(self.right_tools(view, cx)) } diff --git a/crates/ui2/src/to_extract/tab_bar.rs b/crates/ui2/src/to_extract/tab_bar.rs index bb7fca11534dbcb5981a0d695ffb3962ebe67e6c..a1280441832f1a6a8caee0c1a63ec989d021ad37 100644 --- a/crates/ui2/src/to_extract/tab_bar.rs +++ b/crates/ui2/src/to_extract/tab_bar.rs @@ -31,7 +31,7 @@ impl TabBar { .id(self.id.clone()) .w_full() .flex() - .bg(cx.theme().colors().tab_bar) + .bg(cx.theme().colors().tab_bar_background) // Left Side .child( div() diff --git a/crates/ui2/src/to_extract/terminal.rs b/crates/ui2/src/to_extract/terminal.rs index 051ebf7315400298f6b22eb8ae5adb108a7098fe..b912a5960768e3b17a11988560a0201ac6ee2902 100644 --- a/crates/ui2/src/to_extract/terminal.rs +++ b/crates/ui2/src/to_extract/terminal.rs @@ -24,7 +24,7 @@ impl Terminal { div() .w_full() .flex() - .bg(cx.theme().colors().surface) + .bg(cx.theme().colors().surface_background) .child( div().px_1().flex().flex_none().gap_2().child( div() diff --git a/crates/ui2/src/to_extract/toolbar.rs b/crates/ui2/src/to_extract/toolbar.rs index 05a5c991d69d645602f2966f270124efcb5209bd..0e3e7c259ff971622feb5b89fbeddc3bf5023a2f 100644 --- a/crates/ui2/src/to_extract/toolbar.rs +++ b/crates/ui2/src/to_extract/toolbar.rs @@ -56,7 +56,7 @@ impl Toolbar { fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { div() - .bg(cx.theme().colors().toolbar) + .bg(cx.theme().colors().toolbar_background) .p_2() .flex() .justify_between() diff --git a/crates/ui2/src/to_extract/traffic_lights.rs b/crates/ui2/src/to_extract/traffic_lights.rs index 9080276cdd281888813f06c34fee8a256e540aa8..677fae886c838c03cc42ed300ce9df4f79d1d883 100644 --- a/crates/ui2/src/to_extract/traffic_lights.rs +++ b/crates/ui2/src/to_extract/traffic_lights.rs @@ -28,7 +28,7 @@ impl TrafficLight { (true, TrafficLightColor::Red) => system_colors.mac_os_traffic_light_red, (true, TrafficLightColor::Yellow) => system_colors.mac_os_traffic_light_yellow, (true, TrafficLightColor::Green) => system_colors.mac_os_traffic_light_green, - (false, _) => cx.theme().colors().element, + (false, _) => cx.theme().colors().element_background, }; div().w_3().h_3().rounded_full().bg(fill) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index acc41deba880ed986e1391d6fb61d4818ffeef5a..44f705ebb2a734f03e238312df08be54d7bd7368 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1363,12 +1363,12 @@ impl Pane { let (tab_bg, tab_hover_bg, tab_active_bg) = match ix == self.active_item_index { false => ( - cx.theme().colors().tab_inactive, + cx.theme().colors().tab_inactive_background, cx.theme().colors().ghost_element_hover, cx.theme().colors().ghost_element_active, ), true => ( - cx.theme().colors().tab_active, + cx.theme().colors().tab_active_background, cx.theme().colors().element_hover, cx.theme().colors().element_active, ), @@ -1432,7 +1432,7 @@ impl Pane { .id("tab_bar") .w_full() .flex() - .bg(cx.theme().colors().tab_bar) + .bg(cx.theme().colors().tab_bar_background) // Left Side .child( div() diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index ca4ebcdb1305bf72b6d04d1409d4c80358ecbab0..ac99be9f892c84c1226d5fbfec70e1a3afa79ea2 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -44,7 +44,7 @@ impl Render for StatusBar { .items_center() .justify_between() .w_full() - .bg(cx.theme().colors().status_bar) + .bg(cx.theme().colors().status_bar_background) .child(self.render_left_tools(cx)) .child(self.render_right_tools(cx)) } diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 6e4c9e6cfd8d5148f5ccc37d42a7d4369b643524..7561c903d3bf05c5664632015c80350a8f897626 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -2697,7 +2697,7 @@ impl Workspace { fn render_titlebar(&self, cx: &mut ViewContext) -> impl Component { div() - .bg(cx.theme().colors().title_bar) + .bg(cx.theme().colors().title_bar_background) .when( !matches!(cx.window_bounds(), WindowBounds::Fullscreen), |s| s.pl_20(),