Add icon support to Button.
This commit is contained in:
parent
a5aea36f75
commit
3c4891cb69
4 changed files with 71 additions and 29 deletions
|
|
@ -5,12 +5,12 @@ use gpui::{
|
||||||
|
|
||||||
use ui::{
|
use ui::{
|
||||||
button::{Button, ButtonSize, ButtonStyle},
|
button::{Button, ButtonSize, ButtonStyle},
|
||||||
h_flex, v_flex, Clickable, Disableable as _,
|
h_flex, v_flex, Clickable, Disableable as _, Icon, IconName,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::story_case;
|
use super::story_case;
|
||||||
|
|
||||||
pub struct ButtonStory;
|
pub struct ButtonStory {}
|
||||||
|
|
||||||
impl ButtonStory {
|
impl ButtonStory {
|
||||||
fn on_click(ev: &ClickEvent, _: &mut WindowContext) {
|
fn on_click(ev: &ClickEvent, _: &mut WindowContext) {
|
||||||
|
|
@ -26,6 +26,7 @@ impl Render for ButtonStory {
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
|
.w_full()
|
||||||
.justify_start()
|
.justify_start()
|
||||||
.gap_6()
|
.gap_6()
|
||||||
.child(
|
.child(
|
||||||
|
|
@ -48,6 +49,28 @@ impl Render for ButtonStory {
|
||||||
.on_click(Self::on_click),
|
.on_click(Self::on_click),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.gap_6()
|
||||||
|
.child(
|
||||||
|
Button::new("button-icon-1", "Confirm")
|
||||||
|
.icon(IconName::Check)
|
||||||
|
.style(ButtonStyle::Primary)
|
||||||
|
.on_click(Self::on_click),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("button-icon-2", "Abort")
|
||||||
|
.icon(IconName::Close)
|
||||||
|
.style(ButtonStyle::Secondary)
|
||||||
|
.on_click(Self::on_click),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("button-icon-3", "Maximize")
|
||||||
|
.icon(Icon::new(IconName::Maximize))
|
||||||
|
.style(ButtonStyle::Secondary)
|
||||||
|
.on_click(Self::on_click),
|
||||||
|
),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, prelude::FluentBuilder as _, px, ClickEvent, DefiniteLength, Div, ElementId, Hsla,
|
div, prelude::FluentBuilder as _, px, AnyElement, ClickEvent, DefiniteLength, Div, ElementId,
|
||||||
InteractiveElement, IntoElement, MouseButton, ParentElement, RenderOnce, SharedString,
|
Hsla, InteractiveElement, IntoElement, MouseButton, ParentElement, RenderOnce, SharedString,
|
||||||
StatefulInteractiveElement as _, Styled, WindowContext,
|
StatefulInteractiveElement as _, Styled, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
span,
|
h_flex, span,
|
||||||
theme::{ActiveTheme, Colorize as _, ThemeMode},
|
theme::{ActiveTheme, Colorize as _, ThemeMode},
|
||||||
Clickable, Disableable, Selectable,
|
Clickable, Disableable, Icon, IconName, Selectable,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum ButtonRounded {
|
pub enum ButtonRounded {
|
||||||
|
|
@ -17,11 +17,13 @@ pub enum ButtonRounded {
|
||||||
Large,
|
Large,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub enum ButtonSize {
|
pub enum ButtonSize {
|
||||||
Small,
|
Small,
|
||||||
Medium,
|
Medium,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub enum ButtonStyle {
|
pub enum ButtonStyle {
|
||||||
Primary,
|
Primary,
|
||||||
Secondary,
|
Secondary,
|
||||||
|
|
@ -32,6 +34,7 @@ pub enum ButtonStyle {
|
||||||
pub struct Button {
|
pub struct Button {
|
||||||
pub base: Div,
|
pub base: Div,
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
|
icon: Option<Icon>,
|
||||||
label: SharedString,
|
label: SharedString,
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
|
|
@ -49,6 +52,7 @@ impl Button {
|
||||||
Self {
|
Self {
|
||||||
base: div(),
|
base: div(),
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
|
icon: None,
|
||||||
label: label.into(),
|
label: label.into(),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
|
|
@ -82,6 +86,11 @@ impl Button {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
|
||||||
|
self.icon = Some(icon.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tooltip(mut self, tooltip: impl Into<SharedString>) -> Self {
|
pub fn tooltip(mut self, tooltip: impl Into<SharedString>) -> Self {
|
||||||
self.tooltip = Some(tooltip.into());
|
self.tooltip = Some(tooltip.into());
|
||||||
self
|
self
|
||||||
|
|
@ -175,9 +184,15 @@ impl RenderOnce for Button {
|
||||||
normal_style.fg
|
normal_style.fg
|
||||||
};
|
};
|
||||||
|
|
||||||
span()
|
h_flex()
|
||||||
.child(self.label)
|
.items_center()
|
||||||
|
.justify_center()
|
||||||
|
.gap_2()
|
||||||
.text_color(text_color)
|
.text_color(text_color)
|
||||||
|
.when_some(self.icon, |this, icon| {
|
||||||
|
this.child(icon.text_color(text_color))
|
||||||
|
})
|
||||||
|
.child(self.label)
|
||||||
.map(|this| match self.size {
|
.map(|this| match self.size {
|
||||||
ButtonSize::Small => this.text_sm(),
|
ButtonSize::Small => this.text_sm(),
|
||||||
ButtonSize::Medium => this.text_base(),
|
ButtonSize::Medium => this.text_base(),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
use gpui::{svg, IntoElement, RenderOnce, SharedString, Styled, Svg, WindowContext};
|
use gpui::{
|
||||||
|
div, rgb, svg, Div, InteractiveElement, IntoElement, ParentElement as _, RenderOnce,
|
||||||
|
SharedString, StyleRefinement, Styled, Svg, TextStyle, TextStyleRefinement, WindowContext,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::theme::ActiveTheme;
|
use crate::theme::ActiveTheme;
|
||||||
|
|
||||||
|
|
@ -30,6 +33,12 @@ impl IconName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<Icon> for IconName {
|
||||||
|
fn into(self) -> Icon {
|
||||||
|
Icon::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RenderOnce for IconName {
|
impl RenderOnce for IconName {
|
||||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||||
Icon::new(self)
|
Icon::new(self)
|
||||||
|
|
@ -42,16 +51,10 @@ pub struct Icon {
|
||||||
path: SharedString,
|
path: SharedString,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Styled for Icon {
|
|
||||||
fn style(&mut self) -> &mut gpui::StyleRefinement {
|
|
||||||
self.base.style()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Icon {
|
impl Icon {
|
||||||
pub fn new(name: IconName) -> Self {
|
pub fn new(name: IconName) -> Self {
|
||||||
Self {
|
Self {
|
||||||
base: svg().flex_none().size_4(),
|
base: svg().flex_none().size_4().text_color(rgb(0x000000)),
|
||||||
path: name.path(),
|
path: name.path(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,8 +68,14 @@ impl Icon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderOnce for Icon {
|
impl Styled for Icon {
|
||||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
fn style(&mut self) -> &mut StyleRefinement {
|
||||||
self.base.text_color(cx.theme().foreground).path(self.path)
|
self.base.style()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderOnce for Icon {
|
||||||
|
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||||
|
self.base.path(self.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,7 @@ use gpui::{
|
||||||
SharedString, Styled, ViewContext, VisualContext, WindowContext,
|
SharedString, Styled, ViewContext, VisualContext, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{h_flex, styled_ext::ElevationIndex, theme::ActiveTheme, v_flex};
|
||||||
h_flex,
|
|
||||||
styled_ext::ElevationIndex,
|
|
||||||
theme::{ActiveTheme, Colorize},
|
|
||||||
v_flex,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Tooltip {
|
pub struct Tooltip {
|
||||||
title: SharedString,
|
title: SharedString,
|
||||||
|
|
@ -64,13 +59,13 @@ pub fn tooltip_container<V>(
|
||||||
// padding to avoid tooltip appearing right below the mouse cursor
|
// padding to avoid tooltip appearing right below the mouse cursor
|
||||||
div().pl_2().pt_2p5().child(
|
div().pl_2().pt_2p5().child(
|
||||||
v_flex()
|
v_flex()
|
||||||
.bg(cx.theme().popover.invert_l())
|
.bg(cx.theme().popover)
|
||||||
.rounded(px(8.))
|
.rounded(px(8.))
|
||||||
.border_1()
|
.border_1()
|
||||||
.border_color(cx.theme().border.invert_l())
|
.border_color(cx.theme().border)
|
||||||
.shadow(ElevationIndex::ElevatedSurface.shadow())
|
.shadow(ElevationIndex::ElevatedSurface.shadow())
|
||||||
.text_color(cx.theme().background)
|
.text_color(cx.theme().popover_foreground)
|
||||||
.py_1()
|
.py_1p5()
|
||||||
.px_2()
|
.px_2()
|
||||||
.map(|el| f(el, cx)),
|
.map(|el| f(el, cx)),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue