feat: improve compose modal

This commit is contained in:
2025-01-20 15:49:21 +07:00
parent 8f6bedf70a
commit 5f6ba4f0a6
20 changed files with 245 additions and 117 deletions

View File

@@ -345,15 +345,16 @@ impl RenderOnce for Button {
Size::Size(px) => this.size(px),
Size::XSmall => this.size_5(),
Size::Small => this.size_6(),
Size::Large | Size::Medium => this.size_8(),
Size::Medium => this.size_8(),
Size::Large => this.size_9(),
}
} else {
// Normal Button
match self.size {
Size::Size(size) => this.px(size * 0.2),
Size::XSmall => this.h_6().px_0p5(),
Size::Small => this.h_8().px_2(),
_ => this.h_9().px_3(),
Size::Small => this.h_7().px_2(),
_ => this.h_8().px_3(),
}
}
})
@@ -487,7 +488,14 @@ impl ButtonVariant {
fn text_color(&self, cx: &WindowContext) -> Hsla {
match self {
ButtonVariant::Primary => cx.theme().base.step(cx, ColorScaleStep::TWELVE),
ButtonVariant::Primary => match cx.theme().accent.name().to_string().as_str() {
"Sky" => cx.theme().base.darken(cx),
"Mint" => cx.theme().base.darken(cx),
"Lime" => cx.theme().base.darken(cx),
"Amber" => cx.theme().base.darken(cx),
"Yellow" => cx.theme().base.darken(cx),
_ => cx.theme().accent.step(cx, ColorScaleStep::ONE),
},
ButtonVariant::Link => cx.theme().accent.step(cx, ColorScaleStep::NINE),
ButtonVariant::Custom(colors) => colors.foreground,
_ => cx.theme().base.step(cx, ColorScaleStep::TWELVE),
@@ -535,7 +543,7 @@ impl ButtonVariant {
fn hovered(&self, cx: &WindowContext) -> ButtonVariantStyle {
let bg = match self {
ButtonVariant::Primary => cx.theme().accent.step(cx, ColorScaleStep::TEN),
ButtonVariant::Ghost => cx.theme().base.step(cx, ColorScaleStep::FOUR),
ButtonVariant::Ghost => cx.theme().base.step(cx, ColorScaleStep::THREE),
ButtonVariant::Link => cx.theme().transparent,
ButtonVariant::Text => cx.theme().transparent,
ButtonVariant::Custom(colors) => colors.hover,
@@ -560,7 +568,7 @@ impl ButtonVariant {
fn active(&self, cx: &WindowContext) -> ButtonVariantStyle {
let bg = match self {
ButtonVariant::Primary => cx.theme().accent.step(cx, ColorScaleStep::TEN),
ButtonVariant::Ghost => cx.theme().base.step(cx, ColorScaleStep::FOUR),
ButtonVariant::Ghost => cx.theme().base.step(cx, ColorScaleStep::THREE),
ButtonVariant::Link => cx.theme().transparent,
ButtonVariant::Text => cx.theme().transparent,
ButtonVariant::Custom(colors) => colors.active,
@@ -588,7 +596,7 @@ impl ButtonVariant {
fn selected(&self, cx: &WindowContext) -> ButtonVariantStyle {
let bg = match self {
ButtonVariant::Primary => cx.theme().accent.step(cx, ColorScaleStep::TEN),
ButtonVariant::Ghost => cx.theme().base.step(cx, ColorScaleStep::FOUR),
ButtonVariant::Ghost => cx.theme().base.step(cx, ColorScaleStep::THREE),
ButtonVariant::Link => cx.theme().transparent,
ButtonVariant::Text => cx.theme().transparent,
ButtonVariant::Custom(colors) => colors.active,
@@ -618,7 +626,7 @@ impl ButtonVariant {
ButtonVariant::Link | ButtonVariant::Ghost | ButtonVariant::Text => {
cx.theme().transparent
}
_ => cx.theme().base.step(cx, ColorScaleStep::FOUR),
_ => cx.theme().base.step(cx, ColorScaleStep::THREE),
};
let fg = cx.theme().base.step(cx, ColorScaleStep::ELEVEN);

View File

@@ -60,7 +60,7 @@ impl Render for DragPanel {
.rounded(px(cx.theme().radius))
.text_xs()
.border_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.border_color(cx.theme().base.step(cx, ColorScaleStep::SIX))
.bg(cx.theme().base.step(cx, ColorScaleStep::TWO))
.child(self.panel.title(cx))
}
@@ -577,7 +577,7 @@ impl TabPanel {
.border_r_1()
.border_b_1()
.h_full()
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
.bg(cx.theme().base.step(cx, ColorScaleStep::TWO))
.px_2()
.children(left_dock_button)
@@ -616,7 +616,7 @@ impl TabPanel {
this.rounded_l_none()
.border_l_2()
.border_r_0()
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
})
.on_drop(cx.listener(
move |this, drag: &DragPanel, cx| {
@@ -661,7 +661,7 @@ impl TabPanel {
.border_l_1()
.border_b_1()
.h_full()
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
.bg(cx.theme().base.step(cx, ColorScaleStep::TWO))
.px_2()
.gap_1()

View File

@@ -602,7 +602,7 @@ where
.justify_between()
.bg(cx.theme().background)
.border_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::FOUR))
.border_color(cx.theme().base.step(cx, ColorScaleStep::SIX))
.rounded(px(cx.theme().radius))
.when(cx.theme().shadow, |this| this.shadow_sm())
.map(|this| {
@@ -695,7 +695,7 @@ where
.bg(cx.theme().background)
.border_1()
.border_color(
cx.theme().base.step(cx, ColorScaleStep::FOUR),
cx.theme().base.step(cx, ColorScaleStep::SEVEN),
)
.rounded(px(cx.theme().radius))
.shadow_md()

View File

@@ -1390,9 +1390,9 @@ impl Render for TextInput {
.when(self.multi_line, |this| this.h_auto())
.when(self.appearance, |this| {
this.bg(if self.disabled {
cx.theme().base.step(cx, ColorScaleStep::FOUR)
cx.theme().transparent
} else {
cx.theme().background
cx.theme().base.step(cx, ColorScaleStep::THREE)
})
.rounded(px(cx.theme().radius))
.when(cx.theme().shadow, |this| this.shadow_sm())

View File

@@ -5,8 +5,8 @@ use crate::{
v_flex, ContextModal, IconName, Sizable as _, StyledExt,
};
use gpui::{
actions, anchored, div, hsla, point, prelude::FluentBuilder, px, relative, Animation,
AnimationExt as _, AnyElement, AppContext, Bounds, ClickEvent, Div, FocusHandle, Hsla,
actions, anchored, div, point, prelude::FluentBuilder, px, relative, Animation,
AnimationExt as _, AnyElement, AppContext, Bounds, ClickEvent, Div, FocusHandle,
InteractiveElement, IntoElement, KeyBinding, MouseButton, ParentElement, Pixels, Point,
RenderOnce, SharedString, Styled, WindowContext,
};
@@ -33,24 +33,11 @@ pub struct Modal {
margin_top: Option<Pixels>,
on_close: OnClose,
show_close: bool,
overlay: bool,
keyboard: bool,
/// This will be change when open the modal, the focus handle is create when open the modal.
pub(crate) focus_handle: FocusHandle,
pub(crate) layer_ix: usize,
pub(crate) overlay_visible: bool,
}
pub(crate) fn overlay_color(overlay: bool, cx: &WindowContext) -> Hsla {
if !overlay {
return hsla(0., 0., 0., 0.);
}
if cx.theme().appearance.is_dark() {
hsla(0., 1., 1., 0.06)
} else {
hsla(0., 0., 0., 0.06)
}
pub(crate) overlay: bool,
}
impl Modal {
@@ -58,12 +45,10 @@ impl Modal {
let base = v_flex()
.bg(cx.theme().background)
.border_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
.rounded_lg()
.shadow_xl()
.min_h_48()
.p_4()
.gap_4();
.min_h_48();
Self {
base,
@@ -77,7 +62,6 @@ impl Modal {
overlay: true,
keyboard: true,
layer_ix: 0,
overlay_visible: true,
on_close: Rc::new(|_, _| {}),
show_close: true,
}
@@ -171,8 +155,8 @@ impl RenderOnce for Modal {
origin: Point::default(),
size: view_size,
};
let offset_top = px(layer_ix as f32 * 16.);
let y = self.margin_top.unwrap_or(view_size.height / 10.) + offset_top;
let offset_top = px(layer_ix as f32 * 2.);
let y = self.margin_top.unwrap_or(view_size.height / 16.) + offset_top;
let x = bounds.center().x - self.width / 2.;
anchored()
@@ -183,8 +167,8 @@ impl RenderOnce for Modal {
.occlude()
.w(view_size.width)
.h(view_size.height)
.when(self.overlay_visible, |this| {
this.bg(overlay_color(self.overlay, cx))
.when(self.overlay, |this| {
this.bg(cx.theme().base.step_alpha(cx, ColorScaleStep::EIGHT))
})
.on_mouse_down(MouseButton::Left, {
let on_close = self.on_close.clone();
@@ -221,6 +205,10 @@ impl RenderOnce for Modal {
.when_some(self.title, |this, title| {
this.child(
div()
.flex()
.items_center()
.h_10()
.px_2()
.text_sm()
.font_semibold()
.line_height(relative(1.))

View File

@@ -228,7 +228,7 @@ impl Render for Notification {
.relative()
.w_96()
.border_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
.bg(cx.theme().background)
.rounded_md()
.shadow_md()

View File

@@ -65,7 +65,7 @@ impl RenderOnce for ResizeHandle {
})
.child(
div()
.bg(cx.theme().base.step(cx, ColorScaleStep::THREE))
.bg(cx.theme().base.step(cx, ColorScaleStep::FIVE))
.when(self.axis.is_horizontal(), |this| {
this.h_full().w(HANDLE_SIZE)
})

View File

@@ -239,7 +239,7 @@ impl Root {
// Keep only have one overlay, we only render the first modal with overlay.
if has_overlay {
modal.overlay_visible = false;
modal.overlay = false;
}
if modal.has_overlay() {
has_overlay = true;

View File

@@ -66,7 +66,7 @@ pub trait StyledExt: Styled + Sized {
fn popover_style(self, cx: &mut WindowContext) -> Self {
self.bg(cx.theme().background)
.border_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::FOUR))
.border_color(cx.theme().base.step(cx, ColorScaleStep::SIX))
.shadow_lg()
.rounded_lg()
}

View File

@@ -113,7 +113,7 @@ impl Element for Switch {
theme.accent.step(cx, ColorScaleStep::NINE),
theme.background,
),
false => (theme.base.step(cx, ColorScaleStep::FOUR), theme.background),
false => (theme.base.step(cx, ColorScaleStep::THREE), theme.background),
};
let (bg, toggle_bg) = match self.disabled {

View File

@@ -118,7 +118,7 @@ impl RenderOnce for Tab {
.border_x_1()
.border_color(cx.theme().transparent)
.when(self.selected, |this| {
this.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
this.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
})
.when(!self.selected, |this| {
this.child(
@@ -128,7 +128,7 @@ impl RenderOnce for Tab {
.bottom_0()
.size_full()
.border_b_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE)),
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE)),
)
})
.when_some(self.prefix, |this, prefix| {

View File

@@ -79,7 +79,7 @@ impl RenderOnce for TabBar {
.bottom_0()
.size_full()
.border_b_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE)),
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE)),
)
.when_some(self.prefix, |this, prefix| this.child(prefix))
.child(

View File

@@ -11,7 +11,7 @@ pub mod colors;
pub mod scale;
#[derive(Debug, Clone, Copy, Default)]
pub struct ThemeColors {
pub struct SystemColors {
pub background: Hsla,
pub transparent: Hsla,
pub scrollbar: Hsla,
@@ -21,7 +21,7 @@ pub struct ThemeColors {
pub danger: Hsla,
}
impl ThemeColors {
impl SystemColors {
pub fn light() -> Self {
Self {
background: hsl(0.0, 0.0, 100.),
@@ -93,7 +93,7 @@ impl Appearance {
}
pub struct Theme {
colors: ThemeColors,
colors: SystemColors,
/// Base colors.
pub base: ColorScaleSet,
/// Accent colors.
@@ -109,7 +109,7 @@ pub struct Theme {
}
impl Deref for Theme {
type Target = ThemeColors;
type Target = SystemColors;
fn deref(&self) -> &Self::Target {
&self.colors
@@ -159,8 +159,8 @@ impl Theme {
fn new(appearance: Appearance) -> Self {
let color_scales = default_color_scales();
let colors = match appearance {
Appearance::Light => ThemeColors::light(),
Appearance::Dark => ThemeColors::dark(),
Appearance::Light => SystemColors::light(),
Appearance::Dark => SystemColors::dark(),
};
Theme {
@@ -174,7 +174,7 @@ impl Theme {
} else {
"FreeMono".into()
},
radius: 6.0,
radius: 5.0,
shadow: false,
scrollbar_show: ScrollbarShow::default(),
appearance,

View File

@@ -292,4 +292,11 @@ impl ColorScaleSet {
Appearance::Dark => self.dark_alpha.step(step),
}
}
pub fn darken(&self, cx: &AppContext) -> Hsla {
match cx.theme().appearance {
Appearance::Light => self.light.step_12(),
Appearance::Dark => self.dark.step_1(),
}
}
}

View File

@@ -252,7 +252,7 @@ impl RenderOnce for TitleBar {
.justify_between()
.h(HEIGHT)
.border_b_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
.bg(cx.theme().base.step(cx, ColorScaleStep::ONE))
.when(cx.is_fullscreen(), |this| this.pl(px(12.)))
.on_double_click(|_, cx| cx.zoom_window())