wip: design

This commit is contained in:
2025-01-14 12:08:06 +07:00
parent 8be41c9bfa
commit e8b34ae69e
36 changed files with 302 additions and 532 deletions

View File

@@ -20,7 +20,7 @@ pub enum BadgeVariant {
impl BadgeVariant {
fn bg(&self, cx: &gpui::WindowContext) -> Hsla {
match self {
Self::Primary => cx.theme().primary,
Self::Primary => cx.theme().colors.primary,
Self::Secondary => cx.theme().secondary,
Self::Outline => gpui::transparent_black(),
Self::Destructive => cx.theme().danger,
@@ -30,7 +30,7 @@ impl BadgeVariant {
fn border(&self, cx: &gpui::WindowContext) -> Hsla {
match self {
Self::Primary => cx.theme().primary,
Self::Primary => cx.theme().colors.primary,
Self::Secondary => cx.theme().secondary,
Self::Outline => cx.theme().border,
Self::Destructive => cx.theme().danger,

View File

@@ -1,6 +1,6 @@
use crate::{
indicator::Indicator,
theme::{ActiveTheme, Colorize as _},
theme::{scale::ColorScaleStep, ActiveTheme, Colorize as _},
tooltip::Tooltip,
Disableable, Icon, Selectable, Sizable, Size, StyledExt,
};
@@ -76,11 +76,11 @@ pub trait ButtonVariants: Sized {
impl ButtonCustomVariant {
pub fn new(cx: &WindowContext) -> Self {
Self {
color: cx.theme().secondary,
foreground: cx.theme().secondary_foreground,
border: cx.theme().border,
hover: cx.theme().secondary_hover,
active: cx.theme().secondary_active,
color: cx.theme().accent.step(cx, ColorScaleStep::NINE),
foreground: cx.theme().accent.step(cx, ColorScaleStep::ONE),
border: cx.theme().accent.step(cx, ColorScaleStep::TEN),
hover: cx.theme().accent.step(cx, ColorScaleStep::TEN),
active: cx.theme().accent.step(cx, ColorScaleStep::ELEVEN),
shadow: true,
}
}
@@ -120,7 +120,6 @@ impl ButtonCustomVariant {
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum ButtonVariant {
Primary,
Secondary,
Danger,
Outline,
Ghost,
@@ -131,7 +130,7 @@ pub enum ButtonVariant {
impl Default for ButtonVariant {
fn default() -> Self {
Self::Secondary
Self::Primary
}
}
@@ -160,21 +159,20 @@ pub struct Button {
label: Option<SharedString>,
children: Vec<AnyElement>,
disabled: bool,
pub(crate) selected: bool,
variant: ButtonVariant,
rounded: ButtonRounded,
border_corners: Corners<bool>,
border_edges: Edges<bool>,
size: Size,
compact: bool,
reverse: bool,
bold: bool,
centered: bool,
tooltip: Option<SharedString>,
on_click: OnClick,
pub(crate) stop_propagation: bool,
loading: bool,
loading_icon: Option<Icon>,
pub(crate) selected: bool,
pub(crate) stop_propagation: bool,
}
impl From<Button> for AnyElement {
@@ -202,7 +200,6 @@ impl Button {
stop_propagation: true,
loading: false,
reverse: false,
compact: false,
bold: false,
centered: true,
children: Vec::new(),
@@ -252,12 +249,6 @@ impl Button {
self
}
/// Set the button to compact mode, then padding will be reduced.
pub fn compact(mut self) -> Self {
self.compact = true;
self
}
/// Set reverse the position between icon and label.
pub fn reverse(mut self) -> Self {
self.reverse = true;
@@ -372,9 +363,9 @@ impl RenderOnce for Button {
// Normal Button
match self.size {
Size::Size(size) => this.px(size * 0.2),
Size::XSmall => this.h_5().px_1().when(self.compact, |this| this.px_0()),
Size::Small => this.h_6().px_2().when(self.compact, |this| this.px_0p5()),
_ => this.h_8().px_4().when(self.compact, |this| this.px_1()),
Size::XSmall => this.h_6().px_0p5(),
Size::Small => this.h_8().px_2(),
_ => this.h_10().px_4(),
}
}
})
@@ -486,7 +477,7 @@ impl RenderOnce for Button {
})
.when(self.loading, |this| this.bg(normal_style.bg.opacity(0.8)))
.when_some(self.tooltip.clone(), |this, tooltip| {
this.tooltip(move |cx| Tooltip::new(tooltip.clone(), cx))
this.tooltip(move |cx| Tooltip::new(tooltip.clone(), cx).into())
})
}
}
@@ -502,34 +493,25 @@ struct ButtonVariantStyle {
impl ButtonVariant {
fn bg_color(&self, cx: &WindowContext) -> Hsla {
match self {
ButtonVariant::Primary => cx.theme().primary,
ButtonVariant::Secondary => cx.theme().secondary,
ButtonVariant::Primary => cx.theme().accent.step(cx, ColorScaleStep::NINE),
ButtonVariant::Danger => cx.theme().danger,
ButtonVariant::Outline
| ButtonVariant::Ghost
| ButtonVariant::Link
| ButtonVariant::Text => cx.theme().transparent,
ButtonVariant::Custom(colors) => colors.color,
_ => cx.theme().transparent,
}
}
fn text_color(&self, cx: &WindowContext) -> Hsla {
match self {
ButtonVariant::Primary => cx.theme().primary_foreground,
ButtonVariant::Secondary | ButtonVariant::Outline | ButtonVariant::Ghost => {
cx.theme().secondary_foreground
}
ButtonVariant::Danger => cx.theme().danger_foreground,
ButtonVariant::Link => cx.theme().link,
ButtonVariant::Text => cx.theme().foreground,
ButtonVariant::Primary => 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),
}
}
fn border_color(&self, cx: &WindowContext) -> Hsla {
match self {
ButtonVariant::Primary => cx.theme().primary,
ButtonVariant::Secondary => cx.theme().border,
ButtonVariant::Primary => cx.theme().colors.primary,
ButtonVariant::Danger => cx.theme().danger,
ButtonVariant::Outline => cx.theme().border,
ButtonVariant::Ghost | ButtonVariant::Link | ButtonVariant::Text => {
@@ -545,7 +527,7 @@ impl ButtonVariant {
fn shadow(&self, _: &WindowContext) -> bool {
match self {
ButtonVariant::Primary | ButtonVariant::Secondary | ButtonVariant::Danger => true,
ButtonVariant::Primary | ButtonVariant::Danger => true,
ButtonVariant::Custom(c) => c.shadow,
_ => false,
}
@@ -569,16 +551,10 @@ impl ButtonVariant {
fn hovered(&self, cx: &WindowContext) -> ButtonVariantStyle {
let bg = match self {
ButtonVariant::Primary => cx.theme().primary_hover,
ButtonVariant::Secondary | ButtonVariant::Outline => cx.theme().secondary_hover,
ButtonVariant::Primary => cx.theme().accent.step(cx, ColorScaleStep::TEN),
ButtonVariant::Outline => cx.theme().secondary_hover,
ButtonVariant::Danger => cx.theme().danger_hover,
ButtonVariant::Ghost => {
if cx.theme().mode.is_dark() {
cx.theme().secondary.lighten(0.1).opacity(0.8)
} else {
cx.theme().secondary.darken(0.1).opacity(0.8)
}
}
ButtonVariant::Ghost => cx.theme().base.step(cx, ColorScaleStep::FOUR),
ButtonVariant::Link => cx.theme().transparent,
ButtonVariant::Text => cx.theme().transparent,
ButtonVariant::Custom(colors) => colors.hover,
@@ -603,9 +579,9 @@ impl ButtonVariant {
fn active(&self, cx: &WindowContext) -> ButtonVariantStyle {
let bg = match self {
ButtonVariant::Primary => cx.theme().primary_active,
ButtonVariant::Secondary | ButtonVariant::Outline => cx.theme().secondary_active,
ButtonVariant::Outline => cx.theme().secondary_active,
ButtonVariant::Ghost => {
if cx.theme().mode.is_dark() {
if cx.theme().appearance.is_dark() {
cx.theme().secondary.lighten(0.2).opacity(0.8)
} else {
cx.theme().secondary.darken(0.2).opacity(0.8)
@@ -637,9 +613,9 @@ impl ButtonVariant {
fn selected(&self, cx: &WindowContext) -> ButtonVariantStyle {
let bg = match self {
ButtonVariant::Primary => cx.theme().primary_active,
ButtonVariant::Secondary | ButtonVariant::Outline => cx.theme().secondary_active,
ButtonVariant::Outline => cx.theme().secondary_active,
ButtonVariant::Ghost => {
if cx.theme().mode.is_dark() {
if cx.theme().appearance.is_dark() {
cx.theme().secondary.lighten(0.2).opacity(0.8)
} else {
cx.theme().secondary.darken(0.2).opacity(0.8)
@@ -674,9 +650,8 @@ impl ButtonVariant {
| ButtonVariant::Ghost
| ButtonVariant::Outline
| ButtonVariant::Text => cx.theme().transparent,
ButtonVariant::Primary => cx.theme().primary.opacity(0.15),
ButtonVariant::Primary => cx.theme().colors.primary.opacity(0.15),
ButtonVariant::Danger => cx.theme().danger.opacity(0.15),
ButtonVariant::Secondary => cx.theme().secondary.opacity(1.5),
ButtonVariant::Custom(style) => style.color.opacity(0.15),
};
let fg = match self {

View File

@@ -167,7 +167,6 @@ impl RenderOnce for ButtonGroup {
.stop_propagation(false)
.when_some(self.size, |this, size| this.with_size(size))
.when_some(self.variant, |this, variant| this.with_variant(variant))
.when_some(self.compact, |this, _| this.compact())
.on_click(move |_, _| {
state.set(Some(child_index));
})

View File

@@ -65,11 +65,11 @@ impl RenderOnce for Checkbox {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let (color, icon_color) = if self.disabled {
(
cx.theme().primary.opacity(0.5),
cx.theme().colors.primary.opacity(0.5),
cx.theme().primary_foreground.opacity(0.5),
)
} else {
(cx.theme().primary, cx.theme().primary_foreground)
(cx.theme().colors.primary, cx.theme().primary_foreground)
};
h_flex()

View File

@@ -1,13 +1,11 @@
use std::{cell::RefCell, rc::Rc};
use crate::popup_menu::PopupMenu;
use gpui::{
anchored, deferred, div, prelude::FluentBuilder, px, relative, AnyElement, Corner,
DismissEvent, DispatchPhase, Element, ElementId, Focusable, GlobalElementId,
InteractiveElement, IntoElement, MouseButton, MouseDownEvent, ParentElement, Pixels, Point,
Position, Stateful, Style, View, ViewContext, WindowContext,
};
use crate::popup_menu::PopupMenu;
use std::{cell::RefCell, rc::Rc};
pub trait ContextMenuExt: ParentElement + Sized {
fn context_menu(

View File

@@ -23,7 +23,7 @@ pub use state::*;
pub use tab_panel::*;
pub use tiles::*;
use crate::theme::ActiveTheme;
use crate::theme::{scale::ColorScaleStep, ActiveTheme};
pub fn init(cx: &mut AppContext) {
cx.set_global(PanelRegistry::new());
@@ -856,8 +856,7 @@ impl Render for DockArea {
.h_full()
// Left dock
.when_some(self.left_dock.clone(), |this, dock| {
this.bg(cx.theme().muted)
.text_color(cx.theme().muted_foreground)
this.bg(cx.theme().base.step(cx, ColorScaleStep::ONE))
.child(div().flex().flex_none().child(dock))
})
// Center

View File

@@ -1,7 +1,3 @@
use gpui::*;
use prelude::FluentBuilder;
use std::sync::Arc;
use super::{
ClosePanel, DockArea, DockPlacement, Panel, PanelEvent, PanelState, PanelStyle, PanelView,
StackPanel, ToggleZoom,
@@ -12,9 +8,17 @@ use crate::{
h_flex,
popup_menu::{PopupMenu, PopupMenuExt},
tab::{tab_bar::TabBar, Tab},
theme::ActiveTheme,
theme::{scale::ColorScaleStep, ActiveTheme},
v_flex, AxisExt, IconName, Placement, Selectable, Sizable,
};
use gpui::{
div, img, prelude::FluentBuilder, px, rems, AppContext, Corner, DefiniteLength, DismissEvent,
DragMoveEvent, Empty, Entity, EventEmitter, FocusHandle, FocusableView,
InteractiveElement as _, IntoElement, ObjectFit, ParentElement, Pixels, Render, ScrollHandle,
SharedString, StatefulInteractiveElement, Styled, StyledImage, View, ViewContext,
VisualContext as _, WeakView, WindowContext,
};
use std::sync::Arc;
#[derive(Clone, Copy)]
struct TabState {
@@ -49,13 +53,11 @@ impl Render for DragPanel {
.justify_center()
.overflow_hidden()
.whitespace_nowrap()
.border_1()
.border_color(cx.theme().border)
.rounded_md()
.text_color(cx.theme().tab_foreground)
.rounded(px(cx.theme().radius))
.text_xs()
.bg(cx.theme().tab_active)
.opacity(0.75)
.border_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.bg(cx.theme().base.step(cx, ColorScaleStep::TWO))
.child(self.panel.title(cx))
}
}
@@ -572,8 +574,8 @@ impl TabPanel {
.border_r_1()
.border_b_1()
.h_full()
.border_color(cx.theme().border)
.bg(cx.theme().tab_bar)
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.bg(cx.theme().base.step(cx, ColorScaleStep::TWO))
.px_2()
.children(left_dock_button)
.children(bottom_dock_button),
@@ -611,7 +613,7 @@ impl TabPanel {
this.rounded_l_none()
.border_l_2()
.border_r_0()
.border_color(cx.theme().drag_border)
.border_color(cx.theme().base.step(cx, ColorScaleStep::TWO))
})
.on_drop(cx.listener(
move |this, drag: &DragPanel, cx| {
@@ -630,8 +632,11 @@ impl TabPanel {
.flex_grow()
.min_w_16()
.when(state.droppable, |this| {
this.drag_over::<DragPanel>(|this, _, cx| this.bg(cx.theme().drop_target))
.on_drop(cx.listener(move |this, drag: &DragPanel, cx| {
this.drag_over::<DragPanel>(|this, _, cx| {
this.bg(cx.theme().base.step(cx, ColorScaleStep::TWO))
})
.on_drop(cx.listener(
move |this, drag: &DragPanel, cx| {
this.will_split_placement = None;
let ix = if drag.tab_panel == view {
@@ -641,7 +646,8 @@ impl TabPanel {
};
this.on_drop(drag, ix, false, cx)
}))
},
))
}),
)
.suffix(
@@ -652,8 +658,8 @@ impl TabPanel {
.border_l_1()
.border_b_1()
.h_full()
.border_color(cx.theme().border)
.bg(cx.theme().tab_bar)
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.bg(cx.theme().base.step(cx, ColorScaleStep::TWO))
.px_2()
.gap_1()
.child(self.render_toolbar(state, cx))

View File

@@ -1,11 +1,3 @@
use gpui::{
actions, anchored, canvas, deferred, div, prelude::FluentBuilder, px, rems, AnyElement,
AppContext, Bounds, ClickEvent, DismissEvent, ElementId, EventEmitter, FocusHandle,
FocusableView, InteractiveElement, IntoElement, KeyBinding, Length, ParentElement, Pixels,
Render, SharedString, StatefulInteractiveElement, Styled, Task, View, ViewContext,
VisualContext, WeakView, WindowContext,
};
use crate::{
h_flex,
input::ClearButton,
@@ -13,6 +5,13 @@ use crate::{
theme::ActiveTheme,
v_flex, Disableable, Icon, IconName, Sizable, Size, StyleSized, StyledExt,
};
use gpui::{
actions, anchored, canvas, deferred, div, prelude::FluentBuilder, px, rems, AnyElement,
AppContext, Bounds, ClickEvent, DismissEvent, ElementId, EventEmitter, FocusHandle,
FocusableView, InteractiveElement, IntoElement, KeyBinding, Length, ParentElement, Pixels,
Render, SharedString, StatefulInteractiveElement, Styled, Task, View, ViewContext,
VisualContext, WeakView, WindowContext,
};
actions!(dropdown, [Up, Down, Enter, Escape]);

View File

@@ -144,7 +144,7 @@ impl TextElement {
),
size(px(1.5), line_height),
),
cx.theme().primary,
cx.theme().colors.primary,
))
};
}

View File

@@ -1,10 +1,9 @@
use crate::{h_flex, theme::ActiveTheme};
use gpui::{
div, prelude::FluentBuilder, rems, Div, IntoElement, ParentElement, RenderOnce, SharedString,
Styled, WindowContext,
};
use crate::{h_flex, theme::ActiveTheme};
const MASKED: &str = "";
#[derive(Default, PartialEq, Eq)]

View File

@@ -23,7 +23,6 @@ pub mod radio;
pub mod resizable;
pub mod scroll;
pub mod skeleton;
pub mod slider;
pub mod switch;
pub mod tab;
pub mod theme;

View File

@@ -47,7 +47,7 @@ pub(crate) fn overlay_color(overlay: bool, cx: &WindowContext) -> Hsla {
return hsla(0., 0., 0., 0.);
}
if cx.theme().mode.is_dark() {
if cx.theme().appearance.is_dark() {
hsla(0., 1., 1., 0.06)
} else {
hsla(0., 0., 0., 0.06)

View File

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

View File

@@ -1,3 +1,4 @@
use crate::{Selectable, StyledExt as _};
use gpui::{
actions, anchored, deferred, div, prelude::FluentBuilder as _, px, AnyElement, AppContext,
Bounds, Corner, DismissEvent, DispatchPhase, Element, ElementId, EventEmitter, FocusHandle,
@@ -7,8 +8,6 @@ use gpui::{
};
use std::{cell::RefCell, rc::Rc};
use crate::{Selectable, StyledExt as _};
const CONTEXT: &str = "Popover";
actions!(popover, [Escape]);
@@ -44,6 +43,7 @@ impl PopoverContent {
self
}
}
impl EventEmitter<DismissEvent> for PopoverContent {}
impl FocusableView for PopoverContent {

View File

@@ -1,11 +1,19 @@
use crate::scroll::{Scrollbar, ScrollbarState};
use crate::StyledExt;
use crate::{
button::Button, h_flex, list::ListItem, popover::Popover, theme::ActiveTheme, v_flex, Icon,
IconName, Selectable, Sizable as _,
button::Button,
h_flex,
list::ListItem,
popover::Popover,
scroll::{Scrollbar, ScrollbarState},
theme::{scale::ColorScaleStep, ActiveTheme},
v_flex, Icon, IconName, Selectable, Sizable as _, StyledExt,
};
use gpui::{
actions, anchored, canvas, div, prelude::FluentBuilder, px, rems, Action, AnyElement,
AppContext, Bounds, Corner, DismissEvent, Edges, EventEmitter, FocusHandle, FocusableView,
InteractiveElement, IntoElement, KeyBinding, Keystroke, ParentElement, Pixels, Render,
ScrollHandle, SharedString, StatefulInteractiveElement, Styled, View, ViewContext,
VisualContext as _, WeakView, WindowContext,
};
use gpui::*;
use prelude::FluentBuilder;
use std::{cell::Cell, ops::Deref, rc::Rc};
actions!(menu, [Confirm, Dismiss, SelectNext, SelectPrev]);
@@ -48,6 +56,7 @@ pub trait PopupMenuExt: Styled + Selectable + IntoElement + 'static {
.content(move |cx| PopupMenu::build(cx, |menu, cx| f(menu, cx)))
}
}
impl PopupMenuExt for Button {}
enum PopupMenuItem {
@@ -429,12 +438,14 @@ impl PopupMenu {
) -> Option<impl IntoElement> {
if let Some(action) = action {
if let Some(keybinding) = cx.bindings_for_action(action.deref()).first() {
let el = div().text_color(cx.theme().muted_foreground).children(
keybinding
.keystrokes()
.iter()
.map(|key| key_shortcut(key.clone())),
);
let el = div()
.text_color(cx.theme().base.step(cx, ColorScaleStep::ELEVEN))
.children(
keybinding
.keystrokes()
.iter()
.map(|key| key_shortcut(key.clone())),
);
return Some(el);
}
@@ -503,7 +514,6 @@ impl Render for PopupMenu {
.on_action(cx.listener(Self::dismiss))
.on_mouse_down_out(cx.listener(|this, _, cx| this.dismiss(&Dismiss, cx)))
.popover_style(cx)
.text_color(cx.theme().popover_foreground)
.relative()
.p_1()
.child(
@@ -557,7 +567,10 @@ impl Render for PopupMenu {
.h(px(1.))
.mx_neg_1()
.my_0p5()
.bg(cx.theme().muted),
.bg(cx
.theme()
.base
.step(cx, ColorScaleStep::TWO)),
)
}
PopupMenuItem::ElementItem { render, .. } => this

View File

@@ -1,4 +1,4 @@
use crate::theme::ActiveTheme;
use crate::theme::{scale::ColorScaleStep, ActiveTheme};
use gpui::{
div, prelude::FluentBuilder, px, relative, IntoElement, ParentElement, RenderOnce, Styled,
WindowContext,
@@ -44,7 +44,7 @@ impl RenderOnce for Progress {
.relative()
.h(px(self.height))
.rounded(rounded)
.bg(cx.theme().progress_bar.opacity(0.2))
.bg(cx.theme().accent.step(cx, ColorScaleStep::THREE))
.child(
div()
.absolute()
@@ -52,7 +52,7 @@ impl RenderOnce for Progress {
.left_0()
.h_full()
.w(relative_w)
.bg(cx.theme().progress_bar)
.bg(cx.theme().accent.step(cx, ColorScaleStep::NINE))
.map(|this| match self.value {
v if v >= 100. => this.rounded(rounded),
_ => this.rounded_l(rounded),

View File

@@ -1,4 +1,8 @@
use crate::{h_flex, theme::ActiveTheme, IconName};
use crate::{
h_flex,
theme::{scale::ColorScaleStep, ActiveTheme},
IconName,
};
use gpui::{
div, prelude::FluentBuilder, relative, svg, ElementId, InteractiveElement, IntoElement,
ParentElement, RenderOnce, SharedString, StatefulInteractiveElement, Styled, WindowContext,
@@ -53,15 +57,14 @@ impl Radio {
impl RenderOnce for Radio {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let color = if self.disabled {
cx.theme().primary.opacity(0.5)
cx.theme().accent.step(cx, ColorScaleStep::FIVE)
} else {
cx.theme().primary
cx.theme().accent.step(cx, ColorScaleStep::NINE)
};
h_flex()
.id(self.id)
.gap_x_2()
.text_color(cx.theme().foreground)
.items_center()
.line_height(relative(1.))
.child(
@@ -80,9 +83,6 @@ impl RenderOnce for Radio {
.left_px()
.size_3()
.text_color(color)
.when(self.checked, |this| {
this.text_color(cx.theme().primary_foreground)
})
.map(|this| match self.checked {
true => this.path(IconName::Check.path()),
false => this,

View File

@@ -1,15 +1,12 @@
use std::rc::Rc;
use super::resize_handle;
use crate::{h_flex, v_flex, AxisExt};
use gpui::{
canvas, div, prelude::FluentBuilder, px, relative, Along, AnyElement, AnyView, Axis, Bounds,
Element, Entity, EntityId, EventEmitter, IntoElement, IsZero, MouseMoveEvent, MouseUpEvent,
ParentElement, Pixels, Render, StatefulInteractiveElement as _, Style, Styled, View,
ViewContext, VisualContext as _, WeakView, WindowContext,
};
use crate::{h_flex, v_flex, AxisExt};
use super::resize_handle;
use std::rc::Rc;
pub(crate) const PANEL_MIN_SIZE: Pixels = px(100.);
@@ -237,7 +234,9 @@ impl ResizablePanelGroup {
}
}
}
impl EventEmitter<ResizablePanelEvent> for ResizablePanelGroup {}
impl Render for ResizablePanelGroup {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let view = cx.view().clone();

View File

@@ -1,11 +1,13 @@
use crate::{
theme::{scale::ColorScaleStep, ActiveTheme as _},
AxisExt as _,
};
use gpui::{
div, prelude::FluentBuilder as _, px, Axis, Div, ElementId, InteractiveElement, IntoElement,
ParentElement as _, Pixels, RenderOnce, Stateful, StatefulInteractiveElement, Styled as _,
WindowContext,
};
use crate::{theme::ActiveTheme as _, AxisExt as _};
pub(crate) const HANDLE_PADDING: Pixels = px(4.);
pub(crate) const HANDLE_SIZE: Pixels = px(1.);
@@ -34,6 +36,7 @@ impl InteractiveElement for ResizeHandle {
self.base.interactivity()
}
}
impl StatefulInteractiveElement for ResizeHandle {}
impl RenderOnce for ResizeHandle {
@@ -62,7 +65,7 @@ impl RenderOnce for ResizeHandle {
})
.child(
div()
.bg(cx.theme().border)
.bg(cx.theme().base.step(cx, ColorScaleStep::THREE))
.when(self.axis.is_horizontal(), |this| {
this.h_full().w(HANDLE_SIZE)
})

View File

@@ -1,3 +1,9 @@
use crate::{
modal::Modal,
notification::{Notification, NotificationList},
theme::{scale::ColorScaleStep, ActiveTheme},
window_border,
};
use gpui::{
div, AnyView, FocusHandle, InteractiveElement, IntoElement, ParentElement as _, Render, Styled,
View, ViewContext, VisualContext as _, WindowContext,
@@ -7,13 +13,6 @@ use std::{
rc::Rc,
};
use crate::{
modal::Modal,
notification::{Notification, NotificationList},
theme::ActiveTheme,
window_border,
};
/// Extension trait for [`WindowContext`] and [`ViewContext`] to add drawer functionality.
pub trait ContextModal: Sized {
/// Opens a Modal.
@@ -268,8 +267,8 @@ impl Render for Root {
.relative()
.size_full()
.font_family(".SystemUIFont")
.bg(cx.theme().background)
.text_color(cx.theme().foreground)
.bg(cx.theme().base.step(cx, ColorScaleStep::ONE))
.text_color(cx.theme().base.step(cx, ColorScaleStep::TWELVE))
.child(self.view.clone()),
)
}

View File

@@ -1,4 +1,4 @@
use crate::theme::ActiveTheme;
use crate::theme::{scale::ColorScaleStep, ActiveTheme};
use gpui::{
bounce, div, ease_in_out, Animation, AnimationExt, Div, IntoElement, ParentElement as _,
RenderOnce, Styled,
@@ -33,16 +33,18 @@ impl Styled for Skeleton {
impl RenderOnce for Skeleton {
fn render(self, cx: &mut gpui::WindowContext) -> impl IntoElement {
div().child(
self.base.bg(cx.theme().skeleton).with_animation(
"skeleton",
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(bounce(ease_in_out)),
move |this, delta| {
let v = 1.0 - delta * 0.5;
this.opacity(v)
},
),
self.base
.bg(cx.theme().base.step(cx, ColorScaleStep::THREE))
.with_animation(
"skeleton",
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(bounce(ease_in_out)),
move |this, delta| {
let v = 1.0 - delta * 0.5;
this.opacity(v)
},
),
)
}
}

View File

@@ -1,196 +0,0 @@
use crate::{theme::ActiveTheme, tooltip::Tooltip};
use gpui::{
canvas, div, prelude::FluentBuilder as _, px, relative, Axis, Bounds, DragMoveEvent, EntityId,
EventEmitter, InteractiveElement, IntoElement, MouseButton, MouseDownEvent, ParentElement as _,
Pixels, Point, Render, StatefulInteractiveElement as _, Styled, ViewContext,
VisualContext as _,
};
#[derive(Clone, Render)]
pub struct DragThumb(EntityId);
pub enum SliderEvent {
Change(f32),
}
/// A Slider element.
pub struct Slider {
axis: Axis,
min: f32,
max: f32,
step: f32,
value: f32,
bounds: Bounds<Pixels>,
}
impl Slider {
fn new(axis: Axis) -> Self {
Self {
axis,
min: 0.0,
max: 100.0,
step: 1.0,
value: 0.0,
bounds: Bounds::default(),
}
}
pub fn horizontal() -> Self {
Self::new(Axis::Horizontal)
}
/// Set the minimum value of the slider, default: 0.0
pub fn min(mut self, min: f32) -> Self {
self.min = min;
self
}
/// Set the maximum value of the slider, default: 100.0
pub fn max(mut self, max: f32) -> Self {
self.max = max;
self
}
/// Set the step value of the slider, default: 1.0
pub fn step(mut self, step: f32) -> Self {
self.step = step;
self
}
/// Set the default value of the slider, default: 0.0
pub fn default_value(mut self, value: f32) -> Self {
self.value = value;
self
}
/// Set the value of the slider.
pub fn set_value(&mut self, value: f32, cx: &mut gpui::ViewContext<Self>) {
self.value = value;
cx.notify();
}
/// Return percentage value of the slider, range of 0.0..1.0
fn relative_value(&self) -> f32 {
let step = self.step;
let value = self.value;
let min = self.min;
let max = self.max;
let relative_value = (value - min) / (max - min);
let relative_step = step / (max - min);
let relative_value = (relative_value / relative_step).round() * relative_step;
relative_value.clamp(0.0, 1.0)
}
/// Update value by mouse position
fn update_value_by_position(
&mut self,
position: Point<Pixels>,
cx: &mut gpui::ViewContext<Self>,
) {
let bounds = self.bounds;
let axis = self.axis;
let min = self.min;
let max = self.max;
let step = self.step;
let value = match axis {
Axis::Horizontal => {
let relative = (position.x - bounds.left()) / bounds.size.width;
min + (max - min) * relative
}
Axis::Vertical => {
let relative = (position.y - bounds.top()) / bounds.size.height;
max - (max - min) * relative
}
};
let value = (value / step).round() * step;
self.value = value.clamp(self.min, self.max);
cx.emit(SliderEvent::Change(self.value));
cx.notify();
}
fn render_thumb(&self, cx: &mut ViewContext<Self>) -> impl gpui::IntoElement {
let value = self.value;
let entity_id = cx.entity_id();
div()
.id("slider-thumb")
.on_drag(DragThumb(entity_id), |drag, _, cx| {
cx.stop_propagation();
cx.new_view(|_| drag.clone())
})
.on_drag_move(cx.listener(
move |view, e: &DragMoveEvent<DragThumb>, cx| match e.drag(cx) {
DragThumb(id) => {
if *id != entity_id {
return;
}
// set value by mouse position
view.update_value_by_position(e.event.position, cx)
}
},
))
.absolute()
.top(px(-5.))
.left(relative(self.relative_value()))
.ml(-px(8.))
.size_4()
.rounded_full()
.border_1()
.border_color(cx.theme().slider_bar.opacity(0.9))
.when(cx.theme().shadow, |this| this.shadow_md())
.bg(cx.theme().slider_thumb)
.tooltip(move |cx| Tooltip::new(format!("{}", value), cx))
}
fn on_mouse_down(&mut self, event: &MouseDownEvent, cx: &mut gpui::ViewContext<Self>) {
self.update_value_by_position(event.position, cx);
}
}
impl EventEmitter<SliderEvent> for Slider {}
impl Render for Slider {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
div()
.id("slider")
.on_mouse_down(MouseButton::Left, cx.listener(Self::on_mouse_down))
.h_5()
.child(
div()
.id("slider-bar")
.relative()
.w_full()
.my_1p5()
.h_1p5()
.bg(cx.theme().slider_bar.opacity(0.2))
.active(|this| this.bg(cx.theme().slider_bar.opacity(0.4)))
.rounded(px(3.))
.child(
div()
.absolute()
.top_0()
.left_0()
.h_full()
.w(relative(self.relative_value()))
.bg(cx.theme().slider_bar)
.rounded_l(px(3.)),
)
.child(self.render_thumb(cx))
.child({
let view = cx.view().clone();
canvas(
move |bounds, cx| view.update(cx, |r, _| r.bounds = bounds),
|_, _, _| {},
)
.absolute()
.size_full()
}),
)
}
}

View File

@@ -1,6 +1,6 @@
use crate::{
scroll::{Scrollable, ScrollbarAxis},
theme::ActiveTheme,
theme::{scale::ColorScaleStep, ActiveTheme},
};
use gpui::{div, px, Axis, Div, Element, ElementId, EntityId, Pixels, Styled, WindowContext};
use serde::{Deserialize, Serialize};
@@ -64,9 +64,9 @@ pub trait StyledExt: Styled + Sized {
/// Set as Popover style
fn popover_style(self, cx: &mut WindowContext) -> Self {
self.bg(cx.theme().popover)
self.bg(cx.theme().background)
.border_1()
.border_color(cx.theme().border)
.border_color(cx.theme().base.step(cx, ColorScaleStep::FOUR))
.shadow_lg()
.rounded_lg()
}

View File

@@ -105,7 +105,7 @@ impl Element for Switch {
let on_click = self.on_click.clone();
let (bg, toggle_bg) = match self.checked {
true => (theme.primary, theme.background),
true => (theme.colors.primary, theme.background),
false => (theme.input, theme.background),
};

View File

@@ -1,11 +1,12 @@
use crate::h_flex;
use crate::theme::ActiveTheme;
use gpui::prelude::FluentBuilder as _;
use gpui::{
div, AnyElement, Div, ElementId, IntoElement, ParentElement, RenderOnce, ScrollHandle,
StatefulInteractiveElement as _, Styled, WindowContext,
use crate::{
h_flex,
theme::{scale::ColorScaleStep, ActiveTheme},
};
use gpui::{
div, prelude::FluentBuilder as _, px, AnyElement, Div, ElementId, InteractiveElement,
IntoElement, ParentElement, RenderOnce, ScrollHandle, StatefulInteractiveElement as _, Styled,
WindowContext,
};
use gpui::{px, InteractiveElement};
use smallvec::SmallVec;
#[derive(IntoElement)]
@@ -70,8 +71,7 @@ impl RenderOnce for TabBar {
.flex()
.flex_none()
.items_center()
.bg(cx.theme().tab_bar)
.text_color(cx.theme().tab_foreground)
.bg(cx.theme().base.step(cx, ColorScaleStep::TWO))
.child(
div()
.id("border-b")
@@ -79,7 +79,7 @@ impl RenderOnce for TabBar {
.bottom_0()
.size_full()
.border_b_1()
.border_color(cx.theme().border),
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE)),
)
.when_some(self.prefix, |this, prefix| this.child(prefix))
.child(

View File

@@ -1,9 +1,10 @@
use crate::scroll::ScrollbarShow;
use colors::hsl;
use colors::{default_color_scales, hsl};
use gpui::{
blue, hsla, transparent_black, AppContext, Global, Hsla, ModelContext, SharedString,
ViewContext, WindowAppearance, WindowContext,
};
use scale::ColorScaleSet;
use std::ops::{Deref, DerefMut};
pub mod colors;
@@ -11,11 +12,11 @@ pub mod scale;
#[derive(Debug, Clone, Copy, Default)]
pub struct ThemeColors {
pub background: Hsla,
pub border: Hsla,
pub window_border: Hsla,
pub accent: Hsla,
pub accent_foreground: Hsla,
pub background: Hsla,
pub card: Hsla,
pub card_foreground: Hsla,
pub danger: Hsla,
@@ -68,9 +69,9 @@ pub struct ThemeColors {
impl ThemeColors {
pub fn light() -> Self {
Self {
background: hsl(0.0, 0.0, 100.),
accent: hsl(240.0, 5.0, 96.0),
accent_foreground: hsl(240.0, 5.9, 10.0),
background: hsl(0.0, 0.0, 100.),
border: hsl(240.0, 5.9, 90.0),
window_border: hsl(240.0, 5.9, 78.0),
card: hsl(0.0, 0.0, 100.0),
@@ -125,9 +126,9 @@ impl ThemeColors {
pub fn dark() -> Self {
Self {
background: hsl(0.0, 0.0, 8.0),
accent: hsl(240.0, 3.7, 15.9),
accent_foreground: hsl(0.0, 0.0, 78.0),
background: hsl(0.0, 0.0, 8.0),
border: hsl(240.0, 3.7, 16.9),
window_border: hsl(240.0, 3.7, 28.0),
card: hsl(0.0, 0.0, 8.0),
@@ -291,10 +292,14 @@ pub fn init(cx: &mut AppContext) {
Theme::sync_system_appearance(cx)
}
#[derive(Debug, Clone)]
pub struct Theme {
pub colors: ThemeColors,
pub mode: ThemeMode,
/// Base colors.
pub base: ColorScaleSet,
/// Accent colors.
pub accent: ColorScaleSet,
/// Window appearances.
pub appearance: Appearance,
pub font_family: SharedString,
pub font_size: f32,
pub radius: f32,
@@ -331,78 +336,26 @@ impl Theme {
cx.global_mut::<Theme>()
}
/// Apply a mask color to the theme.
pub fn apply_color(&mut self, mask_color: Hsla) {
self.title_bar = self.title_bar.apply(mask_color);
self.title_bar_border = self.title_bar_border.apply(mask_color);
self.background = self.background.apply(mask_color);
self.foreground = self.foreground.apply(mask_color);
self.card = self.card.apply(mask_color);
self.card_foreground = self.card_foreground.apply(mask_color);
self.popover = self.popover.apply(mask_color);
self.popover_foreground = self.popover_foreground.apply(mask_color);
self.primary = self.primary.apply(mask_color);
self.primary_hover = self.primary_hover.apply(mask_color);
self.primary_active = self.primary_active.apply(mask_color);
self.primary_foreground = self.primary_foreground.apply(mask_color);
self.secondary = self.secondary.apply(mask_color);
self.secondary_hover = self.secondary_hover.apply(mask_color);
self.secondary_active = self.secondary_active.apply(mask_color);
self.secondary_foreground = self.secondary_foreground.apply(mask_color);
self.muted = self.muted.apply(mask_color);
self.muted_foreground = self.muted_foreground.apply(mask_color);
self.accent = self.accent.apply(mask_color);
self.accent_foreground = self.accent_foreground.apply(mask_color);
self.border = self.border.apply(mask_color);
self.input = self.input.apply(mask_color);
self.ring = self.ring.apply(mask_color);
self.scrollbar = self.scrollbar.apply(mask_color);
self.scrollbar_thumb = self.scrollbar_thumb.apply(mask_color);
self.scrollbar_thumb_hover = self.scrollbar_thumb_hover.apply(mask_color);
self.drag_border = self.drag_border.apply(mask_color);
self.drop_target = self.drop_target.apply(mask_color);
self.tab_bar = self.tab_bar.apply(mask_color);
self.tab = self.tab.apply(mask_color);
self.tab_active = self.tab_active.apply(mask_color);
self.tab_foreground = self.tab_foreground.apply(mask_color);
self.tab_active_foreground = self.tab_active_foreground.apply(mask_color);
self.progress_bar = self.progress_bar.apply(mask_color);
self.slider_bar = self.slider_bar.apply(mask_color);
self.slider_thumb = self.slider_thumb.apply(mask_color);
self.list = self.list.apply(mask_color);
self.list_even = self.list_even.apply(mask_color);
self.list_head = self.list_head.apply(mask_color);
self.list_active = self.list_active.apply(mask_color);
self.list_active_border = self.list_active_border.apply(mask_color);
self.list_hover = self.list_hover.apply(mask_color);
self.link = self.link.apply(mask_color);
self.link_hover = self.link_hover.apply(mask_color);
self.link_active = self.link_active.apply(mask_color);
self.skeleton = self.skeleton.apply(mask_color);
self.title_bar = self.title_bar.apply(mask_color);
self.title_bar_border = self.title_bar_border.apply(mask_color);
}
/// Sync the theme with the system appearance
pub fn sync_system_appearance(cx: &mut AppContext) {
match cx.window_appearance() {
WindowAppearance::Dark | WindowAppearance::VibrantDark => {
Self::change(ThemeMode::Dark, cx)
Self::change(Appearance::Dark, cx)
}
WindowAppearance::Light | WindowAppearance::VibrantLight => {
Self::change(ThemeMode::Light, cx)
Self::change(Appearance::Light, cx)
}
}
}
pub fn change(mode: ThemeMode, cx: &mut AppContext) {
pub fn change(mode: Appearance, cx: &mut AppContext) {
let colors = match mode {
ThemeMode::Light => ThemeColors::light(),
ThemeMode::Dark => ThemeColors::dark(),
Appearance::Light => ThemeColors::light(),
Appearance::Dark => ThemeColors::dark(),
};
let mut theme = Theme::from(colors);
theme.mode = mode;
theme.appearance = mode;
cx.set_global(theme);
cx.refresh();
@@ -411,8 +364,12 @@ impl Theme {
impl From<ThemeColors> for Theme {
fn from(colors: ThemeColors) -> Self {
let color_scales = default_color_scales();
Theme {
mode: ThemeMode::default(),
base: color_scales.gray,
accent: color_scales.yellow,
appearance: Appearance::default(),
transparent: Hsla::transparent_black(),
font_size: 16.0,
font_family: if cfg!(target_os = "macos") {
@@ -431,13 +388,13 @@ impl From<ThemeColors> for Theme {
}
#[derive(Debug, Clone, Copy, Default, PartialEq, PartialOrd, Eq)]
pub enum ThemeMode {
pub enum Appearance {
#[default]
Light,
Dark,
}
impl ThemeMode {
impl Appearance {
pub fn is_dark(&self) -> bool {
matches!(self, Self::Dark)
}

View File

@@ -1,4 +1,4 @@
use crate::theme::{ActiveTheme, ThemeMode};
use crate::theme::{ActiveTheme, Appearance};
use gpui::{AppContext, Hsla, SharedString};
/// A collection of colors that are used to style the UI.
@@ -280,16 +280,16 @@ impl ColorScaleSet {
}
pub fn step(&self, cx: &AppContext, step: ColorScaleStep) -> Hsla {
match cx.theme().mode {
ThemeMode::Light => self.light().step(step),
ThemeMode::Dark => self.dark().step(step),
match cx.theme().appearance {
Appearance::Light => self.light().step(step),
Appearance::Dark => self.dark().step(step),
}
}
pub fn step_alpha(&self, cx: &AppContext, step: ColorScaleStep) -> Hsla {
match cx.theme().mode {
ThemeMode::Light => self.light_alpha.step(step),
ThemeMode::Dark => self.dark_alpha.step(step),
match cx.theme().appearance {
Appearance::Light => self.light_alpha.step(step),
Appearance::Dark => self.dark_alpha.step(step),
}
}
}

View File

@@ -1,4 +1,8 @@
use crate::{h_flex, theme::ActiveTheme, Icon, IconName, InteractiveElementExt as _, Sizable as _};
use crate::{
h_flex,
theme::{scale::ColorScaleStep, ActiveTheme},
Icon, IconName, InteractiveElementExt as _, Sizable as _,
};
use gpui::{
black, div, prelude::FluentBuilder as _, px, relative, white, AnyElement, ClickEvent, Div,
Element, Hsla, InteractiveElement as _, IntoElement, MouseButton, ParentElement, Pixels,
@@ -6,9 +10,8 @@ use gpui::{
};
use std::rc::Rc;
pub const HEIGHT: Pixels = px(34.);
pub const TITLE_BAR_HEIGHT: Pixels = px(35.);
const HEIGHT: Pixels = px(34.);
const TITLE_BAR_HEIGHT: Pixels = px(35.);
#[cfg(target_os = "macos")]
const TITLE_BAR_LEFT_PADDING: Pixels = px(80.);
#[cfg(not(target_os = "macos"))]
@@ -59,14 +62,14 @@ impl Default for TitleBar {
// We don't need implementation the click event for the control buttons.
// If user clicked in the bounds, the window event will be triggered.
#[derive(IntoElement, Clone)]
enum ControlIcon {
enum Control {
Minimize,
Restore,
Maximize,
Close { on_close_window: OnCloseWindow },
}
impl ControlIcon {
impl Control {
fn minimize() -> Self {
Self::Minimize
}
@@ -106,7 +109,7 @@ impl ControlIcon {
}
fn fg(&self, cx: &WindowContext) -> Hsla {
if cx.theme().mode.is_dark() {
if cx.theme().appearance.is_dark() {
white()
} else {
black()
@@ -114,7 +117,7 @@ impl ControlIcon {
}
fn hover_fg(&self, cx: &WindowContext) -> Hsla {
if self.is_close() || cx.theme().mode.is_dark() {
if self.is_close() || cx.theme().appearance.is_dark() {
white()
} else {
black()
@@ -129,7 +132,7 @@ impl ControlIcon {
b: 32.0 / 255.0,
a: 1.0,
}
} else if cx.theme().mode.is_dark() {
} else if cx.theme().appearance.is_dark() {
Rgba {
r: 0.9,
g: 0.9,
@@ -147,7 +150,7 @@ impl ControlIcon {
}
}
impl RenderOnce for ControlIcon {
impl RenderOnce for Control {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let fg = self.fg(cx);
let hover_fg = self.hover_fg(cx);
@@ -155,7 +158,7 @@ impl RenderOnce for ControlIcon {
let icon = self.clone();
let is_linux = cfg!(target_os = "linux");
let on_close_window = match &icon {
ControlIcon::Close { on_close_window } => on_close_window.clone(),
Control::Close { on_close_window } => on_close_window.clone(),
_ => None,
};
@@ -214,14 +217,14 @@ impl RenderOnce for WindowControls {
.justify_center()
.content_stretch()
.h_full()
.child(ControlIcon::minimize())
.child(Control::minimize())
.child(if cx.is_maximized() {
ControlIcon::restore()
Control::restore()
} else {
ControlIcon::maximize()
Control::maximize()
}),
)
.child(ControlIcon::close(self.on_close_window))
.child(Control::close(self.on_close_window))
}
}
@@ -249,8 +252,8 @@ impl RenderOnce for TitleBar {
.justify_between()
.h(HEIGHT)
.border_b_1()
.border_color(cx.theme().title_bar_border.opacity(0.7))
.bg(cx.theme().title_bar)
.border_color(cx.theme().base.step(cx, ColorScaleStep::THREE))
.bg(cx.theme().base.step(cx, ColorScaleStep::ONE))
.when(cx.is_fullscreen(), |this| this.pl(px(12.)))
.on_double_click(|_, cx| cx.zoom_window())
.child(
@@ -292,7 +295,6 @@ impl IntoElement for TitleBarElement {
impl Element for TitleBarElement {
type RequestLayoutState = ();
type PrepaintState = ();
fn id(&self) -> Option<gpui::ElementId> {
@@ -328,7 +330,6 @@ impl Element for TitleBarElement {
) -> Self::PrepaintState {
}
#[allow(unused_variables)]
fn paint(
&mut self,
_: Option<&gpui::GlobalElementId>,
@@ -338,6 +339,7 @@ impl Element for TitleBarElement {
cx: &mut WindowContext,
) {
use gpui::{MouseButton, MouseMoveEvent, MouseUpEvent};
cx.on_mouse_event(move |ev: &MouseMoveEvent, _, cx: &mut WindowContext| {
if bounds.contains(&ev.position) && ev.pressed_button == Some(MouseButton::Left) {
cx.start_window_move();

View File

@@ -1,18 +1,16 @@
use crate::theme::{scale::ColorScaleStep, ActiveTheme};
use gpui::{
div, px, AnyView, IntoElement, ParentElement, Render, SharedString, Styled, ViewContext,
div, px, IntoElement, ParentElement, Render, SharedString, Styled, View, ViewContext,
VisualContext, WindowContext,
};
use crate::theme::ActiveTheme;
pub struct Tooltip {
text: SharedString,
}
impl Tooltip {
#[allow(clippy::new_ret_no_self)]
pub fn new(text: impl Into<SharedString>, cx: &mut WindowContext) -> AnyView {
cx.new_view(|_| Self { text: text.into() }).into()
pub fn new(text: impl Into<SharedString>, cx: &mut WindowContext) -> View<Self> {
cx.new_view(|_| Self { text: text.into() })
}
}
@@ -23,10 +21,8 @@ impl Render for Tooltip {
div()
.font_family(".SystemUIFont")
.m_3()
.bg(cx.theme().popover)
.text_color(cx.theme().popover_foreground)
.border_1()
.border_color(cx.theme().border)
.bg(cx.theme().base.step(cx, ColorScaleStep::TWELVE))
.text_color(cx.theme().base.step(cx, ColorScaleStep::ONE))
.shadow_md()
.rounded(px(6.))
.py_0p5()

View File

@@ -1,19 +1,17 @@
use crate::theme::ActiveTheme;
use gpui::{
canvas, div, point, prelude::FluentBuilder as _, px, AnyElement, Bounds, CursorStyle,
Decorations, Edges, Hsla, InteractiveElement as _, IntoElement, MouseButton, ParentElement,
Pixels, Point, RenderOnce, ResizeEdge, Size, Styled as _, WindowContext,
};
use crate::theme::ActiveTheme;
pub(crate) const BORDER_SIZE: Pixels = Pixels(1.0);
pub(crate) const BORDER_RADIUS: Pixels = Pixels(0.0);
#[cfg(not(target_os = "linux"))]
pub(crate) const SHADOW_SIZE: Pixels = Pixels(0.0);
#[cfg(target_os = "linux")]
pub(crate) const SHADOW_SIZE: Pixels = Pixels(12.0);
pub(crate) const BORDER_SIZE: Pixels = Pixels(1.0);
pub(crate) const BORDER_RADIUS: Pixels = Pixels(0.0);
/// Create a new window border.
pub fn window_border() -> WindowBorder {
WindowBorder::new()