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

@@ -126,7 +126,7 @@ impl ChatRegistry {
let id = room_hash(&ev.tags);
// Filter all seen events
if !hashes.iter().any(|h| h == &id) {
Some(cx.new_model(|_| Room::new(&ev)))
Some(cx.new_model(|_| Room::parse(&ev)))
} else {
None
}
@@ -170,7 +170,7 @@ impl ChatRegistry {
cx.notify();
})
} else {
let room = cx.new_model(|_| Room::new(&event));
let room = cx.new_model(|_| Room::parse(&event));
self.inbox.update(cx, |this, cx| {
this.rooms.insert(0, room);

View File

@@ -68,7 +68,27 @@ pub struct Room {
}
impl Room {
pub fn new(event: &Event) -> Self {
pub fn new(
id: u64,
owner: Member,
members: Vec<Member>,
title: Option<SharedString>,
last_seen: Timestamp,
) -> Self {
let is_group = members.len() > 1;
Self {
id,
owner,
members,
title,
last_seen,
is_group,
new_messages: vec![],
}
}
pub fn parse(event: &Event) -> Room {
let id = room_hash(&event.tags);
let last_seen = event.created_at;
@@ -89,17 +109,7 @@ impl Room {
Some(name.into())
};
let is_group = members.len() > 1;
Self {
id,
owner,
members,
title,
last_seen,
is_group,
new_messages: vec![],
}
Self::new(id, owner, members, title, last_seen)
}
pub fn set_metadata(&mut self, public_key: PublicKey, metadata: Metadata) {

View File

@@ -501,7 +501,7 @@ impl Render for ChatPanel {
div()
.flex_1()
.flex()
.bg(cx.theme().base.step(cx, ColorScaleStep::FOUR))
.bg(cx.theme().base.step(cx, ColorScaleStep::THREE))
.rounded(px(cx.theme().radius))
.px_2()
.child(self.input.clone()),

View File

@@ -6,13 +6,14 @@ use gpui::{
};
use nostr_sdk::prelude::*;
use serde::Deserialize;
use std::collections::HashSet;
use std::{collections::HashSet, time::Duration};
use ui::{
button::{Button, ButtonRounded},
indicator::Indicator,
input::TextInput,
input::{InputEvent, TextInput},
prelude::FluentBuilder,
theme::{scale::ColorScaleStep, ActiveTheme},
Icon, IconName, Sizable, StyledExt,
Icon, IconName, Sizable, Size, StyledExt,
};
#[derive(Clone, PartialEq, Eq, Deserialize)]
@@ -21,24 +22,48 @@ struct SelectContact(PublicKey);
impl_internal_actions!(contacts, [SelectContact]);
pub struct Compose {
input: View<TextInput>,
title_input: View<TextInput>,
message_input: View<TextInput>,
user_input: View<TextInput>,
contacts: Model<Option<Vec<Member>>>,
selected: Model<HashSet<PublicKey>>,
focus_handle: FocusHandle,
is_loading: bool,
}
impl Compose {
pub fn new(cx: &mut ViewContext<'_, Self>) -> Self {
let contacts = cx.new_model(|_| None);
let selected = cx.new_model(|_| HashSet::new());
let input = cx.new_view(|cx| {
let user_input = cx.new_view(|cx| {
TextInput::new(cx)
.text_size(ui::Size::Small)
.small()
.placeholder("npub1...")
});
let title_input = cx.new_view(|cx| {
TextInput::new(cx)
.appearance(false)
.text_size(ui::Size::Small)
.placeholder("npub1...")
.cleanable()
.text_size(Size::XSmall)
.placeholder("Family...")
});
let message_input = cx.new_view(|cx| {
TextInput::new(cx)
.appearance(false)
.text_size(Size::XSmall)
.placeholder("Hello...")
});
cx.subscribe(&user_input, move |this, _, input_event, cx| {
if let InputEvent::PressEnter = input_event {
this.add(cx);
}
})
.detach();
cx.spawn(|this, mut async_cx| {
let client = get_client();
@@ -75,9 +100,12 @@ impl Compose {
.detach();
Self {
input,
title_input,
message_input,
user_input,
contacts,
selected,
is_loading: false,
focus_handle: cx.focus_handle(),
}
}
@@ -86,6 +114,61 @@ impl Compose {
self.selected.read(cx).iter().collect()
}
fn add(&mut self, cx: &mut ViewContext<Self>) {
let content = self.user_input.read(cx).text().to_string();
let input = self.user_input.downgrade();
// Show loading spinner
self.is_loading = true;
cx.notify();
if let Ok(public_key) = PublicKey::parse(&content) {
cx.spawn(|this, mut async_cx| async move {
let query: anyhow::Result<Metadata, anyhow::Error> = async_cx
.background_executor()
.spawn(async move {
let client = get_client();
let metadata = client
.fetch_metadata(public_key, Duration::from_secs(3))
.await?;
Ok(metadata)
})
.await;
if let Ok(metadata) = query {
if let Some(view) = this.upgrade() {
_ = async_cx.update_view(&view, |this, cx| {
this.contacts.update(cx, |this, cx| {
if let Some(members) = this {
members.insert(0, Member::new(public_key, metadata));
}
cx.notify();
});
this.selected.update(cx, |this, cx| {
this.insert(public_key);
cx.notify();
});
this.is_loading = false;
cx.notify();
});
}
if let Some(input) = input.upgrade() {
_ = async_cx.update_view(&input, |input, cx| {
input.set_text("", cx);
});
}
}
})
.detach();
} else {
// Handle error
}
}
fn on_action_select(&mut self, action: &SelectContact, cx: &mut ViewContext<Self>) {
self.selected.update(cx, |this, cx| {
if this.contains(&action.0) {
@@ -95,8 +178,6 @@ impl Compose {
};
cx.notify();
});
// TODO
}
}
@@ -110,33 +191,66 @@ impl Render for Compose {
.on_action(cx.listener(Self::on_action_select))
.flex()
.flex_col()
.gap_3()
.gap_1()
.child(
div()
.px_2()
.text_xs()
.text_color(cx.theme().base.step(cx, ColorScaleStep::ELEVEN))
.child(msg),
)
.child(
div()
.flex()
.flex_col()
.gap_2()
.child(
div()
.text_xs()
.text_color(cx.theme().base.step(cx, ColorScaleStep::ELEVEN))
.child(msg),
.h_10()
.px_2()
.border_b_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
.flex()
.items_center()
.gap_1()
.child(div().text_xs().font_semibold().child("Title:"))
.child(self.title_input.clone()),
)
.child(
div()
.bg(cx.theme().base.step(cx, ColorScaleStep::FOUR))
.rounded(px(cx.theme().radius))
.h_10()
.px_2()
.child(self.input.clone()),
.border_b_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
.flex()
.items_center()
.gap_1()
.child(div().text_xs().font_semibold().child("Message:"))
.child(self.message_input.clone()),
),
)
.child(
div()
.flex()
.flex_col()
.gap_1()
.child(div().text_xs().font_semibold().child("Contacts"))
.child(div().map(|this| {
.gap_2()
.child(div().px_2().text_xs().font_semibold().child("To:"))
.child(
div()
.flex()
.items_center()
.gap_2()
.px_2()
.child(
Button::new("add")
.icon(IconName::Plus)
.small()
.rounded(ButtonRounded::Size(px(9999.)))
.loading(self.is_loading)
.on_click(cx.listener(|this, _, cx| this.add(cx))),
)
.child(self.user_input.clone()),
)
.map(|this| {
if let Some(contacts) = self.contacts.read(cx).clone() {
this.child(
uniform_list(
@@ -155,9 +269,8 @@ impl Render for Compose {
div()
.id(ix)
.w_full()
.h_10()
.px_1p5()
.rounded(px(cx.theme().radius))
.h_9()
.px_2()
.flex()
.items_center()
.justify_between()
@@ -166,10 +279,10 @@ impl Render for Compose {
.flex()
.items_center()
.gap_2()
.text_sm()
.text_xs()
.child(
div().flex_shrink_0().child(
img(item.avatar()).size_8(),
img(item.avatar()).size_6(),
),
)
.child(item.name()),
@@ -177,7 +290,7 @@ impl Render for Compose {
.when(is_select, |this| {
this.child(
Icon::new(IconName::CircleCheck)
.size_4()
.size_3()
.text_color(cx.theme().base.step(
cx,
ColorScaleStep::TWELVE,
@@ -188,13 +301,7 @@ impl Render for Compose {
this.bg(cx
.theme()
.base
.step(cx, ColorScaleStep::FOUR))
.text_color(
cx.theme().base.step(
cx,
ColorScaleStep::ELEVEN,
),
)
.step(cx, ColorScaleStep::THREE))
})
.on_click(move |_, cx| {
cx.dispatch_action(Box::new(
@@ -207,7 +314,7 @@ impl Render for Compose {
items
},
)
.h(px(320.)),
.h(px(300.)),
)
} else {
this.flex()
@@ -216,7 +323,7 @@ impl Render for Compose {
.h_16()
.child(Indicator::new().small())
}
})),
}),
)
}
}

View File

@@ -1,7 +1,7 @@
use crate::views::sidebar::inbox::Inbox;
use compose::Compose;
use gpui::{
AnyElement, AppContext, Entity, EntityId, EventEmitter, FocusHandle, FocusableView,
div, px, AnyElement, AppContext, Entity, EntityId, EventEmitter, FocusHandle, FocusableView,
IntoElement, ParentElement, Render, SharedString, Styled, View, ViewContext, VisualContext,
WindowContext,
};
@@ -13,6 +13,7 @@ use ui::{
},
popup_menu::PopupMenu,
scroll::ScrollbarAxis,
theme::{scale::ColorScaleStep, ActiveTheme},
v_flex, ContextModal, Icon, IconName, Sizable, StyledExt,
};
@@ -61,14 +62,21 @@ impl Sidebar {
modal
.title("Direct Messages")
.width(px(420.))
.child(compose.clone())
.footer(
Button::new("create")
.label(label)
.primary()
.bold()
.rounded(ButtonRounded::Large)
.w_full(),
div()
.p_2()
.border_t_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
.child(
Button::new("create")
.label(label)
.primary()
.bold()
.rounded(ButtonRounded::Large)
.w_full(),
),
)
})
}
@@ -125,7 +133,7 @@ impl Render for Sidebar {
.ghost()
.not_centered()
.icon(Icon::new(IconName::ComposeFill))
.label("New Message")
.label("Compose")
.on_click(cx.listener(|this, _, cx| this.show_compose(cx))),
),
)

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())