Update to use shadcn ui theme
This commit is contained in:
parent
11af9900eb
commit
94cb714ebf
11 changed files with 276 additions and 221 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -4250,6 +4250,8 @@ dependencies = [
|
||||||
"catppuccin",
|
"catppuccin",
|
||||||
"gpui",
|
"gpui",
|
||||||
"log",
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,5 @@ workspace = { path = "crates/workspace" }
|
||||||
util = { path = "crates/util" }
|
util = { path = "crates/util" }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
serde = "1.0.203"
|
||||||
|
serde_json = "1"
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,5 @@ edition = "2021"
|
||||||
catppuccin = "2.4.0"
|
catppuccin = "2.4.0"
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
log.wokrspace = true
|
log.wokrspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,9 @@ use gpui::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
colors::Color,
|
|
||||||
disableable::{Clickable, Disableable, Selectable},
|
disableable::{Clickable, Disableable, Selectable},
|
||||||
label::Label,
|
label::Label,
|
||||||
theme::Theme,
|
theme::{Colorize as _, Theme},
|
||||||
HlsaExt as _,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum ButtonRounded {
|
pub enum ButtonRounded {
|
||||||
|
|
@ -120,6 +118,7 @@ impl RenderOnce for Button {
|
||||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||||
let theme = cx.global::<Theme>();
|
let theme = cx.global::<Theme>();
|
||||||
let style: ButtonStyle = self.style;
|
let style: ButtonStyle = self.style;
|
||||||
|
let normal_style = style.normal(cx);
|
||||||
|
|
||||||
self.base
|
self.base
|
||||||
.id(self.id)
|
.id(self.id)
|
||||||
|
|
@ -127,7 +126,7 @@ impl RenderOnce for Button {
|
||||||
.items_center()
|
.items_center()
|
||||||
.justify_center()
|
.justify_center()
|
||||||
.map(|this| match self.size {
|
.map(|this| match self.size {
|
||||||
ButtonSize::Small => this.px_3().py_2().h_5(),
|
ButtonSize::Small => this.px_3().py_2().h_6(),
|
||||||
ButtonSize::Medium => this.px_4().py_2().h_8(),
|
ButtonSize::Medium => this.px_4().py_2().h_8(),
|
||||||
})
|
})
|
||||||
.map(|this| match self.rounded {
|
.map(|this| match self.rounded {
|
||||||
|
|
@ -137,8 +136,14 @@ impl RenderOnce for Button {
|
||||||
ButtonRounded::None => this.rounded_none(),
|
ButtonRounded::None => this.rounded_none(),
|
||||||
})
|
})
|
||||||
.when(!self.disabled, |this| {
|
.when(!self.disabled, |this| {
|
||||||
this.hover(|this| this.border_color(theme.blue))
|
this.hover(|this| {
|
||||||
.active(|this| this.bg(theme.blue.lighten(10.0)))
|
let hover_style = style.hovered(cx);
|
||||||
|
this.bg(hover_style.bg).border_color(hover_style.border)
|
||||||
|
})
|
||||||
|
.active(|this| {
|
||||||
|
let active_style = style.active(cx);
|
||||||
|
this.bg(active_style.bg).border_color(active_style.border)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.when_some(
|
.when_some(
|
||||||
self.on_click.filter(|_| !self.disabled),
|
self.on_click.filter(|_| !self.disabled),
|
||||||
|
|
@ -157,13 +162,13 @@ impl RenderOnce for Button {
|
||||||
.border_color(disabled_style.border)
|
.border_color(disabled_style.border)
|
||||||
})
|
})
|
||||||
.border_1()
|
.border_1()
|
||||||
.border_color(theme.crust)
|
.border_color(normal_style.border)
|
||||||
.bg(theme.base)
|
.bg(normal_style.bg)
|
||||||
.child({
|
.child({
|
||||||
let text_color = if self.disabled {
|
let text_color = if self.disabled {
|
||||||
theme.text_disabled
|
normal_style.fg.opacity(0.6)
|
||||||
} else {
|
} else {
|
||||||
theme.text
|
normal_style.fg
|
||||||
};
|
};
|
||||||
|
|
||||||
Label::new(self.label)
|
Label::new(self.label)
|
||||||
|
|
@ -183,58 +188,64 @@ struct ButtonStyles {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ButtonStyle {
|
impl ButtonStyle {
|
||||||
fn bg_color(&self) -> Color {
|
fn bg_color(&self, cx: &WindowContext) -> Hsla {
|
||||||
|
let theme = cx.global::<Theme>();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
ButtonStyle::Primary => Color::Primary,
|
ButtonStyle::Primary => theme.primary,
|
||||||
ButtonStyle::Secondary => Color::Secondary,
|
ButtonStyle::Secondary => theme.secondary,
|
||||||
ButtonStyle::Danger => Color::Destructive,
|
ButtonStyle::Danger => theme.destructive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_color(&self) -> Color {
|
fn text_color(&self, cx: &WindowContext) -> Hsla {
|
||||||
|
let theme = cx.global::<Theme>();
|
||||||
match self {
|
match self {
|
||||||
ButtonStyle::Primary => Color::PrimaryForeground,
|
ButtonStyle::Primary => theme.primary_foreground,
|
||||||
ButtonStyle::Secondary => Color::SecondaryForeground,
|
ButtonStyle::Secondary => theme.secondary_foreground,
|
||||||
ButtonStyle::Danger => Color::DestructiveForeground,
|
ButtonStyle::Danger => theme.destructive_foreground,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn border_color(&self) -> Color {
|
fn border_color(&self, cx: &WindowContext) -> Hsla {
|
||||||
|
let theme = cx.global::<Theme>();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
ButtonStyle::Primary => Color::Primary,
|
ButtonStyle::Primary => theme.primary,
|
||||||
ButtonStyle::Secondary => Color::Secondary,
|
ButtonStyle::Secondary => theme.secondary,
|
||||||
ButtonStyle::Danger => Color::Destructive,
|
ButtonStyle::Danger => theme.destructive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normal(&self, cx: &WindowContext) -> ButtonStyles {
|
fn normal(&self, cx: &WindowContext) -> ButtonStyles {
|
||||||
let bg = self.bg_color().color(cx);
|
let bg = self.bg_color(cx);
|
||||||
let border = self.border_color().color(cx);
|
let border = self.border_color(cx);
|
||||||
let fg = self.text_color().color(cx);
|
let fg = self.text_color(cx);
|
||||||
|
|
||||||
ButtonStyles { bg, border, fg }
|
ButtonStyles { bg, border, fg }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hovered(&self, cx: &WindowContext) -> ButtonStyles {
|
fn hovered(&self, cx: &WindowContext) -> ButtonStyles {
|
||||||
let bg = self.bg_color().color(cx).lighten(0.05);
|
// Hover color = color/90
|
||||||
let border = self.border_color().color(cx).lighten(0.05);
|
let bg = self.bg_color(cx).divide(0.9);
|
||||||
let fg = self.text_color().color(cx);
|
let border = self.border_color(cx).divide(0.9);
|
||||||
|
let fg = self.text_color(cx).divide(0.9);
|
||||||
|
|
||||||
ButtonStyles { bg, border, fg }
|
ButtonStyles { bg, border, fg }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn active(&self, cx: &WindowContext) -> ButtonStyles {
|
fn active(&self, cx: &WindowContext) -> ButtonStyles {
|
||||||
let bg = self.bg_color().color(cx).darken(0.05);
|
let bg = self.bg_color(cx);
|
||||||
let border = self.border_color().color(cx).darken(0.05);
|
let border = self.border_color(cx);
|
||||||
let fg = self.text_color().color(cx);
|
let fg = self.text_color(cx);
|
||||||
|
|
||||||
ButtonStyles { bg, border, fg }
|
ButtonStyles { bg, border, fg }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disabled(&self, cx: &WindowContext) -> ButtonStyles {
|
fn disabled(&self, cx: &WindowContext) -> ButtonStyles {
|
||||||
let bg = self.bg_color().color(cx).grayscale();
|
let bg = self.bg_color(cx).grayscale();
|
||||||
let border = self.border_color().color(cx).grayscale();
|
let border = self.border_color(cx).grayscale();
|
||||||
let fg = self.text_color().color(cx).grayscale();
|
let fg = self.text_color(cx).grayscale();
|
||||||
|
|
||||||
ButtonStyles { bg, border, fg }
|
ButtonStyles { bg, border, fg }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
use gpui::{hsla, Hsla, WindowContext};
|
|
||||||
|
|
||||||
pub fn hls(h: f32, l: f32, s: f32) -> Hsla {
|
|
||||||
hsla(h, l / 100., s / 100., 1.)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extension trait for `Hsla` to provide more color manipulation methods.
|
|
||||||
pub trait HlsaExt {
|
|
||||||
fn darken(&self, amount: f32) -> Hsla;
|
|
||||||
fn lighten(&self, amount: f32) -> Hsla;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HlsaExt for Hsla {
|
|
||||||
/// Darken the color by a percentage.
|
|
||||||
///
|
|
||||||
/// `amount` value is 0.0 - 1.0
|
|
||||||
fn darken(&self, amount: f32) -> Hsla {
|
|
||||||
let l = self.l - (self.l * amount);
|
|
||||||
hsla(self.h, l, self.s, self.a)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Lighten the color by a percentage.
|
|
||||||
///
|
|
||||||
/// `amount` value is 0.0 - 1.0
|
|
||||||
fn lighten(&self, amount: f32) -> Hsla {
|
|
||||||
let l = self.l + (self.l * amount);
|
|
||||||
hsla(self.h, l, self.s, self.a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// .dark {
|
|
||||||
// --background: 240 10% 3.9%;
|
|
||||||
// --foreground: 0 0% 98%;
|
|
||||||
// --card: 240 10% 3.9%;
|
|
||||||
// --card-foreground: 0 0% 98%;
|
|
||||||
// --popover: 240 10% 3.9%;
|
|
||||||
// --popover-foreground: 0 0% 98%;
|
|
||||||
// --primary: 0 0% 98%;
|
|
||||||
// --primary-foreground: 240 5.9% 10%;
|
|
||||||
// --secondary: 240 3.7% 15.9%;
|
|
||||||
// --secondary-foreground: 0 0% 98%;
|
|
||||||
// --muted: 240 3.7% 15.9%;
|
|
||||||
// --muted-foreground: 240 5% 64.9%;
|
|
||||||
// --accent: 240 3.7% 15.9%;
|
|
||||||
// --accent-foreground: 0 0% 98%;
|
|
||||||
// --destructive: 0 62.8% 30.6%;
|
|
||||||
// --destructive-foreground: 0 85.7% 97.3%;
|
|
||||||
// --border: 240 3.7% 15.9%;
|
|
||||||
// --input: 240 3.7% 15.9%;
|
|
||||||
// --ring: 240 4.9% 83.9%;
|
|
||||||
// --selection: 240 21.6% 50.6%;
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub enum Color {
|
|
||||||
Background,
|
|
||||||
Foreground,
|
|
||||||
Card,
|
|
||||||
CardForeground,
|
|
||||||
Popover,
|
|
||||||
PopoverForeground,
|
|
||||||
Primary,
|
|
||||||
PrimaryForeground,
|
|
||||||
Secondary,
|
|
||||||
SecondaryForeground,
|
|
||||||
Muted,
|
|
||||||
MutedForeground,
|
|
||||||
Accent,
|
|
||||||
AccentForeground,
|
|
||||||
Destructive,
|
|
||||||
DestructiveForeground,
|
|
||||||
Border,
|
|
||||||
Input,
|
|
||||||
Ring,
|
|
||||||
Selection,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Color {
|
|
||||||
pub fn color(&self, _cx: &WindowContext) -> Hsla {
|
|
||||||
match self {
|
|
||||||
Color::Background => hls(240., 10., 3.9),
|
|
||||||
Color::Foreground => hls(0., 0., 98.),
|
|
||||||
Color::Card => hls(240., 10., 3.9),
|
|
||||||
Color::CardForeground => hls(0., 0., 98.),
|
|
||||||
Color::Popover => hls(240., 10., 3.9),
|
|
||||||
Color::PopoverForeground => hls(0., 0., 98.),
|
|
||||||
Color::Primary => hls(0., 0., 98.),
|
|
||||||
Color::PrimaryForeground => hls(240., 5.9, 10.),
|
|
||||||
Color::Secondary => hls(240., 3.7, 15.9),
|
|
||||||
Color::SecondaryForeground => hls(0., 0., 98.),
|
|
||||||
Color::Muted => hls(240., 3.7, 15.9),
|
|
||||||
Color::MutedForeground => hls(240., 5., 64.9),
|
|
||||||
Color::Accent => hls(240., 3.7, 15.9),
|
|
||||||
Color::AccentForeground => hls(0., 0., 98.),
|
|
||||||
Color::Destructive => hls(0., 62.8, 30.6),
|
|
||||||
Color::DestructiveForeground => hls(0., 85.7, 97.3),
|
|
||||||
Color::Border => hls(240., 3.7, 15.9),
|
|
||||||
Color::Input => hls(240., 3.7, 15.9),
|
|
||||||
Color::Ring => hls(240., 4.9, 83.9),
|
|
||||||
Color::Selection => hls(213., 21.6, 50.6),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,7 +3,7 @@ use gpui::{
|
||||||
ParentElement, RenderOnce, SharedString, Styled, WindowContext,
|
ParentElement, RenderOnce, SharedString, Styled, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{hls, theme::Theme};
|
use crate::theme::Theme;
|
||||||
|
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct Label {
|
pub struct Label {
|
||||||
|
|
@ -21,7 +21,7 @@ impl Label {
|
||||||
base: div(),
|
base: div(),
|
||||||
label: label.into(),
|
label: label.into(),
|
||||||
multiple_lines: false,
|
multiple_lines: false,
|
||||||
color: hls(0., 0., 0.),
|
color: Hsla::white(),
|
||||||
line_height: None,
|
line_height: None,
|
||||||
text_size: None,
|
text_size: None,
|
||||||
}
|
}
|
||||||
|
|
@ -46,8 +46,6 @@ impl Styled for Label {
|
||||||
|
|
||||||
impl RenderOnce for Label {
|
impl RenderOnce for Label {
|
||||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||||
let theme = cx.global::<Theme>();
|
|
||||||
|
|
||||||
let label_text = if !self.multiple_lines {
|
let label_text = if !self.multiple_lines {
|
||||||
SharedString::from(self.label.replace('\n', ""))
|
SharedString::from(self.label.replace('\n', ""))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -56,7 +54,7 @@ impl RenderOnce for Label {
|
||||||
|
|
||||||
self.base
|
self.base
|
||||||
.child(label_text)
|
.child(label_text)
|
||||||
.text_color(theme.text)
|
.text_color(self.color)
|
||||||
.map(|this| {
|
.map(|this| {
|
||||||
if let Some(text_size) = self.text_size {
|
if let Some(text_size) = self.text_size {
|
||||||
this.text_size(text_size)
|
this.text_size(text_size)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
pub mod button;
|
pub mod button;
|
||||||
mod colors;
|
|
||||||
pub mod cursor;
|
pub mod cursor;
|
||||||
pub mod disableable;
|
pub mod disableable;
|
||||||
pub mod label;
|
pub mod label;
|
||||||
pub mod story;
|
pub mod story;
|
||||||
pub mod text_field;
|
pub mod text_field;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
|
|
||||||
pub use colors::*;
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@ mod blink_manager;
|
||||||
mod cursor_layout;
|
mod cursor_layout;
|
||||||
mod text_view;
|
mod text_view;
|
||||||
|
|
||||||
use crate::{disableable::Disableable, theme::Theme};
|
use crate::{
|
||||||
|
disableable::Disableable,
|
||||||
|
theme::{Colorize as _, Theme},
|
||||||
|
};
|
||||||
use blink_manager::BlinkManager;
|
use blink_manager::BlinkManager;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, ClipboardItem, Context, EventEmitter, FocusHandle, InteractiveElement, IntoElement,
|
div, ClipboardItem, Context, EventEmitter, FocusHandle, InteractiveElement, IntoElement,
|
||||||
|
|
@ -198,9 +201,9 @@ impl RenderOnce for TextField {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.border_color(if self.focus_handle.is_focused(cx) {
|
.border_color(if self.focus_handle.is_focused(cx) {
|
||||||
theme.blue
|
theme.ring
|
||||||
} else {
|
} else {
|
||||||
theme.crust
|
theme.input
|
||||||
})
|
})
|
||||||
.border_1()
|
.border_1()
|
||||||
.rounded_sm()
|
.rounded_sm()
|
||||||
|
|
@ -208,9 +211,9 @@ impl RenderOnce for TextField {
|
||||||
.px_3()
|
.px_3()
|
||||||
.min_w_20()
|
.min_w_20()
|
||||||
.bg(if self.disable {
|
.bg(if self.disable {
|
||||||
theme.crust
|
theme.background.opacity(0.5)
|
||||||
} else {
|
} else {
|
||||||
theme.base
|
theme.background
|
||||||
})
|
})
|
||||||
.child(view)
|
.child(view)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::ops::Range;
|
||||||
use super::{
|
use super::{
|
||||||
blink_manager::BlinkManager, cursor_layout::CursorLayout, TextEvent, CURSOR_BLINK_INTERVAL,
|
blink_manager::BlinkManager, cursor_layout::CursorLayout, TextEvent, CURSOR_BLINK_INTERVAL,
|
||||||
};
|
};
|
||||||
use crate::{hls, theme::Theme};
|
use crate::theme::{Colorize as _, Theme};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
px, relative, Context, Element, EventEmitter, FocusHandle, HighlightStyle, InteractiveText,
|
px, relative, Context, Element, EventEmitter, FocusHandle, HighlightStyle, InteractiveText,
|
||||||
IntoElement, Model, Render, Style, StyledText, TextStyle, View, ViewContext, VisualContext,
|
IntoElement, Model, Render, Style, StyledText, TextStyle, View, ViewContext, VisualContext,
|
||||||
|
|
@ -32,11 +32,13 @@ impl TextView {
|
||||||
) -> View<Self> {
|
) -> View<Self> {
|
||||||
let blink_manager = cx.new_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
|
let blink_manager = cx.new_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
|
||||||
|
|
||||||
|
let theme = cx.global::<Theme>();
|
||||||
|
|
||||||
let cursor = CursorLayout::new(
|
let cursor = CursorLayout::new(
|
||||||
gpui::Point::new(gpui::px(0.0), gpui::px(0.0)),
|
gpui::Point::new(gpui::px(0.0), gpui::px(0.0)),
|
||||||
px(2.0),
|
px(2.0),
|
||||||
px(20.0),
|
px(20.0),
|
||||||
hls(212., 92., 45.),
|
theme.ring,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -219,8 +221,7 @@ impl Render for TextView {
|
||||||
dbg!("textView render", &text);
|
dbg!("textView render", &text);
|
||||||
|
|
||||||
let mut style = TextStyle {
|
let mut style = TextStyle {
|
||||||
color: theme.text,
|
color: theme.foreground,
|
||||||
font_family: theme.font_sans.clone(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -229,15 +230,14 @@ impl Render for TextView {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut selection_style = HighlightStyle::default();
|
let mut selection_style = HighlightStyle::default();
|
||||||
let mut color = theme.lavender;
|
let color = theme.foreground.opacity(0.8);
|
||||||
color.fade_out(0.8);
|
|
||||||
selection_style.background_color = Some(color);
|
selection_style.background_color = Some(color);
|
||||||
|
|
||||||
let mut highlights = vec![(self.char_range_to_text_range(&text), selection_style)];
|
let mut highlights = vec![(self.char_range_to_text_range(&text), selection_style)];
|
||||||
|
|
||||||
if text.is_empty() {
|
if text.is_empty() {
|
||||||
text = self.placeholder.to_string();
|
text = self.placeholder.to_string();
|
||||||
style.color = theme.subtext0;
|
style.color = theme.muted_foreground;
|
||||||
highlights = vec![];
|
highlights = vec![];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,65 +1,214 @@
|
||||||
use std::sync::Arc;
|
use gpui::{AppContext, Global, Hsla, Rgba};
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
use catppuccin::{Flavor, FlavorColors};
|
fn hex(color: &str) -> Hsla {
|
||||||
use gpui::{AppContext, Global, Hsla, Rgba, SharedString};
|
let color: Rgba = serde_json::from_value(json!(color)).unwrap();
|
||||||
|
color.into()
|
||||||
|
}
|
||||||
|
|
||||||
fn color_to_hsla(color: catppuccin::Color) -> Hsla {
|
fn hsl(h: f32, s: f32, l: f32) -> Hsla {
|
||||||
Rgba {
|
Hsla { h, s, l, a: 1.0 }
|
||||||
r: color.rgb.r as f32 / 255.0,
|
}
|
||||||
g: color.rgb.g as f32 / 255.0,
|
|
||||||
b: color.rgb.b as f32 / 255.0,
|
pub trait Colorize {
|
||||||
a: 1.0,
|
fn opacity(&self, opacity: f32) -> Hsla;
|
||||||
|
fn divide(&self, divisor: f32) -> Hsla;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Colorize for Hsla {
|
||||||
|
/// Returns a new color with the given opacity.
|
||||||
|
///
|
||||||
|
/// The opacity is a value between 0.0 and 1.0, where 0.0 is fully transparent and 1.0 is fully opaque.
|
||||||
|
fn opacity(&self, opacity: f32) -> Hsla {
|
||||||
|
Hsla {
|
||||||
|
a: self.a * opacity,
|
||||||
|
..*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new color with each channel divided by the given divisor.
|
||||||
|
///
|
||||||
|
/// The divisor in range of 0.0 .. 1.0
|
||||||
|
fn divide(&self, divisor: f32) -> Hsla {
|
||||||
|
Hsla {
|
||||||
|
a: divisor,
|
||||||
|
..*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @layer base {
|
||||||
|
// :root {
|
||||||
|
// --background: 0 0% 100%;
|
||||||
|
// --foreground: 240 10% 3.9%;
|
||||||
|
// --card: 0 0% 100%;
|
||||||
|
// --card-foreground: 240 10% 3.9%;
|
||||||
|
// --popover: 0 0% 100%;
|
||||||
|
// --popover-foreground: 240 10% 3.9%;
|
||||||
|
// --primary: 240 5.9% 10%;
|
||||||
|
// --primary-foreground: 0 0% 98%;
|
||||||
|
// --secondary: 240 4.8% 95.9%;
|
||||||
|
// --secondary-foreground: 240 5.9% 10%;
|
||||||
|
// --muted: 240 4.8% 95.9%;
|
||||||
|
// --muted-foreground: 240 3.8% 46.1%;
|
||||||
|
// --accent: 240 4.8% 95.9%;
|
||||||
|
// --accent-foreground: 240 5.9% 10%;
|
||||||
|
// --destructive: 0 84.2% 60.2%;
|
||||||
|
// --destructive-foreground: 0 0% 98%;
|
||||||
|
// --border: 240 5.9% 90%;
|
||||||
|
// --input: 240 5.9% 90%;
|
||||||
|
// --ring: 240 5.9% 10%;
|
||||||
|
// --radius: 0rem;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .dark {
|
||||||
|
// --background: 240 10% 3.9%;
|
||||||
|
// --foreground: 0 0% 98%;
|
||||||
|
// --card: 240 10% 3.9%;
|
||||||
|
// --card-foreground: 0 0% 98%;
|
||||||
|
// --popover: 240 10% 3.9%;
|
||||||
|
// --popover-foreground: 0 0% 98%;
|
||||||
|
// --primary: 0 0% 98%;
|
||||||
|
// --primary-foreground: 240 5.9% 10%;
|
||||||
|
// --secondary: 240 3.7% 15.9%;
|
||||||
|
// --secondary-foreground: 0 0% 98%;
|
||||||
|
// --muted: 240 3.7% 15.9%;
|
||||||
|
// --muted-foreground: 240 5% 64.9%;
|
||||||
|
// --accent: 240 3.7% 15.9%;
|
||||||
|
// --accent-foreground: 0 0% 98%;
|
||||||
|
// --destructive: 0 62.8% 30.6%;
|
||||||
|
// --destructive-foreground: 0 0% 98%;
|
||||||
|
// --border: 240 3.7% 15.9%;
|
||||||
|
// --input: 240 3.7% 15.9%;
|
||||||
|
// --ring: 240 4.9% 83.9%;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct Colors {
|
||||||
|
pub background: Hsla,
|
||||||
|
pub foreground: Hsla,
|
||||||
|
pub card: Hsla,
|
||||||
|
pub card_foreground: Hsla,
|
||||||
|
pub popover: Hsla,
|
||||||
|
pub popover_foreground: Hsla,
|
||||||
|
pub primary: Hsla,
|
||||||
|
pub primary_foreground: Hsla,
|
||||||
|
pub secondary: Hsla,
|
||||||
|
pub secondary_foreground: Hsla,
|
||||||
|
pub muted: Hsla,
|
||||||
|
pub muted_foreground: Hsla,
|
||||||
|
pub accent: Hsla,
|
||||||
|
pub accent_foreground: Hsla,
|
||||||
|
pub destructive: Hsla,
|
||||||
|
pub destructive_foreground: Hsla,
|
||||||
|
pub border: Hsla,
|
||||||
|
pub input: Hsla,
|
||||||
|
pub ring: Hsla,
|
||||||
|
pub radius: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Colors {
|
||||||
|
fn light() -> Colors {
|
||||||
|
Colors {
|
||||||
|
background: hsl(0.0, 0.0, 1.0),
|
||||||
|
foreground: hsl(240.0, 0.1, 0.039),
|
||||||
|
card: hsl(0.0, 0.0, 1.0),
|
||||||
|
card_foreground: hsl(240.0, 0.1, 0.039),
|
||||||
|
popover: hsl(0.0, 0.0, 1.0),
|
||||||
|
popover_foreground: hsl(240.0, 0.1, 0.039),
|
||||||
|
primary: hsl(240.0, 0.059, 0.1),
|
||||||
|
primary_foreground: hsl(0.0, 0.0, 0.98),
|
||||||
|
secondary: hsl(240.0, 0.048, 0.959),
|
||||||
|
secondary_foreground: hsl(240.0, 0.059, 0.1),
|
||||||
|
muted: hsl(240.0, 0.048, 0.959),
|
||||||
|
muted_foreground: hsl(240.0, 0.038, 0.461),
|
||||||
|
accent: hsl(240.0, 0.048, 0.959),
|
||||||
|
accent_foreground: hsl(240.0, 0.059, 0.1),
|
||||||
|
destructive: hsl(0.0, 0.842, 0.602),
|
||||||
|
destructive_foreground: hsl(0.0, 0.0, 0.98),
|
||||||
|
border: hsl(240.0, 0.059, 0.9),
|
||||||
|
input: hsl(240.0, 0.059, 0.9),
|
||||||
|
ring: hsl(240.0, 0.059, 0.1),
|
||||||
|
radius: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dark() -> Colors {
|
||||||
|
Colors {
|
||||||
|
background: hsl(240.0, 0.1, 0.039),
|
||||||
|
foreground: hsl(0.0, 0.0, 0.98),
|
||||||
|
card: hsl(240.0, 0.1, 0.039),
|
||||||
|
card_foreground: hsl(0.0, 0.0, 0.98),
|
||||||
|
popover: hsl(240.0, 0.1, 0.039),
|
||||||
|
popover_foreground: hsl(0.0, 0.0, 0.98),
|
||||||
|
primary: hsl(0.0, 0.0, 0.98),
|
||||||
|
primary_foreground: hsl(240.0, 0.059, 0.1),
|
||||||
|
secondary: hsl(240.0, 0.037, 0.159),
|
||||||
|
secondary_foreground: hsl(0.0, 0.0, 0.98),
|
||||||
|
muted: hsl(240.0, 0.037, 0.159),
|
||||||
|
muted_foreground: hsl(240.0, 0.05, 0.649),
|
||||||
|
accent: hsl(240.0, 0.037, 0.159),
|
||||||
|
accent_foreground: hsl(0.0, 0.0, 0.98),
|
||||||
|
destructive: hsl(0.0, 0.628, 0.306),
|
||||||
|
destructive_foreground: hsl(0.0, 0.0, 0.98),
|
||||||
|
border: hsl(240.0, 0.037, 0.159),
|
||||||
|
input: hsl(240.0, 0.037, 0.159),
|
||||||
|
ring: hsl(240.0, 0.049, 0.839),
|
||||||
|
radius: 0.0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
pub font_sans: SharedString,
|
pub background: Hsla,
|
||||||
pub font_mono: SharedString,
|
pub foreground: Hsla,
|
||||||
pub crust: Hsla,
|
pub card: Hsla,
|
||||||
pub text: Hsla,
|
pub card_foreground: Hsla,
|
||||||
pub base: Hsla,
|
pub popover: Hsla,
|
||||||
pub mantle: Hsla,
|
pub popover_foreground: Hsla,
|
||||||
pub green: Hsla,
|
pub primary: Hsla,
|
||||||
pub red: Hsla,
|
pub primary_foreground: Hsla,
|
||||||
pub blue: Hsla,
|
pub secondary: Hsla,
|
||||||
pub text_disabled: Hsla,
|
pub secondary_foreground: Hsla,
|
||||||
pub subtext1: Hsla,
|
pub muted: Hsla,
|
||||||
pub subtext0: Hsla,
|
pub muted_foreground: Hsla,
|
||||||
pub overlay2: Hsla,
|
pub accent: Hsla,
|
||||||
pub overlay1: Hsla,
|
pub accent_foreground: Hsla,
|
||||||
pub overlay0: Hsla,
|
pub destructive: Hsla,
|
||||||
pub surface2: Hsla,
|
pub destructive_foreground: Hsla,
|
||||||
pub surface1: Hsla,
|
pub border: Hsla,
|
||||||
pub surface0: Hsla,
|
pub input: Hsla,
|
||||||
pub lavender: Hsla,
|
pub ring: Hsla,
|
||||||
|
pub radius: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Global for Theme {}
|
impl Global for Theme {}
|
||||||
|
|
||||||
impl From<FlavorColors> for Theme {
|
impl From<Colors> for Theme {
|
||||||
fn from(colors: FlavorColors) -> Self {
|
fn from(colors: Colors) -> Self {
|
||||||
Theme {
|
Theme {
|
||||||
font_sans: "Inter".into(),
|
background: colors.background,
|
||||||
font_mono: "JetBrains Mono".into(),
|
foreground: colors.foreground,
|
||||||
crust: color_to_hsla(colors.crust),
|
card: colors.card,
|
||||||
text: color_to_hsla(colors.text),
|
card_foreground: colors.card_foreground,
|
||||||
base: color_to_hsla(colors.base),
|
popover: colors.popover,
|
||||||
mantle: color_to_hsla(colors.mantle),
|
popover_foreground: colors.popover_foreground,
|
||||||
green: color_to_hsla(colors.green),
|
primary: colors.primary,
|
||||||
red: color_to_hsla(colors.red),
|
primary_foreground: colors.primary_foreground,
|
||||||
blue: color_to_hsla(colors.blue),
|
secondary: colors.secondary,
|
||||||
subtext0: color_to_hsla(colors.subtext0),
|
secondary_foreground: colors.secondary_foreground,
|
||||||
subtext1: color_to_hsla(colors.subtext1),
|
muted: colors.muted,
|
||||||
text_disabled: color_to_hsla(colors.subtext0),
|
muted_foreground: colors.muted_foreground,
|
||||||
overlay0: color_to_hsla(colors.overlay0),
|
accent: colors.accent,
|
||||||
overlay1: color_to_hsla(colors.overlay1),
|
accent_foreground: colors.accent_foreground,
|
||||||
overlay2: color_to_hsla(colors.overlay2),
|
destructive: colors.destructive,
|
||||||
surface0: color_to_hsla(colors.surface0),
|
destructive_foreground: colors.destructive_foreground,
|
||||||
surface1: color_to_hsla(colors.surface1),
|
border: colors.border,
|
||||||
surface2: color_to_hsla(colors.surface2),
|
input: colors.input,
|
||||||
lavender: color_to_hsla(colors.lavender),
|
ring: colors.ring,
|
||||||
|
radius: colors.radius,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -71,7 +220,7 @@ pub enum ThemeMode {
|
||||||
|
|
||||||
impl Theme {
|
impl Theme {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::from(catppuccin::PALETTE.latte.colors)
|
Self::from(Colors::light())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
|
|
@ -79,12 +228,12 @@ impl Theme {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change(mode: ThemeMode, cx: &mut AppContext) {
|
pub fn change(mode: ThemeMode, cx: &mut AppContext) {
|
||||||
let flavour = match mode {
|
let colors = match mode {
|
||||||
ThemeMode::Light => catppuccin::PALETTE.latte,
|
ThemeMode::Light => Colors::light(),
|
||||||
ThemeMode::Dark => catppuccin::PALETTE.mocha,
|
ThemeMode::Dark => Colors::dark(),
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.set_global(Self::from(flavour.colors));
|
cx.set_global(Self::from(colors));
|
||||||
cx.refresh();
|
cx.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,7 @@
|
||||||
use gpui::{prelude::FluentBuilder, *};
|
use gpui::*;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ui::{
|
use ui::{button::Button, disableable::Clickable as _, story::Stories, theme::Theme};
|
||||||
button::Button,
|
|
||||||
disableable::Clickable as _,
|
|
||||||
story::Stories,
|
|
||||||
text_field::{self, TextField},
|
|
||||||
theme::Theme,
|
|
||||||
Color,
|
|
||||||
};
|
|
||||||
use util::ResultExt as _;
|
use util::ResultExt as _;
|
||||||
|
|
||||||
mod app_state;
|
mod app_state;
|
||||||
|
|
@ -101,7 +94,7 @@ impl Render for Workspace {
|
||||||
.flex_col()
|
.flex_col()
|
||||||
.size_full()
|
.size_full()
|
||||||
.p_4()
|
.p_4()
|
||||||
.bg(theme.base)
|
.bg(theme.background)
|
||||||
.gap_4()
|
.gap_4()
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue