diff --git a/crates/app/src/story_workspace.rs b/crates/app/src/story_workspace.rs index 7be6bc36..83ce0bdf 100644 --- a/crates/app/src/story_workspace.rs +++ b/crates/app/src/story_workspace.rs @@ -94,6 +94,7 @@ impl StoryWorkspace { None, None, false, + None, cx, ); @@ -105,6 +106,7 @@ impl StoryWorkspace { None, None, false, + None, cx, ); @@ -116,6 +118,7 @@ impl StoryWorkspace { Some(Placement::Bottom), Some(px(200.)), true, + None, cx, ); @@ -127,6 +130,7 @@ impl StoryWorkspace { None, None, true, + None, cx, ); @@ -138,6 +142,7 @@ impl StoryWorkspace { None, None, true, + None, cx, ); @@ -149,6 +154,7 @@ impl StoryWorkspace { None, None, true, + None, cx, ); @@ -160,6 +166,7 @@ impl StoryWorkspace { None, None, true, + None, cx, ); @@ -171,6 +178,7 @@ impl StoryWorkspace { None, None, true, + None, cx, ); @@ -182,6 +190,7 @@ impl StoryWorkspace { None, None, true, + None, cx, ); @@ -193,6 +202,7 @@ impl StoryWorkspace { Some(Placement::Bottom), Some(px(200.)), true, + None, cx, ); @@ -204,6 +214,7 @@ impl StoryWorkspace { Some(Placement::Bottom), None, true, + Some(cx.theme().muted), cx, ); @@ -223,6 +234,7 @@ impl StoryWorkspace { None, None, true, + None, cx, ); @@ -234,6 +246,7 @@ impl StoryWorkspace { Some(Placement::Bottom), Some(px(200.)), true, + None, cx, ); @@ -245,6 +258,7 @@ impl StoryWorkspace { None, None, true, + None, cx, ); @@ -256,6 +270,7 @@ impl StoryWorkspace { None, None, true, + None, cx, ); @@ -267,6 +282,7 @@ impl StoryWorkspace { Some(Placement::Bottom), None, true, + None, cx, ); diff --git a/crates/story/src/lib.rs b/crates/story/src/lib.rs index 091fb3b7..8435eeca 100644 --- a/crates/story/src/lib.rs +++ b/crates/story/src/lib.rs @@ -38,17 +38,19 @@ pub use webview_story::WebViewStory; use gpui::{ actions, div, prelude::FluentBuilder as _, px, AnyView, AppContext, Div, EventEmitter, - FocusableView, InteractiveElement, IntoElement, ParentElement, Pixels, Render, SharedString, - StatefulInteractiveElement, Styled as _, View, ViewContext, VisualContext, WindowContext, + FocusableView, Hsla, InteractiveElement, IntoElement, ParentElement, Pixels, Render, + SharedString, StatefulInteractiveElement, Styled as _, View, ViewContext, VisualContext, + WindowContext, }; use ui::{ divider::Divider, - dock::{Panel, PanelEvent, TabPanel}, + dock::{Panel, PanelEvent, TabPanel, TitleStyle}, h_flex, label::Label, notification::Notification, popup_menu::PopupMenu, + theme::ActiveTheme, v_flex, ContextModal, Placement, }; @@ -80,6 +82,7 @@ pub fn section(title: impl IntoElement, cx: &WindowContext) -> Div { pub struct StoryContainer { focus_handle: gpui::FocusHandle, name: SharedString, + title_bg: Option, description: SharedString, width: Option, height: Option, @@ -106,6 +109,7 @@ impl StoryContainer { Self { focus_handle, name: name.into(), + title_bg: None, description: description.into(), width: None, height: None, @@ -123,13 +127,18 @@ impl StoryContainer { placement: Option, size: Option, closeable: bool, + title_bg: Option, cx: &mut WindowContext, ) { let name = name.into(); let description = description.into(); tab_panel.update(cx, |panel, cx| { - let view = cx.new_view(|cx| Self::new(name, description, closeable, cx).story(story)); + let view = cx.new_view(|cx| { + Self::new(name, description, closeable, cx) + .story(story) + .title_bg(title_bg) + }); if let Some(placement) = placement { panel.add_panel_at(Arc::new(view.clone()), placement, size, cx); } else { @@ -154,6 +163,11 @@ impl StoryContainer { self } + pub fn title_bg(mut self, title_bg: Option) -> Self { + self.title_bg = title_bg; + self + } + fn on_action_panel_info(&mut self, _: &PanelInfo, cx: &mut ViewContext) { struct Info; let note = Notification::new(format!("You have clicked panel info on: {}", self.name)) @@ -167,6 +181,17 @@ impl Panel for StoryContainer { self.name.clone() } + fn title_style(&self, cx: &WindowContext) -> Option { + if let Some(bg) = self.title_bg { + Some(TitleStyle { + background: bg, + foreground: cx.theme().foreground, + }) + } else { + None + } + } + fn closeable(&self, _cx: &WindowContext) -> bool { self.closeable } diff --git a/crates/ui/src/dock/panel.rs b/crates/ui/src/dock/panel.rs index ed56dab7..fea5dd8a 100644 --- a/crates/ui/src/dock/panel.rs +++ b/crates/ui/src/dock/panel.rs @@ -1,16 +1,26 @@ -use gpui::{AnyView, EventEmitter, FocusableView, SharedString, View, WindowContext}; +use gpui::{AnyView, EventEmitter, FocusableView, Hsla, SharedString, View, WindowContext}; use rust_i18n::t; use crate::popup_menu::PopupMenu; use super::PanelEvent; +pub struct TitleStyle { + pub background: Hsla, + pub foreground: Hsla, +} + pub trait Panel: EventEmitter + FocusableView { /// The title of the panel, default is `None`. fn title(&self, _cx: &WindowContext) -> SharedString { t!("Dock.Unnamed").into() } + /// The theme of the panel title, default is `None`. + fn title_style(&self, _cx: &WindowContext) -> Option { + None + } + /// Whether the panel can be closed, default is `true`. fn closeable(&self, _cx: &WindowContext) -> bool { true @@ -23,9 +33,10 @@ pub trait Panel: EventEmitter + FocusableView { } pub trait PanelView: 'static + Send + Sync { - /// The title of the panel, default is `None`. fn title(&self, _cx: &WindowContext) -> SharedString; + fn title_style(&self, _cx: &WindowContext) -> Option; + fn closeable(&self, cx: &WindowContext) -> bool; fn popup_menu(&self, menu: PopupMenu, cx: &WindowContext) -> PopupMenu; @@ -38,6 +49,10 @@ impl PanelView for View { self.read(cx).title(cx) } + fn title_style(&self, cx: &WindowContext) -> Option { + self.read(cx).title_style(cx) + } + fn closeable(&self, cx: &WindowContext) -> bool { self.read(cx).closeable(cx) } diff --git a/crates/ui/src/dock/tab_panel.rs b/crates/ui/src/dock/tab_panel.rs index ea1509e4..d87c24e8 100644 --- a/crates/ui/src/dock/tab_panel.rs +++ b/crates/ui/src/dock/tab_panel.rs @@ -242,12 +242,16 @@ impl TabPanel { if self.panels.len() == 1 { let panel = self.panels.get(0).unwrap(); let title = panel.title(cx); + let title_style = panel.title_style(cx); return h_flex() .justify_between() .items_center() .line_height(rems(1.0)) .pr_3() + .when_some(title_style, |this, theme| { + this.bg(theme.background).text_color(theme.foreground) + }) .child( div() .id("tab")