tab: Add new pill style, renamed old pill tab to outline. (#696)
<img width="1011" alt="image" src="https://github.com/user-attachments/assets/4800a737-4e57-405b-b083-bf57ae3038ad" /> ## Break Changes - As you see on the above screenshot, the old `pill` style has been renamed to `outline`.
This commit is contained in:
parent
8611a23aae
commit
8f2ca40c51
5 changed files with 110 additions and 33 deletions
|
|
@ -4,7 +4,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
accordion::Accordion,
|
accordion::Accordion,
|
||||||
button::{Button, ButtonGroup},
|
button::{Button, ButtonGroup, ButtonVariants as _},
|
||||||
checkbox::Checkbox,
|
checkbox::Checkbox,
|
||||||
h_flex,
|
h_flex,
|
||||||
switch::Switch,
|
switch::Switch,
|
||||||
|
|
@ -72,6 +72,8 @@ impl Render for AccordionStory {
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(
|
.child(
|
||||||
ButtonGroup::new("toggle-size")
|
ButtonGroup::new("toggle-size")
|
||||||
|
.outline()
|
||||||
|
.compact()
|
||||||
.child(
|
.child(
|
||||||
Button::new("xsmall")
|
Button::new("xsmall")
|
||||||
.label("XSmall")
|
.label("XSmall")
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use gpui::{
|
||||||
ParentElement, Pixels, Render, ScrollHandle, SharedString, Size, Styled, Window,
|
ParentElement, Pixels, Render, ScrollHandle, SharedString, Size, Styled, Window,
|
||||||
};
|
};
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
button::{Button, ButtonGroup},
|
button::{Button, ButtonGroup, ButtonVariants as _},
|
||||||
divider::Divider,
|
divider::Divider,
|
||||||
gray_100, gray_800, h_flex,
|
gray_100, gray_800, h_flex,
|
||||||
label::Label,
|
label::Label,
|
||||||
|
|
@ -103,6 +103,8 @@ impl ScrollableStory {
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(
|
.child(
|
||||||
ButtonGroup::new("test-cases")
|
ButtonGroup::new("test-cases")
|
||||||
|
.outline()
|
||||||
|
.compact()
|
||||||
.child(
|
.child(
|
||||||
Button::new("test-0")
|
Button::new("test-0")
|
||||||
.label("Size 0")
|
.label("Size 0")
|
||||||
|
|
@ -138,6 +140,8 @@ impl ScrollableStory {
|
||||||
.child(Divider::vertical().px_2())
|
.child(Divider::vertical().px_2())
|
||||||
.child(
|
.child(
|
||||||
ButtonGroup::new("scrollbars")
|
ButtonGroup::new("scrollbars")
|
||||||
|
.outline()
|
||||||
|
.compact()
|
||||||
.child(
|
.child(
|
||||||
Button::new("test-axis-both")
|
Button::new("test-axis-both")
|
||||||
.label("Both Scrollbar")
|
.label("Both Scrollbar")
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,8 @@ impl Render for TabsStory {
|
||||||
.gap_6()
|
.gap_6()
|
||||||
.child(
|
.child(
|
||||||
ButtonGroup::new("toggle-size")
|
ButtonGroup::new("toggle-size")
|
||||||
|
.outline()
|
||||||
|
.compact()
|
||||||
.child(
|
.child(
|
||||||
Button::new("xsmall")
|
Button::new("xsmall")
|
||||||
.label("XSmall")
|
.label("XSmall")
|
||||||
|
|
@ -144,6 +146,28 @@ impl Render for TabsStory {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.child(
|
||||||
|
section("Underline Tabs", cx).child(
|
||||||
|
TabBar::new("underline")
|
||||||
|
.w_full()
|
||||||
|
.px_2()
|
||||||
|
.mx_3()
|
||||||
|
.underline()
|
||||||
|
.with_size(self.size)
|
||||||
|
.selected_index(self.active_tab_ix)
|
||||||
|
.on_click(cx.listener(|this, ix: &usize, window, cx| {
|
||||||
|
this.set_active_tab(*ix, window, cx);
|
||||||
|
}))
|
||||||
|
.child("Account")
|
||||||
|
.child("Profile")
|
||||||
|
.child("Documents")
|
||||||
|
.child("Mail")
|
||||||
|
.child("Appearance")
|
||||||
|
.child("Settings")
|
||||||
|
.child("About")
|
||||||
|
.child("License"),
|
||||||
|
),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
section("Pill Tabs", cx).child(
|
section("Pill Tabs", cx).child(
|
||||||
TabBar::new("pill")
|
TabBar::new("pill")
|
||||||
|
|
@ -164,6 +188,26 @@ impl Render for TabsStory {
|
||||||
.child(Tab::new("License")),
|
.child(Tab::new("License")),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.child(
|
||||||
|
section("Outline Tabs", cx).child(
|
||||||
|
TabBar::new("outline")
|
||||||
|
.w_full()
|
||||||
|
.outline()
|
||||||
|
.with_size(self.size)
|
||||||
|
.selected_index(self.active_tab_ix)
|
||||||
|
.on_click(cx.listener(|this, ix: &usize, window, cx| {
|
||||||
|
this.set_active_tab(*ix, window, cx);
|
||||||
|
}))
|
||||||
|
.child(Tab::new("Account"))
|
||||||
|
.child(Tab::new("Profile").disabled(true))
|
||||||
|
.child(Tab::new("Documents & Files"))
|
||||||
|
.child(Tab::new("Mail"))
|
||||||
|
.child(Tab::new("Appearance"))
|
||||||
|
.child(Tab::new("Settings"))
|
||||||
|
.child(Tab::new("About"))
|
||||||
|
.child(Tab::new("License")),
|
||||||
|
),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
section("Segmented Tabs", cx).child(
|
section("Segmented Tabs", cx).child(
|
||||||
TabBar::new("segmented")
|
TabBar::new("segmented")
|
||||||
|
|
@ -180,27 +224,5 @@ impl Render for TabsStory {
|
||||||
.children(vec!["Appearance", "Settings", "About", "License"]),
|
.children(vec!["Appearance", "Settings", "About", "License"]),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(
|
|
||||||
section("Underline Tabs", cx).child(
|
|
||||||
TabBar::new("underline")
|
|
||||||
.w_full()
|
|
||||||
.px_2()
|
|
||||||
.mx_3()
|
|
||||||
.underline()
|
|
||||||
.with_size(self.size)
|
|
||||||
.selected_index(self.active_tab_ix)
|
|
||||||
.on_click(cx.listener(|this, ix: &usize, window, cx| {
|
|
||||||
this.set_active_tab(*ix, window, cx);
|
|
||||||
}))
|
|
||||||
.child("Account")
|
|
||||||
.child("Profile")
|
|
||||||
.child("Documents")
|
|
||||||
.child("Mail")
|
|
||||||
.child("Appearance")
|
|
||||||
.child("Settings")
|
|
||||||
.child("About")
|
|
||||||
.child("License"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ use gpui::{
|
||||||
pub enum TabVariant {
|
pub enum TabVariant {
|
||||||
#[default]
|
#[default]
|
||||||
Tab,
|
Tab,
|
||||||
|
Outline,
|
||||||
Pill,
|
Pill,
|
||||||
Segmented,
|
Segmented,
|
||||||
Underline,
|
Underline,
|
||||||
|
|
@ -66,23 +67,23 @@ impl TabVariant {
|
||||||
fn inner_height(&self, size: Size) -> Pixels {
|
fn inner_height(&self, size: Size) -> Pixels {
|
||||||
match size {
|
match size {
|
||||||
Size::XSmall => match self {
|
Size::XSmall => match self {
|
||||||
TabVariant::Tab | TabVariant::Pill => px(20.),
|
TabVariant::Tab | TabVariant::Outline | TabVariant::Pill => px(20.),
|
||||||
TabVariant::Segmented => px(16.),
|
TabVariant::Segmented => px(16.),
|
||||||
TabVariant::Underline => px(20.),
|
TabVariant::Underline => px(20.),
|
||||||
},
|
},
|
||||||
Size::Small => match self {
|
Size::Small => match self {
|
||||||
TabVariant::Tab | TabVariant::Pill => px(24.),
|
TabVariant::Tab | TabVariant::Outline | TabVariant::Pill => px(24.),
|
||||||
TabVariant::Segmented => px(20.),
|
TabVariant::Segmented => px(20.),
|
||||||
TabVariant::Underline => px(22.),
|
TabVariant::Underline => px(22.),
|
||||||
},
|
},
|
||||||
Size::Large => match self {
|
Size::Large => match self {
|
||||||
TabVariant::Tab | TabVariant::Pill => px(36.),
|
TabVariant::Tab | TabVariant::Outline | TabVariant::Pill => px(36.),
|
||||||
TabVariant::Segmented => px(28.),
|
TabVariant::Segmented => px(28.),
|
||||||
TabVariant::Underline => px(30.),
|
TabVariant::Underline => px(30.),
|
||||||
},
|
},
|
||||||
_ => match self {
|
_ => match self {
|
||||||
TabVariant::Tab => px(30.),
|
TabVariant::Tab => px(30.),
|
||||||
TabVariant::Pill => px(26.),
|
TabVariant::Outline | TabVariant::Pill => px(26.),
|
||||||
TabVariant::Segmented => px(24.),
|
TabVariant::Segmented => px(24.),
|
||||||
TabVariant::Underline => px(24.),
|
TabVariant::Underline => px(24.),
|
||||||
},
|
},
|
||||||
|
|
@ -143,7 +144,7 @@ impl TabVariant {
|
||||||
border_color: cx.theme().transparent,
|
border_color: cx.theme().transparent,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TabVariant::Pill => TabStyle {
|
TabVariant::Outline => TabStyle {
|
||||||
fg: cx.theme().tab_foreground,
|
fg: cx.theme().tab_foreground,
|
||||||
bg: cx.theme().transparent,
|
bg: cx.theme().transparent,
|
||||||
borders: Edges::all(px(1.)),
|
borders: Edges::all(px(1.)),
|
||||||
|
|
@ -151,6 +152,12 @@ impl TabVariant {
|
||||||
radius: px(99.),
|
radius: px(99.),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
TabVariant::Pill => TabStyle {
|
||||||
|
fg: cx.theme().foreground,
|
||||||
|
bg: cx.theme().transparent,
|
||||||
|
radius: px(99.),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
TabVariant::Segmented => TabStyle {
|
TabVariant::Segmented => TabStyle {
|
||||||
fg: cx.theme().tab_foreground,
|
fg: cx.theme().tab_foreground,
|
||||||
bg: cx.theme().transparent,
|
bg: cx.theme().transparent,
|
||||||
|
|
@ -187,7 +194,7 @@ impl TabVariant {
|
||||||
border_color: cx.theme().transparent,
|
border_color: cx.theme().transparent,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TabVariant::Pill => TabStyle {
|
TabVariant::Outline => TabStyle {
|
||||||
fg: cx.theme().secondary_foreground,
|
fg: cx.theme().secondary_foreground,
|
||||||
bg: cx.theme().secondary_hover,
|
bg: cx.theme().secondary_hover,
|
||||||
borders: Edges::all(px(1.)),
|
borders: Edges::all(px(1.)),
|
||||||
|
|
@ -195,6 +202,12 @@ impl TabVariant {
|
||||||
radius: px(99.),
|
radius: px(99.),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
TabVariant::Pill => TabStyle {
|
||||||
|
fg: cx.theme().secondary_foreground,
|
||||||
|
bg: cx.theme().secondary_hover,
|
||||||
|
radius: px(99.),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
TabVariant::Segmented => TabStyle {
|
TabVariant::Segmented => TabStyle {
|
||||||
fg: cx.theme().tab_foreground,
|
fg: cx.theme().tab_foreground,
|
||||||
bg: cx.theme().transparent,
|
bg: cx.theme().transparent,
|
||||||
|
|
@ -236,7 +249,7 @@ impl TabVariant {
|
||||||
border_color: cx.theme().border,
|
border_color: cx.theme().border,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TabVariant::Pill => TabStyle {
|
TabVariant::Outline => TabStyle {
|
||||||
fg: cx.theme().primary,
|
fg: cx.theme().primary,
|
||||||
bg: cx.theme().transparent,
|
bg: cx.theme().transparent,
|
||||||
borders: Edges::all(px(1.)),
|
borders: Edges::all(px(1.)),
|
||||||
|
|
@ -244,6 +257,12 @@ impl TabVariant {
|
||||||
radius: px(99.),
|
radius: px(99.),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
TabVariant::Pill => TabStyle {
|
||||||
|
fg: cx.theme().primary_foreground,
|
||||||
|
bg: cx.theme().primary,
|
||||||
|
radius: px(99.),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
TabVariant::Segmented => TabStyle {
|
TabVariant::Segmented => TabStyle {
|
||||||
fg: cx.theme().tab_active_foreground,
|
fg: cx.theme().tab_active_foreground,
|
||||||
bg: cx.theme().transparent,
|
bg: cx.theme().transparent,
|
||||||
|
|
@ -283,7 +302,7 @@ impl TabVariant {
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
TabVariant::Pill => TabStyle {
|
TabVariant::Outline => TabStyle {
|
||||||
fg: cx.theme().muted_foreground,
|
fg: cx.theme().muted_foreground,
|
||||||
bg: cx.theme().transparent,
|
bg: cx.theme().transparent,
|
||||||
borders: Edges::all(px(1.)),
|
borders: Edges::all(px(1.)),
|
||||||
|
|
@ -295,6 +314,20 @@ impl TabVariant {
|
||||||
radius: px(99.),
|
radius: px(99.),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
TabVariant::Pill => TabStyle {
|
||||||
|
fg: if selected {
|
||||||
|
cx.theme().primary_foreground.opacity(0.5)
|
||||||
|
} else {
|
||||||
|
cx.theme().muted_foreground
|
||||||
|
},
|
||||||
|
bg: if selected {
|
||||||
|
cx.theme().primary.opacity(0.5)
|
||||||
|
} else {
|
||||||
|
cx.theme().transparent
|
||||||
|
},
|
||||||
|
radius: px(99.),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
TabVariant::Segmented => TabStyle {
|
TabVariant::Segmented => TabStyle {
|
||||||
fg: cx.theme().muted_foreground,
|
fg: cx.theme().muted_foreground,
|
||||||
bg: cx.theme().tab_bar,
|
bg: cx.theme().tab_bar,
|
||||||
|
|
@ -425,6 +458,12 @@ impl Tab {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use outline variant.
|
||||||
|
pub fn outline(mut self) -> Self {
|
||||||
|
self.variant = TabVariant::Outline;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Use Segmented variant.
|
/// Use Segmented variant.
|
||||||
pub fn segmented(mut self) -> Self {
|
pub fn segmented(mut self) -> Self {
|
||||||
self.variant = TabVariant::Segmented;
|
self.variant = TabVariant::Segmented;
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,12 @@ impl TabBar {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the Tab variant to Outline, all children will inherit the variant.
|
||||||
|
pub fn outline(mut self) -> Self {
|
||||||
|
self.variant = TabVariant::Outline;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the Tab variant to Segmented, all children will inherit the variant.
|
/// Set the Tab variant to Segmented, all children will inherit the variant.
|
||||||
pub fn segmented(mut self) -> Self {
|
pub fn segmented(mut self) -> Self {
|
||||||
self.variant = TabVariant::Segmented;
|
self.variant = TabVariant::Segmented;
|
||||||
|
|
@ -143,10 +149,14 @@ impl RenderOnce for TabBar {
|
||||||
let padding = Edges::all(px(0.));
|
let padding = Edges::all(px(0.));
|
||||||
(cx.theme().tab_bar, padding, px(0.))
|
(cx.theme().tab_bar, padding, px(0.))
|
||||||
}
|
}
|
||||||
TabVariant::Pill => {
|
TabVariant::Outline => {
|
||||||
let padding = Edges::all(px(0.));
|
let padding = Edges::all(px(0.));
|
||||||
(cx.theme().transparent, padding, default_gap)
|
(cx.theme().transparent, padding, default_gap)
|
||||||
}
|
}
|
||||||
|
TabVariant::Pill => {
|
||||||
|
let padding = Edges::all(px(0.));
|
||||||
|
(cx.theme().transparent, padding, px(4.))
|
||||||
|
}
|
||||||
TabVariant::Segmented => {
|
TabVariant::Segmented => {
|
||||||
let padding_x = match self.size {
|
let padding_x = match self.size {
|
||||||
Size::XSmall => px(3.),
|
Size::XSmall => px(3.),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue