feat: apply declarative render rule across components
This commit is contained in:
+65
-73
@@ -1,6 +1,6 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use gpui::prelude::FluentBuilder as _;
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
AnyElement, App, Div, ElementId, InteractiveElement as _, IntoElement, KeyDownEvent,
|
||||
ParentElement as _, RenderOnce, Role, SharedString, Stateful, StatefulInteractiveElement as _,
|
||||
@@ -97,6 +97,9 @@ impl Tab {
|
||||
}
|
||||
}
|
||||
|
||||
// Tab is a data builder, not an element, adopt the combinators explicitly.
|
||||
impl FluentBuilder for Tab {}
|
||||
|
||||
/// A tab strip.
|
||||
#[derive(IntoElement)]
|
||||
pub struct Tabs {
|
||||
@@ -215,7 +218,7 @@ impl RenderOnce for Tabs {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut strip_root = div()
|
||||
div()
|
||||
.id(self.id.clone())
|
||||
.flex()
|
||||
.text_size(theme.sizes.medium.text_size)
|
||||
@@ -243,17 +246,14 @@ impl RenderOnce for Tabs {
|
||||
}
|
||||
cx.stop_propagation();
|
||||
}
|
||||
});
|
||||
|
||||
strip_root = match self.variant {
|
||||
TabsVariant::Underline => strip_root
|
||||
.gap_1()
|
||||
.border_b_1()
|
||||
.border_color(theme.colors.border),
|
||||
TabsVariant::Pill => strip_root.items_center().gap_1(),
|
||||
};
|
||||
|
||||
strip_root.children(strip)
|
||||
})
|
||||
.map(|root| match self.variant {
|
||||
TabsVariant::Underline => {
|
||||
root.gap_1().border_b_1().border_color(theme.colors.border)
|
||||
}
|
||||
TabsVariant::Pill => root.items_center().gap_1(),
|
||||
})
|
||||
.children(strip)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ fn render_tab(
|
||||
}
|
||||
};
|
||||
|
||||
let mut strip_tab = div()
|
||||
let strip_tab = div()
|
||||
.id((tab.key.clone(), "tab"))
|
||||
.debug_selector({
|
||||
let tabs_id = tabs_id.clone();
|
||||
@@ -310,67 +310,59 @@ fn render_tab(
|
||||
.text_color(label_color)
|
||||
.when(!tab.disabled && !selected, |strip_tab| {
|
||||
strip_tab.hover(|strip_tab| strip_tab.bg(theme.colors.muted))
|
||||
});
|
||||
|
||||
strip_tab = match variant {
|
||||
TabsVariant::Underline => strip_tab
|
||||
.px_2()
|
||||
.py_1()
|
||||
.rounded_tl(theme.radius.sm)
|
||||
.rounded_tr(theme.radius.sm)
|
||||
.border_b_2()
|
||||
.border_color(gpui::transparent_black())
|
||||
.when(selected, |strip_tab| {
|
||||
strip_tab.border_color(theme.ramps.primary.base)
|
||||
}),
|
||||
TabsVariant::Pill => strip_tab
|
||||
.h(small.control_height + metrics.plate_inset * 2.0)
|
||||
.px(metrics.dense_padding_x)
|
||||
.pr(metrics.plate_inset)
|
||||
.rounded(theme.radius.control)
|
||||
.when(selected, |strip_tab| {
|
||||
strip_tab
|
||||
.bg(theme.colors.muted)
|
||||
.hover(|strip_tab| strip_tab.bg(theme.colors.muted_hover))
|
||||
}),
|
||||
};
|
||||
|
||||
if let Some(lead) = tab.lead.take() {
|
||||
strip_tab = strip_tab.child(lead);
|
||||
}
|
||||
|
||||
strip_tab = strip_tab.child(tab.label.clone());
|
||||
|
||||
if variant == TabsVariant::Pill {
|
||||
strip_tab = strip_tab.child(div().flex_none().w(metrics.padding_x * 1.5));
|
||||
}
|
||||
|
||||
if tab.busy && !tab.disabled {
|
||||
strip_tab = strip_tab.child(
|
||||
Spinner::new((tab.key.clone(), "tab-busy"))
|
||||
.small()
|
||||
.accessibility_label("Loading"),
|
||||
);
|
||||
}
|
||||
|
||||
if tab.closeable && on_close.is_some() && !tab.disabled {
|
||||
strip_tab = strip_tab.child(render_tab_close(tabs_id, &tab, index, on_close));
|
||||
}
|
||||
|
||||
if !tab.disabled {
|
||||
strip_tab = strip_tab.cursor_pointer().on_click({
|
||||
let on_change = on_change.clone();
|
||||
let focus = focus.clone();
|
||||
move |_, window, cx| {
|
||||
window.focus(&focus, cx);
|
||||
if index != selected_index
|
||||
&& let Some(on_change) = &on_change
|
||||
{
|
||||
on_change(index, window, cx);
|
||||
})
|
||||
.map(|strip_tab| match variant {
|
||||
TabsVariant::Underline => strip_tab
|
||||
.px_2()
|
||||
.py_1()
|
||||
.rounded_tl(theme.radius.sm)
|
||||
.rounded_tr(theme.radius.sm)
|
||||
.border_b_2()
|
||||
.border_color(gpui::transparent_black())
|
||||
.when(selected, |strip_tab| {
|
||||
strip_tab.border_color(theme.ramps.primary.base)
|
||||
}),
|
||||
TabsVariant::Pill => strip_tab
|
||||
.h(small.control_height + metrics.plate_inset * 2.0)
|
||||
.px(metrics.dense_padding_x)
|
||||
.pr(metrics.plate_inset)
|
||||
.rounded(theme.radius.control)
|
||||
.when(selected, |strip_tab| {
|
||||
strip_tab
|
||||
.bg(theme.colors.muted)
|
||||
.hover(|strip_tab| strip_tab.bg(theme.colors.muted_hover))
|
||||
}),
|
||||
})
|
||||
.when_some(tab.lead.take(), |strip_tab, lead| strip_tab.child(lead))
|
||||
.child(tab.label.clone())
|
||||
.when(variant == TabsVariant::Pill, |strip_tab| {
|
||||
strip_tab.child(div().flex_none().w(metrics.padding_x * 1.5))
|
||||
})
|
||||
.when(tab.busy && !tab.disabled, |strip_tab| {
|
||||
strip_tab.child(
|
||||
Spinner::new((tab.key.clone(), "tab-busy"))
|
||||
.small()
|
||||
.accessibility_label("Loading"),
|
||||
)
|
||||
})
|
||||
.when(
|
||||
tab.closeable && on_close.is_some() && !tab.disabled,
|
||||
|strip_tab| strip_tab.child(render_tab_close(tabs_id, &tab, index, on_close)),
|
||||
)
|
||||
.when(!tab.disabled, |strip_tab| {
|
||||
strip_tab.cursor_pointer().on_click({
|
||||
let on_change = on_change.clone();
|
||||
let focus = focus.clone();
|
||||
move |_, window, cx| {
|
||||
window.focus(&focus, cx);
|
||||
if index != selected_index
|
||||
&& let Some(on_change) = &on_change
|
||||
{
|
||||
on_change(index, window, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
match tab.wrap {
|
||||
Some(wrap) => wrap(strip_tab),
|
||||
|
||||
Reference in New Issue
Block a user