badge: Add new component (#540)
<img width="137" alt="image" src="https://github.com/user-attachments/assets/6d7008b2-fe0f-4c4e-bd16-1dd8ae883f11" /> <img width="118" alt="image" src="https://github.com/user-attachments/assets/3137dd88-5038-4c59-90c1-cee2cdc542bd" />
This commit is contained in:
parent
2aad7e412a
commit
31736b0e21
3 changed files with 104 additions and 29 deletions
|
|
@ -10,10 +10,10 @@ use story::{
|
|||
TooltipStory,
|
||||
};
|
||||
use ui::{
|
||||
badge::Badge,
|
||||
button::{Button, ButtonVariants as _},
|
||||
color_picker::{ColorPicker, ColorPickerEvent},
|
||||
dock::{DockArea, DockAreaState, DockEvent, DockItem, DockPlacement},
|
||||
h_flex,
|
||||
popup_menu::PopupMenuExt,
|
||||
scroll::ScrollbarShow,
|
||||
theme::{ActiveTheme, Theme},
|
||||
|
|
@ -553,41 +553,28 @@ impl Render for StoryWorkspace {
|
|||
.child(self.locale_selector.clone())
|
||||
.child(self.font_size_selector.clone())
|
||||
.child(
|
||||
Button::new("github")
|
||||
.icon(IconName::GitHub)
|
||||
.small()
|
||||
.ghost()
|
||||
.on_click(|_, cx| {
|
||||
cx.open_url("https://github.com/longbridge/gpui-component")
|
||||
}),
|
||||
Badge::new().dot().count(1).child(
|
||||
Button::new("github")
|
||||
.icon(IconName::GitHub)
|
||||
.small()
|
||||
.ghost()
|
||||
.on_click(|_, cx| {
|
||||
cx.open_url(
|
||||
"https://github.com/longbridge/gpui-component",
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.relative()
|
||||
.child(
|
||||
div().relative().child(
|
||||
Badge::new().count(notifications_count).max(99).child(
|
||||
Button::new("bell")
|
||||
.small()
|
||||
.ghost()
|
||||
.compact()
|
||||
.icon(IconName::Bell),
|
||||
)
|
||||
.when(notifications_count > 0, |this| {
|
||||
this.child(
|
||||
h_flex()
|
||||
.absolute()
|
||||
.rounded_full()
|
||||
.top(px(-2.))
|
||||
.right(px(-2.))
|
||||
.p(px(1.))
|
||||
.min_w(px(12.))
|
||||
.bg(ui::red_500())
|
||||
.text_color(ui::white())
|
||||
.justify_center()
|
||||
.text_size(px(10.))
|
||||
.line_height(relative(1.))
|
||||
.child(format!("{}", notifications_count.min(99))),
|
||||
)
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
87
crates/ui/src/badge.rs
Normal file
87
crates/ui/src/badge.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
use gpui::{
|
||||
div, prelude::FluentBuilder, px, relative, AnyElement, Div, IntoElement, ParentElement,
|
||||
RenderOnce, Styled, WindowContext,
|
||||
};
|
||||
|
||||
use crate::{h_flex, red_500, white};
|
||||
|
||||
#[derive(Default)]
|
||||
enum BadgeStyle {
|
||||
Dot,
|
||||
#[default]
|
||||
Number,
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct Badge {
|
||||
base: Div,
|
||||
count: usize,
|
||||
max: usize,
|
||||
style: BadgeStyle,
|
||||
}
|
||||
|
||||
impl Badge {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
base: div(),
|
||||
count: 0,
|
||||
max: 99,
|
||||
style: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dot(mut self) -> Self {
|
||||
self.style = BadgeStyle::Dot;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn count(mut self, count: usize) -> Self {
|
||||
self.count = count;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn max(mut self, max: usize) -> Self {
|
||||
self.max = max;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl ParentElement for Badge {
|
||||
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
|
||||
self.base.extend(elements);
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for Badge {
|
||||
fn render(self, _: &mut WindowContext) -> impl IntoElement {
|
||||
self.base.relative().when(self.count > 0, |this| {
|
||||
this.child(
|
||||
h_flex()
|
||||
.absolute()
|
||||
.justify_center()
|
||||
.rounded_full()
|
||||
.bg(red_500())
|
||||
.map(|this| match self.style {
|
||||
BadgeStyle::Dot => this.top(px(0.)).right(px(0.)).size(px(6.)),
|
||||
BadgeStyle::Number => {
|
||||
let count = if self.count > self.max {
|
||||
format!("{}+", self.max)
|
||||
} else {
|
||||
self.count.to_string()
|
||||
};
|
||||
|
||||
this.top(px(-2.))
|
||||
.right_neg_1p5()
|
||||
.py_0p5()
|
||||
.px_0p5()
|
||||
.min_w_3p5()
|
||||
.text_color(white())
|
||||
.text_size(px(10.))
|
||||
.line_height(relative(1.))
|
||||
.child(count)
|
||||
}
|
||||
}),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ mod window_border;
|
|||
|
||||
pub mod accordion;
|
||||
pub mod animation;
|
||||
pub mod badge;
|
||||
pub mod breadcrumb;
|
||||
pub mod button;
|
||||
pub mod button_group;
|
||||
|
|
|
|||
Loading…
Reference in a new issue