From 4aabab3e4ee00ea0fe775c94bd3df236f7911359 Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Wed, 11 Mar 2026 16:30:21 +0700 Subject: [PATCH] wip: refactor tabs --- assets/themes/catppuccin-frappe.json | 2 - assets/themes/catppuccin-latte.json | 2 - assets/themes/catppuccin-macchiato.json | 2 - assets/themes/catppuccin-mocha.json | 2 - assets/themes/flexoki.json | 2 - assets/themes/rose-pine-dawn.json | 2 - assets/themes/rose-pine-moon.json | 2 - assets/themes/rose-pine.json | 2 - crates/chat_ui/src/lib.rs | 2 +- crates/coop/src/panels/backup.rs | 8 +- crates/coop/src/panels/contact_list.rs | 2 +- crates/coop/src/panels/greeter.rs | 3 +- crates/coop/src/panels/messaging_relays.rs | 2 +- crates/coop/src/panels/profile.rs | 2 +- crates/coop/src/panels/relay_list.rs | 14 +-- crates/coop/src/sidebar/entry.rs | 8 +- crates/coop/src/sidebar/mod.rs | 2 +- crates/coop/src/workspace.rs | 8 +- crates/theme/src/colors.rs | 19 ++--- crates/theme/src/lib.rs | 2 +- crates/ui/src/{dock_area => dock}/dock.rs | 18 ++-- crates/ui/src/{dock_area => dock}/mod.rs | 24 +++--- crates/ui/src/{dock_area => dock}/panel.rs | 8 +- .../ui/src/{dock_area => dock}/stack_panel.rs | 4 +- .../ui/src/{dock_area => dock}/tab_panel.rs | 44 +++++----- crates/ui/src/lib.rs | 2 +- crates/ui/src/resizable/resize_handle.rs | 2 +- crates/ui/src/tab/mod.rs | 85 ++++++++----------- crates/ui/src/tab/tab_bar.rs | 26 ++---- 29 files changed, 130 insertions(+), 171 deletions(-) rename crates/ui/src/{dock_area => dock}/dock.rs (96%) rename crates/ui/src/{dock_area => dock}/mod.rs (97%) rename crates/ui/src/{dock_area => dock}/panel.rs (96%) rename crates/ui/src/{dock_area => dock}/stack_panel.rs (99%) rename crates/ui/src/{dock_area => dock}/tab_panel.rs (97%) diff --git a/assets/themes/catppuccin-frappe.json b/assets/themes/catppuccin-frappe.json index e24cb26..a5ceeb0 100644 --- a/assets/themes/catppuccin-frappe.json +++ b/assets/themes/catppuccin-frappe.json @@ -60,7 +60,6 @@ "tab_inactive_foreground": "#b5bfe2", "tab_active_background": "#303446", "tab_active_foreground": "#c6d0f5", - "tab_hover_foreground": "#babbf1", "scrollbar_thumb_background": "#c6d0f533", "scrollbar_thumb_hover_background": "#c6d0f580", "scrollbar_thumb_border": "#00000000", @@ -127,7 +126,6 @@ "tab_inactive_foreground": "#b5bfe2", "tab_active_background": "#303446", "tab_active_foreground": "#c6d0f5", - "tab_hover_foreground": "#babbf1", "scrollbar_thumb_background": "#c6d0f533", "scrollbar_thumb_hover_background": "#c6d0f580", "scrollbar_thumb_border": "#00000000", diff --git a/assets/themes/catppuccin-latte.json b/assets/themes/catppuccin-latte.json index 2b78530..c1dbcad 100644 --- a/assets/themes/catppuccin-latte.json +++ b/assets/themes/catppuccin-latte.json @@ -60,7 +60,6 @@ "tab_inactive_foreground": "#5c5f77", "tab_active_background": "#eff1f5", "tab_active_foreground": "#4c4f69", - "tab_hover_foreground": "#8839ef", "scrollbar_thumb_background": "#4c4f6933", "scrollbar_thumb_hover_background": "#4c4f6980", "scrollbar_thumb_border": "#00000000", @@ -127,7 +126,6 @@ "tab_inactive_foreground": "#5c5f77", "tab_active_background": "#eff1f5", "tab_active_foreground": "#4c4f69", - "tab_hover_foreground": "#8839ef", "scrollbar_thumb_background": "#4c4f6933", "scrollbar_thumb_hover_background": "#4c4f6980", "scrollbar_thumb_border": "#00000000", diff --git a/assets/themes/catppuccin-macchiato.json b/assets/themes/catppuccin-macchiato.json index a4c56b7..fad7d8b 100644 --- a/assets/themes/catppuccin-macchiato.json +++ b/assets/themes/catppuccin-macchiato.json @@ -60,7 +60,6 @@ "tab_inactive_foreground": "#b8c0e0", "tab_active_background": "#24273a", "tab_active_foreground": "#cad3f5", - "tab_hover_foreground": "#b7bdf8", "scrollbar_thumb_background": "#cad3f533", "scrollbar_thumb_hover_background": "#cad3f580", "scrollbar_thumb_border": "#00000000", @@ -127,7 +126,6 @@ "tab_inactive_foreground": "#b8c0e0", "tab_active_background": "#24273a", "tab_active_foreground": "#cad3f5", - "tab_hover_foreground": "#b7bdf8", "scrollbar_thumb_background": "#cad3f533", "scrollbar_thumb_hover_background": "#cad3f580", "scrollbar_thumb_border": "#00000000", diff --git a/assets/themes/catppuccin-mocha.json b/assets/themes/catppuccin-mocha.json index 420cbf3..87e1e8e 100644 --- a/assets/themes/catppuccin-mocha.json +++ b/assets/themes/catppuccin-mocha.json @@ -60,7 +60,6 @@ "tab_inactive_foreground": "#bac2de", "tab_active_background": "#1e1e2e", "tab_active_foreground": "#cdd6f4", - "tab_hover_foreground": "#b4befe", "scrollbar_thumb_background": "#cdd6f433", "scrollbar_thumb_hover_background": "#cdd6f580", "scrollbar_thumb_border": "#00000000", @@ -127,7 +126,6 @@ "tab_inactive_foreground": "#bac2de", "tab_active_background": "#1e1e2e", "tab_active_foreground": "#cdd6f4", - "tab_hover_foreground": "#b4befe", "scrollbar_thumb_background": "#cdd6f433", "scrollbar_thumb_hover_background": "#cdd6f580", "scrollbar_thumb_border": "#00000000", diff --git a/assets/themes/flexoki.json b/assets/themes/flexoki.json index 3d5c955..7e71db0 100644 --- a/assets/themes/flexoki.json +++ b/assets/themes/flexoki.json @@ -60,7 +60,6 @@ "tab_inactive_foreground": "#6F6E69", "tab_active_background": "#FFFCF0", "tab_active_foreground": "#100F0F", - "tab_hover_foreground": "#205EA6", "scrollbar_thumb_background": "#100F0F33", "scrollbar_thumb_hover_background": "#100F0F4d", "scrollbar_thumb_border": "#00000000", @@ -127,7 +126,6 @@ "tab_inactive_foreground": "#878580", "tab_active_background": "#100F0F", "tab_active_foreground": "#FFFCF0", - "tab_hover_foreground": "#4385BE", "scrollbar_thumb_background": "#FFFCF033", "scrollbar_thumb_hover_background": "#FFFCF04d", "scrollbar_thumb_border": "#00000000", diff --git a/assets/themes/rose-pine-dawn.json b/assets/themes/rose-pine-dawn.json index e30cc2a..79a54f1 100644 --- a/assets/themes/rose-pine-dawn.json +++ b/assets/themes/rose-pine-dawn.json @@ -60,7 +60,6 @@ "tab_inactive_foreground": "#797593", "tab_active_background": "#faf4ed", "tab_active_foreground": "#575279", - "tab_hover_foreground": "#907aa9", "scrollbar_thumb_background": "#57527933", "scrollbar_thumb_hover_background": "#5752794d", "scrollbar_thumb_border": "#00000000", @@ -127,7 +126,6 @@ "tab_inactive_foreground": "#797593", "tab_active_background": "#faf4ed", "tab_active_foreground": "#575279", - "tab_hover_foreground": "#907aa9", "scrollbar_thumb_background": "#57527933", "scrollbar_thumb_hover_background": "#5752794d", "scrollbar_thumb_border": "#00000000", diff --git a/assets/themes/rose-pine-moon.json b/assets/themes/rose-pine-moon.json index 37b8ef6..bfd2c44 100644 --- a/assets/themes/rose-pine-moon.json +++ b/assets/themes/rose-pine-moon.json @@ -60,7 +60,6 @@ "tab_inactive_foreground": "#908caa", "tab_active_background": "#232136", "tab_active_foreground": "#e0def4", - "tab_hover_foreground": "#c4a7e7", "scrollbar_thumb_background": "#e0def433", "scrollbar_thumb_hover_background": "#e0def44d", "scrollbar_thumb_border": "#00000000", @@ -127,7 +126,6 @@ "tab_inactive_foreground": "#908caa", "tab_active_background": "#232136", "tab_active_foreground": "#e0def4", - "tab_hover_foreground": "#c4a7e7", "scrollbar_thumb_background": "#e0def433", "scrollbar_thumb_hover_background": "#e0def44d", "scrollbar_thumb_border": "#00000000", diff --git a/assets/themes/rose-pine.json b/assets/themes/rose-pine.json index 703fa5c..3a6c48f 100644 --- a/assets/themes/rose-pine.json +++ b/assets/themes/rose-pine.json @@ -60,7 +60,6 @@ "tab_inactive_foreground": "#908caa", "tab_active_background": "#191724", "tab_active_foreground": "#e0def4", - "tab_hover_foreground": "#c4a7e7", "scrollbar_thumb_background": "#e0def433", "scrollbar_thumb_hover_background": "#e0def44d", "scrollbar_thumb_border": "#00000000", @@ -127,7 +126,6 @@ "tab_inactive_foreground": "#908caa", "tab_active_background": "#191724", "tab_active_foreground": "#e0def4", - "tab_hover_foreground": "#c4a7e7", "scrollbar_thumb_background": "#e0def433", "scrollbar_thumb_hover_background": "#e0def44d", "scrollbar_thumb_border": "#00000000", diff --git a/crates/chat_ui/src/lib.rs b/crates/chat_ui/src/lib.rs index 9f82af8..ab7d589 100644 --- a/crates/chat_ui/src/lib.rs +++ b/crates/chat_ui/src/lib.rs @@ -23,7 +23,7 @@ use state::{NostrRegistry, upload}; use theme::ActiveTheme; use ui::avatar::Avatar; use ui::button::{Button, ButtonVariants}; -use ui::dock_area::panel::{Panel, PanelEvent}; +use ui::dock::{Panel, PanelEvent}; use ui::indicator::Indicator; use ui::input::{InputEvent, InputState, TextInput}; use ui::menu::DropdownMenu; diff --git a/crates/coop/src/panels/backup.rs b/crates/coop/src/panels/backup.rs index e7dbce9..12c29c2 100644 --- a/crates/coop/src/panels/backup.rs +++ b/crates/coop/src/panels/backup.rs @@ -2,16 +2,16 @@ use std::time::Duration; use anyhow::Error; use gpui::{ - div, AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle, - Focusable, IntoElement, ParentElement, Render, SharedString, Styled, Task, Window, + AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle, + Focusable, IntoElement, ParentElement, Render, SharedString, Styled, Task, Window, div, }; use nostr_sdk::prelude::*; use state::KEYRING; use theme::ActiveTheme; use ui::button::{Button, ButtonVariants}; -use ui::dock_area::panel::{Panel, PanelEvent}; +use ui::dock::{Panel, PanelEvent}; use ui::input::{InputState, TextInput}; -use ui::{divider, v_flex, IconName, Sizable, StyledExt}; +use ui::{IconName, Sizable, StyledExt, divider, v_flex}; const MSG: &str = "Store your account keys in a safe location. \ You can restore your account or move to another client anytime you want."; diff --git a/crates/coop/src/panels/contact_list.rs b/crates/coop/src/panels/contact_list.rs index c6899ff..3935a26 100644 --- a/crates/coop/src/panels/contact_list.rs +++ b/crates/coop/src/panels/contact_list.rs @@ -15,7 +15,7 @@ use state::NostrRegistry; use theme::ActiveTheme; use ui::avatar::Avatar; use ui::button::{Button, ButtonVariants}; -use ui::dock_area::panel::{Panel, PanelEvent}; +use ui::dock::{Panel, PanelEvent}; use ui::input::{InputEvent, InputState, TextInput}; use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, h_flex, v_flex}; diff --git a/crates/coop/src/panels/greeter.rs b/crates/coop/src/panels/greeter.rs index 208ecab..97e1c37 100644 --- a/crates/coop/src/panels/greeter.rs +++ b/crates/coop/src/panels/greeter.rs @@ -5,8 +5,7 @@ use gpui::{ use state::NostrRegistry; use theme::ActiveTheme; use ui::button::{Button, ButtonVariants}; -use ui::dock_area::dock::DockPlacement; -use ui::dock_area::panel::{Panel, PanelEvent}; +use ui::dock::{DockPlacement, Panel, PanelEvent}; use ui::{Icon, IconName, Sizable, StyledExt, h_flex, v_flex}; use crate::panels::profile; diff --git a/crates/coop/src/panels/messaging_relays.rs b/crates/coop/src/panels/messaging_relays.rs index 5c5c36b..32e88cf 100644 --- a/crates/coop/src/panels/messaging_relays.rs +++ b/crates/coop/src/panels/messaging_relays.rs @@ -13,7 +13,7 @@ use smallvec::{SmallVec, smallvec}; use state::NostrRegistry; use theme::ActiveTheme; use ui::button::{Button, ButtonVariants}; -use ui::dock_area::panel::{Panel, PanelEvent}; +use ui::dock::{Panel, PanelEvent}; use ui::input::{InputEvent, InputState, TextInput}; use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, divider, h_flex, v_flex}; diff --git a/crates/coop/src/panels/profile.rs b/crates/coop/src/panels/profile.rs index fa26822..b9b26ce 100644 --- a/crates/coop/src/panels/profile.rs +++ b/crates/coop/src/panels/profile.rs @@ -14,7 +14,7 @@ use state::{NostrRegistry, upload}; use theme::ActiveTheme; use ui::avatar::Avatar; use ui::button::{Button, ButtonVariants}; -use ui::dock_area::panel::{Panel, PanelEvent}; +use ui::dock::{Panel, PanelEvent}; use ui::input::{InputState, TextInput}; use ui::notification::Notification; use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, h_flex, v_flex}; diff --git a/crates/coop/src/panels/relay_list.rs b/crates/coop/src/panels/relay_list.rs index 7aa283f..a47a338 100644 --- a/crates/coop/src/panels/relay_list.rs +++ b/crates/coop/src/panels/relay_list.rs @@ -1,23 +1,23 @@ use std::collections::HashSet; use std::time::Duration; -use anyhow::{anyhow, Context as AnyhowContext, Error}; +use anyhow::{Context as AnyhowContext, Error, anyhow}; use gpui::prelude::FluentBuilder; use gpui::{ - div, px, rems, Action, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, - Focusable, InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, - Subscription, Task, TextAlign, Window, + Action, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable, + InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Subscription, + Task, TextAlign, Window, div, px, rems, }; use nostr_sdk::prelude::*; use serde::Deserialize; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use state::NostrRegistry; use theme::ActiveTheme; use ui::button::{Button, ButtonVariants}; -use ui::dock_area::panel::{Panel, PanelEvent}; +use ui::dock::{Panel, PanelEvent}; use ui::input::{InputEvent, InputState, TextInput}; use ui::menu::DropdownMenu; -use ui::{divider, h_flex, v_flex, Disableable, IconName, Sizable, StyledExt, WindowExtension}; +use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, divider, h_flex, v_flex}; const MSG: &str = "Relay List (or Gossip Relays) are a set of relays \ where you will publish all your events. Others also publish events \ diff --git a/crates/coop/src/sidebar/entry.rs b/crates/coop/src/sidebar/entry.rs index d07618b..6c5c0ea 100644 --- a/crates/coop/src/sidebar/entry.rs +++ b/crates/coop/src/sidebar/entry.rs @@ -3,16 +3,16 @@ use std::rc::Rc; use chat::RoomKind; use gpui::prelude::FluentBuilder; use gpui::{ - div, App, ClickEvent, InteractiveElement, IntoElement, ParentElement as _, RenderOnce, - SharedString, StatefulInteractiveElement, Styled, Window, + App, ClickEvent, InteractiveElement, IntoElement, ParentElement as _, RenderOnce, SharedString, + StatefulInteractiveElement, Styled, Window, div, }; use nostr_sdk::prelude::*; use settings::AppSettings; use theme::ActiveTheme; use ui::avatar::Avatar; -use ui::dock_area::ClosePanel; +use ui::dock::ClosePanel; use ui::modal::ModalButtonProps; -use ui::{h_flex, Icon, IconName, Selectable, Sizable, StyledExt, WindowExtension}; +use ui::{Icon, IconName, Selectable, Sizable, StyledExt, WindowExtension, h_flex}; use crate::dialogs::screening; diff --git a/crates/coop/src/sidebar/mod.rs b/crates/coop/src/sidebar/mod.rs index 0c9bd78..927caec 100644 --- a/crates/coop/src/sidebar/mod.rs +++ b/crates/coop/src/sidebar/mod.rs @@ -18,7 +18,7 @@ use smallvec::{SmallVec, smallvec}; use state::{FIND_DELAY, NostrRegistry}; use theme::{ActiveTheme, SIDEBAR_WIDTH, TABBAR_HEIGHT}; use ui::button::{Button, ButtonVariants}; -use ui::dock_area::panel::{Panel, PanelEvent}; +use ui::dock::{Panel, PanelEvent}; use ui::indicator::Indicator; use ui::input::{InputEvent, InputState, TextInput}; use ui::notification::Notification; diff --git a/crates/coop/src/workspace.rs b/crates/coop/src/workspace.rs index e830e45..869cd1e 100644 --- a/crates/coop/src/workspace.rs +++ b/crates/coop/src/workspace.rs @@ -18,9 +18,7 @@ use theme::{ActiveTheme, SIDEBAR_WIDTH, Theme, ThemeRegistry}; use title_bar::TitleBar; use ui::avatar::Avatar; use ui::button::{Button, ButtonVariants}; -use ui::dock_area::dock::DockPlacement; -use ui::dock_area::panel::PanelView; -use ui::dock_area::{ClosePanel, DockArea, DockItem}; +use ui::dock::{ClosePanel, DockArea, DockItem, DockPlacement, PanelView}; use ui::menu::{DropdownMenu, PopupMenuItem}; use ui::notification::{Notification, NotificationKind}; use ui::{Disableable, IconName, Root, Sizable, WindowExtension, h_flex, v_flex}; @@ -277,8 +275,8 @@ impl Workspace { /// Set the center dock layout fn set_center_layout(&mut self, window: &mut Window, cx: &mut Context) { let dock = self.dock.downgrade(); - let greeeter = Arc::new(greeter::init(window, cx)); - let tabs = DockItem::tabs(vec![greeeter], None, &dock, window, cx); + let greeter = Arc::new(greeter::init(window, cx)); + let tabs = DockItem::tabs(vec![greeter], None, &dock, window, cx); let center = DockItem::split(Axis::Vertical, vec![tabs], &dock, window, cx); // Update the layout with center dock diff --git a/crates/theme/src/colors.rs b/crates/theme/src/colors.rs index c11d5a5..7910ea6 100644 --- a/crates/theme/src/colors.rs +++ b/crates/theme/src/colors.rs @@ -1,4 +1,4 @@ -use gpui::{hsla, Hsla, Rgba}; +use gpui::{Hsla, Rgba, hsla}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -77,11 +77,10 @@ pub struct ThemeColors { pub ghost_element_disabled: Hsla, // Tab colors - pub tab_inactive_background: Hsla, - pub tab_inactive_foreground: Hsla, + pub tab_background: Hsla, + pub tab_foreground: Hsla, pub tab_active_background: Hsla, pub tab_active_foreground: Hsla, - pub tab_hover_foreground: Hsla, // Scrollbar colors pub scrollbar_thumb_background: Hsla, @@ -166,11 +165,10 @@ impl ThemeColors { ghost_element_selected: neutral().light().step_5(), ghost_element_disabled: neutral().light_alpha().step_2(), - tab_inactive_background: neutral().light().step_2(), - tab_inactive_foreground: neutral().light().step_11(), + tab_background: neutral().light().step_3(), + tab_foreground: neutral().light().step_11(), tab_active_background: neutral().light().step_1(), tab_active_foreground: neutral().light().step_12(), - tab_hover_foreground: brand().light().step_9(), scrollbar_thumb_background: neutral().light_alpha().step_3(), scrollbar_thumb_hover_background: neutral().light_alpha().step_4(), @@ -250,11 +248,10 @@ impl ThemeColors { ghost_element_selected: neutral().dark().step_5(), ghost_element_disabled: neutral().dark_alpha().step_2(), - tab_inactive_background: neutral().dark().step_2(), - tab_inactive_foreground: neutral().dark().step_11(), - tab_active_background: neutral().dark().step_3(), + tab_background: neutral().dark().step_3(), + tab_foreground: neutral().dark().step_11(), + tab_active_background: neutral().dark().step_1(), tab_active_foreground: neutral().dark().step_12(), - tab_hover_foreground: brand().dark().step_9(), scrollbar_thumb_background: neutral().dark_alpha().step_3(), scrollbar_thumb_hover_background: neutral().dark_alpha().step_4(), diff --git a/crates/theme/src/lib.rs b/crates/theme/src/lib.rs index 96c170b..4a977af 100644 --- a/crates/theme/src/lib.rs +++ b/crates/theme/src/lib.rs @@ -34,7 +34,7 @@ pub const CLIENT_SIDE_DECORATION_BORDER: Pixels = px(1.0); pub const TITLEBAR_HEIGHT: Pixels = px(36.0); /// Defines workspace tabbar height -pub const TABBAR_HEIGHT: Pixels = px(28.0); +pub const TABBAR_HEIGHT: Pixels = px(32.0); /// Defines default sidebar width pub const SIDEBAR_WIDTH: Pixels = px(240.); diff --git a/crates/ui/src/dock_area/dock.rs b/crates/ui/src/dock/dock.rs similarity index 96% rename from crates/ui/src/dock_area/dock.rs rename to crates/ui/src/dock/dock.rs index 374317e..c0e7ec5 100644 --- a/crates/ui/src/dock_area/dock.rs +++ b/crates/ui/src/dock/dock.rs @@ -3,20 +3,26 @@ use std::sync::Arc; use gpui::prelude::FluentBuilder as _; use gpui::{ - div, px, App, AppContext, Axis, Context, Element, Entity, IntoElement, MouseMoveEvent, + App, AppContext, Axis, Context, Element, Empty, Entity, IntoElement, MouseMoveEvent, MouseUpEvent, ParentElement as _, Pixels, Point, Render, Style, Styled as _, WeakEntity, - Window, + Window, div, px, }; use super::{DockArea, DockItem}; -use crate::dock_area::panel::PanelView; -use crate::dock_area::tab_panel::TabPanel; -use crate::resizable::{resize_handle, PANEL_MIN_SIZE}; use crate::StyledExt; +use crate::dock::panel::PanelView; +use crate::dock::tab_panel::TabPanel; +use crate::resizable::{PANEL_MIN_SIZE, resize_handle}; -#[derive(Clone, Render)] +#[derive(Clone)] struct ResizePanel; +impl Render for ResizePanel { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + Empty + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DockPlacement { Center, diff --git a/crates/ui/src/dock_area/mod.rs b/crates/ui/src/dock/mod.rs similarity index 97% rename from crates/ui/src/dock_area/mod.rs rename to crates/ui/src/dock/mod.rs index 395983e..ad8f365 100644 --- a/crates/ui/src/dock_area/mod.rs +++ b/crates/ui/src/dock/mod.rs @@ -2,22 +2,24 @@ use std::sync::Arc; use gpui::prelude::FluentBuilder; use gpui::{ - actions, div, px, AnyElement, AnyView, App, AppContext, Axis, Bounds, Context, Decorations, - Edges, Entity, EntityId, EventEmitter, Focusable, InteractiveElement as _, IntoElement, - ParentElement as _, Pixels, Render, SharedString, Styled, Subscription, WeakEntity, Window, + AnyElement, AnyView, App, AppContext, Axis, Bounds, Context, Decorations, Edges, Entity, + EntityId, EventEmitter, Focusable, InteractiveElement as _, IntoElement, ParentElement as _, + Pixels, Render, SharedString, Styled, Subscription, WeakEntity, Window, actions, div, px, }; use theme::CLIENT_SIDE_DECORATION_ROUNDING; -use crate::dock_area::dock::{Dock, DockPlacement}; -use crate::dock_area::panel::{Panel, PanelEvent, PanelStyle, PanelView}; -use crate::dock_area::stack_panel::StackPanel; -use crate::dock_area::tab_panel::TabPanel; use crate::ElementExt; -pub mod dock; -pub mod panel; -pub mod stack_panel; -pub mod tab_panel; +#[allow(clippy::module_inception)] +mod dock; +mod panel; +mod stack_panel; +mod tab_panel; + +pub use dock::*; +pub use panel::*; +pub use stack_panel::*; +pub use tab_panel::*; actions!(dock, [ToggleZoom, ClosePanel]); diff --git a/crates/ui/src/dock_area/panel.rs b/crates/ui/src/dock/panel.rs similarity index 96% rename from crates/ui/src/dock_area/panel.rs rename to crates/ui/src/dock/panel.rs index a77d7a6..0f7e101 100644 --- a/crates/ui/src/dock_area/panel.rs +++ b/crates/ui/src/dock/panel.rs @@ -1,5 +1,5 @@ use gpui::{ - AnyElement, AnyView, App, Element, Entity, EventEmitter, FocusHandle, Focusable, Hsla, Render, + AnyElement, AnyView, App, Element, Entity, EventEmitter, FocusHandle, Focusable, Render, SharedString, Window, }; @@ -21,12 +21,6 @@ pub enum PanelStyle { TabBar, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct TitleStyle { - pub background: Hsla, - pub foreground: Hsla, -} - pub trait Panel: EventEmitter + Render + Focusable { /// The name of the panel used to serialize, deserialize and identify the panel. /// diff --git a/crates/ui/src/dock_area/stack_panel.rs b/crates/ui/src/dock/stack_panel.rs similarity index 99% rename from crates/ui/src/dock_area/stack_panel.rs rename to crates/ui/src/dock/stack_panel.rs index 85d20e8..b79e442 100644 --- a/crates/ui/src/dock_area/stack_panel.rs +++ b/crates/ui/src/dock/stack_panel.rs @@ -10,8 +10,8 @@ use smallvec::SmallVec; use theme::{ActiveTheme, AxisExt as _, CLIENT_SIDE_DECORATION_ROUNDING, Placement}; use super::{DockArea, PanelEvent}; -use crate::dock_area::panel::{Panel, PanelView}; -use crate::dock_area::tab_panel::TabPanel; +use crate::dock::panel::{Panel, PanelView}; +use crate::dock::tab_panel::TabPanel; use crate::h_flex; use crate::resizable::{ PANEL_MIN_SIZE, ResizablePanelEvent, ResizablePanelGroup, ResizablePanelState, ResizableState, diff --git a/crates/ui/src/dock_area/tab_panel.rs b/crates/ui/src/dock/tab_panel.rs similarity index 97% rename from crates/ui/src/dock_area/tab_panel.rs rename to crates/ui/src/dock/tab_panel.rs index 7265dfe..baa2f81 100644 --- a/crates/ui/src/dock_area/tab_panel.rs +++ b/crates/ui/src/dock/tab_panel.rs @@ -5,15 +5,15 @@ use gpui::{ App, AppContext, Context, Corner, DefiniteLength, DismissEvent, DragMoveEvent, Empty, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement as _, IntoElement, MouseButton, ParentElement, Pixels, Render, ScrollHandle, SharedString, StatefulInteractiveElement, Styled, - WeakEntity, Window, div, px, rems, + WeakEntity, Window, div, rems, }; use theme::{ActiveTheme, AxisExt, CLIENT_SIDE_DECORATION_ROUNDING, Placement, TABBAR_HEIGHT}; use crate::button::{Button, ButtonVariants as _}; -use crate::dock_area::dock::DockPlacement; -use crate::dock_area::panel::{Panel, PanelView}; -use crate::dock_area::stack_panel::StackPanel; -use crate::dock_area::{ClosePanel, DockArea, PanelEvent, PanelStyle, ToggleZoom}; +use crate::dock::dock::DockPlacement; +use crate::dock::panel::{Panel, PanelView}; +use crate::dock::stack_panel::StackPanel; +use crate::dock::{ClosePanel, DockArea, PanelEvent, PanelStyle, ToggleZoom}; use crate::menu::{DropdownMenu, PopupMenu}; use crate::tab::Tab; use crate::tab::tab_bar::TabBar; @@ -425,14 +425,13 @@ impl TabPanel { let view = cx.entity().clone(); let build_popup_menu = move |this, cx: &App| view.read(cx).popup_menu(this, cx); let toolbar = self.toolbar_buttons(window, cx); - let has_toolbar = !toolbar.is_empty(); h_flex() .p_0p5() - .gap_1() + .gap_1p5() .occlude() .rounded_full() - .children(toolbar.into_iter().map(|btn| btn.small().ghost().rounded())) + .children(toolbar.into_iter().map(|btn| btn.small().ghost())) .when(self.zoomed, |this| { this.child( Button::new("zoom") @@ -445,15 +444,11 @@ impl TabPanel { })), ) }) - .when(has_toolbar, |this| { - this.child(div().flex_shrink_0().h_4().w_px().bg(cx.theme().border)) - }) .child( Button::new("menu") .icon(IconName::Ellipsis) .small() .ghost() - .rounded() .dropdown_menu({ let zoomable = state.zoomable; let closable = state.closable; @@ -654,12 +649,8 @@ impl TabPanel { h_flex() .items_center() .top_0() - .right(-px(1.)) - .border_r_1() - .border_b_1() .h_full() - .border_color(cx.theme().border) - .bg(cx.theme().surface_background) + .bg(cx.theme().tab_background) .px_2() .children(left_dock_button) .children(bottom_dock_button), @@ -691,7 +682,7 @@ impl TabPanel { MouseButton::Middle, cx.listener({ let panel = panel.clone(); - move |view, _, window, cx| { + move |view, _ev, window, cx| { view.remove_panel(&panel, window, cx); } }), @@ -722,6 +713,19 @@ impl TabPanel { }, )) }) + .suffix( + Button::new("close-{ix}") + .icon(IconName::Close) + .tooltip("Close panel") + .ghost() + .xsmall() + .on_click(cx.listener({ + let panel = panel.clone(); + move |view, _ev, window, cx| { + view.remove_panel(&panel, window, cx); + } + })), + ) }), ) })) @@ -762,9 +766,6 @@ impl TabPanel { .top_0() .right_0() .h_full() - .border_color(cx.theme().border) - .border_l_1() - .border_b_1() .child(self.render_toolbar(state, window, cx)) .when_some(right_dock_button, |this, btn| this.child(btn)), ) @@ -1099,6 +1100,7 @@ impl Focusable for TabPanel { } impl EventEmitter for TabPanel {} + impl EventEmitter for TabPanel {} impl Render for TabPanel { diff --git a/crates/ui/src/lib.rs b/crates/ui/src/lib.rs index d047e88..6179733 100644 --- a/crates/ui/src/lib.rs +++ b/crates/ui/src/lib.rs @@ -17,7 +17,7 @@ pub mod avatar; pub mod button; pub mod checkbox; pub mod divider; -pub mod dock_area; +pub mod dock; pub mod group_box; pub mod history; pub mod indicator; diff --git a/crates/ui/src/resizable/resize_handle.rs b/crates/ui/src/resizable/resize_handle.rs index 8bc1ca9..e982c9f 100644 --- a/crates/ui/src/resizable/resize_handle.rs +++ b/crates/ui/src/resizable/resize_handle.rs @@ -9,7 +9,7 @@ use gpui::{ }; use theme::{ActiveTheme, AxisExt}; -use crate::dock_area::dock::DockPlacement; +use crate::dock::DockPlacement; pub(crate) const HANDLE_PADDING: Pixels = px(4.); pub(crate) const HANDLE_SIZE: Pixels = px(1.); diff --git a/crates/ui/src/tab/mod.rs b/crates/ui/src/tab/mod.rs index cace2b1..f53e050 100644 --- a/crates/ui/src/tab/mod.rs +++ b/crates/ui/src/tab/mod.rs @@ -1,11 +1,11 @@ use gpui::prelude::FluentBuilder; use gpui::{ - div, px, AnyElement, App, Div, InteractiveElement, IntoElement, MouseButton, ParentElement, - RenderOnce, StatefulInteractiveElement, Styled, Window, + AnyElement, App, Div, InteractiveElement, IntoElement, MouseButton, ParentElement, RenderOnce, + StatefulInteractiveElement, Styled, Window, div, px, }; use theme::{ActiveTheme, TABBAR_HEIGHT}; -use crate::{Selectable, Sizable, Size}; +use crate::{Selectable, Sizable, Size, h_flex}; pub mod tab_bar; @@ -106,59 +106,44 @@ impl Sizable for Tab { impl RenderOnce for Tab { fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement { - let (text_color, hover_text_color, bg_color, border_color) = - match (self.selected, self.disabled) { - (true, false) => ( - cx.theme().tab_active_foreground, - cx.theme().tab_hover_foreground, - cx.theme().tab_active_background, - cx.theme().border, - ), - (false, false) => ( - cx.theme().tab_inactive_foreground, - cx.theme().tab_hover_foreground, - cx.theme().ghost_element_background, - cx.theme().border_transparent, - ), - (true, true) => ( - cx.theme().tab_inactive_foreground, - cx.theme().tab_hover_foreground, - cx.theme().ghost_element_background, - cx.theme().border_disabled, - ), - (false, true) => ( - cx.theme().tab_inactive_foreground, - cx.theme().tab_hover_foreground, - cx.theme().ghost_element_background, - cx.theme().border_disabled, - ), - }; + let (text_color, bg_color) = match (self.selected, self.disabled) { + (true, false) => ( + cx.theme().tab_active_foreground, + cx.theme().tab_active_background, + ), + (false, false) => (cx.theme().tab_foreground, cx.theme().tab_background), + (true, true) => (cx.theme().text_muted, cx.theme().tab_background), + (false, true) => (cx.theme().text_placeholder, cx.theme().tab_background), + }; self.base .id(self.ix) - .h(TABBAR_HEIGHT) - .px_4() + .group("") .relative() - .flex() - .items_center() .flex_shrink_0() - .cursor_pointer() .overflow_hidden() - .text_xs() - .text_ellipsis() - .text_color(text_color) - .bg(bg_color) - .border_l(px(1.)) - .border_r(px(1.)) - .border_color(border_color) - .when(!self.selected && !self.disabled, |this| { - this.hover(|this| this.text_color(hover_text_color)) - }) - .when_some(self.prefix, |this, prefix| { - this.child(prefix).text_color(text_color) - }) - .when_some(self.label, |this, label| this.child(label)) - .when_some(self.suffix, |this, suffix| this.child(suffix)) + .child( + h_flex() + .h(TABBAR_HEIGHT - px(8.)) + .px_1() + .text_xs() + .text_ellipsis() + .text_color(text_color) + .bg(bg_color) + .rounded(cx.theme().radius) + .when(cx.theme().shadow && self.selected, |this| this.shadow_xs()) + .when_some(self.prefix, |this, prefix| this.child(prefix)) + .when_some(self.label, |this, label| this.child(label)) + .when_some(self.suffix, |this, suffix| { + this.child( + div() + .pl_4() + .invisible() + .group_hover("", |this| this.visible()) + .child(suffix), + ) + }), + ) .on_mouse_down(MouseButton::Left, |_ev, _window, cx| { cx.stop_propagation(); }) diff --git a/crates/ui/src/tab/tab_bar.rs b/crates/ui/src/tab/tab_bar.rs index 0362612..adfebf8 100644 --- a/crates/ui/src/tab/tab_bar.rs +++ b/crates/ui/src/tab/tab_bar.rs @@ -1,14 +1,14 @@ -use gpui::prelude::FluentBuilder as _; #[cfg(not(target_os = "windows"))] use gpui::Pixels; +use gpui::prelude::FluentBuilder as _; use gpui::{ - div, px, AnyElement, App, Div, InteractiveElement, IntoElement, ParentElement, RenderOnce, - ScrollHandle, StatefulInteractiveElement as _, StyleRefinement, Styled, Window, + AnyElement, App, Div, InteractiveElement, IntoElement, ParentElement, RenderOnce, ScrollHandle, + StatefulInteractiveElement as _, StyleRefinement, Styled, Window, div, px, }; use smallvec::SmallVec; use theme::ActiveTheme; -use crate::{h_flex, Sizable, Size, StyledExt}; +use crate::{Sizable, Size, StyledExt, h_flex}; #[derive(IntoElement)] pub struct TabBar { @@ -96,24 +96,16 @@ impl RenderOnce for TabBar { self.base .group("tab-bar") .relative() - .refine_style(&self.style) - .bg(cx.theme().surface_background) - .child( - div() - .id("border-bottom") - .absolute() - .left_0() - .bottom_0() - .size_full() - .border_b_1() - .border_color(cx.theme().border), - ) + .flex() + .items_center() + .bg(cx.theme().tab_background) .text_color(cx.theme().text) + .refine_style(&self.style) .when_some(self.prefix, |this, prefix| this.child(prefix)) .child( h_flex() .id("tabs") - .flex_grow() + .flex_1() .overflow_x_scroll() .when_some(self.scroll_handle, |this, scroll_handle| { this.track_scroll(&scroll_handle)