ui: Add new component for thread sidebar panel toggle (#51441)
This commit is contained in:
1 parent
8e045237c4
commit
ea5c58c19a
5 files changed
+235
-3
No files matched your search
@@ -1,5 +1,7 @@
|
||||
mod configured_api_card;
|
||||
mod thread_item;
|
||||
mod thread_sidebar_toggle;
|
||||
|
||||
pub use configured_api_card::*;
|
||||
pub use thread_item::*;
|
||||
pub use thread_sidebar_toggle::*;
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{Tooltip, prelude::*};
|
||||
use gpui::{ClickEvent, IntoElement, ParentElement, SharedString};
|
||||
|
||||
#[derive(IntoElement)]
|
||||
#[derive(IntoElement, RegisterComponent)]
|
||||
pub struct ConfiguredApiCard {
|
||||
label: SharedString,
|
||||
button_label: Option<SharedString>,
|
||||
@@ -52,6 +52,59 @@ impl ConfiguredApiCard {
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for ConfiguredApiCard {
|
||||
fn scope() -> ComponentScope {
|
||||
ComponentScope::Agent
|
||||
}
|
||||
|
||||
fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
|
||||
let container = || {
|
||||
v_flex()
|
||||
.w_72()
|
||||
.p_2()
|
||||
.gap_2()
|
||||
.border_1()
|
||||
.border_color(cx.theme().colors().border_variant)
|
||||
.bg(cx.theme().colors().panel_background)
|
||||
};
|
||||
|
||||
let examples = vec![
|
||||
single_example(
|
||||
"Default",
|
||||
container()
|
||||
.child(ConfiguredApiCard::new("API key is configured"))
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"Custom Button Label",
|
||||
container()
|
||||
.child(
|
||||
ConfiguredApiCard::new("OpenAI API key configured")
|
||||
.button_label("Remove Key"),
|
||||
)
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"With Tooltip",
|
||||
container()
|
||||
.child(
|
||||
ConfiguredApiCard::new("Anthropic API key configured")
|
||||
.tooltip_label("Click to reset your API key"),
|
||||
)
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"Disabled",
|
||||
container()
|
||||
.child(ConfiguredApiCard::new("API key is configured").disabled(true))
|
||||
.into_any_element(),
|
||||
),
|
||||
];
|
||||
|
||||
Some(example_group(examples).into_any_element())
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ConfiguredApiCard {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let button_label = self.button_label.unwrap_or("Reset Key".into());
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
use gpui::{AnyView, ClickEvent};
|
||||
use ui_macros::RegisterComponent;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::{IconButton, IconName, Tooltip};
|
||||
|
||||
#[derive(IntoElement, RegisterComponent)]
|
||||
pub struct ThreadSidebarToggle {
|
||||
sidebar_selected: bool,
|
||||
thread_selected: bool,
|
||||
flipped: bool,
|
||||
sidebar_tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView + 'static>>,
|
||||
thread_tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView + 'static>>,
|
||||
on_sidebar_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||
on_thread_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||
}
|
||||
|
||||
impl ThreadSidebarToggle {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
sidebar_selected: false,
|
||||
thread_selected: false,
|
||||
flipped: false,
|
||||
sidebar_tooltip: None,
|
||||
thread_tooltip: None,
|
||||
on_sidebar_click: None,
|
||||
on_thread_click: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sidebar_selected(mut self, selected: bool) -> Self {
|
||||
self.sidebar_selected = selected;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn thread_selected(mut self, selected: bool) -> Self {
|
||||
self.thread_selected = selected;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn flipped(mut self, flipped: bool) -> Self {
|
||||
self.flipped = flipped;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn sidebar_tooltip(
|
||||
mut self,
|
||||
tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static,
|
||||
) -> Self {
|
||||
self.sidebar_tooltip = Some(Box::new(tooltip));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn thread_tooltip(
|
||||
mut self,
|
||||
tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static,
|
||||
) -> Self {
|
||||
self.thread_tooltip = Some(Box::new(tooltip));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_sidebar_click(
|
||||
mut self,
|
||||
handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_sidebar_click = Some(Box::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_thread_click(
|
||||
mut self,
|
||||
handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_thread_click = Some(Box::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ThreadSidebarToggle {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let sidebar_icon = match (self.sidebar_selected, self.flipped) {
|
||||
(true, false) => IconName::ThreadsSidebarLeftOpen,
|
||||
(false, false) => IconName::ThreadsSidebarLeftClosed,
|
||||
(true, true) => IconName::ThreadsSidebarRightOpen,
|
||||
(false, true) => IconName::ThreadsSidebarRightClosed,
|
||||
};
|
||||
|
||||
h_flex()
|
||||
.min_w_0()
|
||||
.rounded_sm()
|
||||
.gap_px()
|
||||
.border_1()
|
||||
.border_color(cx.theme().colors().border)
|
||||
.when(self.flipped, |this| this.flex_row_reverse())
|
||||
.child(
|
||||
IconButton::new("sidebar-toggle", sidebar_icon)
|
||||
.icon_size(IconSize::Small)
|
||||
.toggle_state(self.sidebar_selected)
|
||||
.when_some(self.sidebar_tooltip, |this, tooltip| this.tooltip(tooltip))
|
||||
.when_some(self.on_sidebar_click, |this, handler| {
|
||||
this.on_click(handler)
|
||||
}),
|
||||
)
|
||||
.child(div().h_4().w_px().bg(cx.theme().colors().border))
|
||||
.child(
|
||||
IconButton::new("thread-toggle", IconName::Thread)
|
||||
.icon_size(IconSize::Small)
|
||||
.toggle_state(self.thread_selected)
|
||||
.when_some(self.thread_tooltip, |this, tooltip| this.tooltip(tooltip))
|
||||
.when_some(self.on_thread_click, |this, handler| this.on_click(handler)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for ThreadSidebarToggle {
|
||||
fn scope() -> ComponentScope {
|
||||
ComponentScope::Agent
|
||||
}
|
||||
|
||||
fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
|
||||
let container = || div().p_2().bg(cx.theme().colors().status_bar_background);
|
||||
|
||||
let examples = vec![
|
||||
single_example(
|
||||
"Both Unselected",
|
||||
container()
|
||||
.child(ThreadSidebarToggle::new())
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"Sidebar Selected",
|
||||
container()
|
||||
.child(ThreadSidebarToggle::new().sidebar_selected(true))
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"Thread Selected",
|
||||
container()
|
||||
.child(ThreadSidebarToggle::new().thread_selected(true))
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"Both Selected",
|
||||
container()
|
||||
.child(
|
||||
ThreadSidebarToggle::new()
|
||||
.sidebar_selected(true)
|
||||
.thread_selected(true),
|
||||
)
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"Flipped",
|
||||
container()
|
||||
.child(
|
||||
ThreadSidebarToggle::new()
|
||||
.sidebar_selected(true)
|
||||
.thread_selected(true)
|
||||
.flipped(true),
|
||||
)
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"With Tooltips",
|
||||
container()
|
||||
.child(
|
||||
ThreadSidebarToggle::new()
|
||||
.sidebar_tooltip(Tooltip::text("Toggle Sidebar"))
|
||||
.thread_tooltip(Tooltip::text("Toggle Thread")),
|
||||
)
|
||||
.into_any_element(),
|
||||
),
|
||||
];
|
||||
|
||||
Some(example_group(examples).into_any_element())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user