feat: impl catppuccin theme

This commit is contained in:
2026-04-26 00:46:11 +01:00
parent dab18c40c5
commit 3b0fe3e311
6 changed files with 118 additions and 58 deletions

View File

@@ -8,6 +8,7 @@ use crate::{api, app};
pub struct Global { pub struct Global {
pub safe_area: gpui::Bounds<gpui::Pixels>, pub safe_area: gpui::Bounds<gpui::Pixels>,
pub theme_family: theme::ThemeFamily,
pub current_theme: theme::Theme, pub current_theme: theme::Theme,
pub rng: rand::prelude::ThreadRng, pub rng: rand::prelude::ThreadRng,
} }
@@ -18,7 +19,9 @@ impl Chrome {
pub fn new(window: &mut gpui::Window, cx: &mut gpui::Context<Self>) -> Self { pub fn new(window: &mut gpui::Window, cx: &mut gpui::Context<Self>) -> Self {
cx.observe_window_appearance(window, |_, window, cx| { cx.observe_window_appearance(window, |_, window, cx| {
cx.update_global::<app::Global, ()>(|global, cx| { cx.update_global::<app::Global, ()>(|global, cx| {
global.current_theme = window.appearance().into(); global.current_theme = global
.theme_family
.theme_for_appearance(window.appearance());
cx.notify(); cx.notify();
}); });
}) })

View File

@@ -11,6 +11,7 @@ pub const fn hex(hex: u32) -> Rgba {
} }
} }
#[allow(dead_code)]
pub const fn neutral(shade: u16) -> Rgba { pub const fn neutral(shade: u16) -> Rgba {
match shade { match shade {
50 => hex(0xfafafa), 50 => hex(0xfafafa),
@@ -28,6 +29,7 @@ pub const fn neutral(shade: u16) -> Rgba {
} }
} }
#[allow(dead_code)]
pub const fn violet(shade: u16) -> Rgba { pub const fn violet(shade: u16) -> Rgba {
match shade { match shade {
50 => hex(0xf5f3ff), 50 => hex(0xf5f3ff),
@@ -45,6 +47,7 @@ pub const fn violet(shade: u16) -> Rgba {
} }
} }
#[allow(dead_code)]
pub const fn amber(shade: u16) -> Rgba { pub const fn amber(shade: u16) -> Rgba {
match shade { match shade {
50 => hex(0xfffbeb), 50 => hex(0xfffbeb),
@@ -62,6 +65,7 @@ pub const fn amber(shade: u16) -> Rgba {
} }
} }
#[allow(dead_code)]
pub const fn red(shade: u16) -> Rgba { pub const fn red(shade: u16) -> Rgba {
match shade { match shade {
50 => hex(0xfef2f2), 50 => hex(0xfef2f2),

View File

@@ -1,6 +1,6 @@
use gpui::{div, prelude::*}; use gpui::{div, prelude::*};
use crate::{app, theme::Variant}; use crate::app;
pub struct Screen { pub struct Screen {
pub text: gpui::SharedString, pub text: gpui::SharedString,

View File

@@ -49,9 +49,11 @@ fn setup_application(cx: &mut gpui::App) {
}, },
}); });
let theme_family = theme::ThemeFamily::default();
let global = app::Global { let global = app::Global {
safe_area: bounds(point(px(0.), px(0.)), size(px(72.), px(12.))), safe_area: bounds(point(px(0.), px(0.)), size(px(72.), px(12.))),
current_theme: cx.window_appearance().into(), theme_family,
current_theme: theme_family.theme_for_appearance(cx.window_appearance()),
rng: rand::rng(), rng: rand::rng(),
}; };

View File

@@ -46,7 +46,9 @@ pub fn open_window(screen: Screen, cx: &mut gpui::App) -> anyhow::Result<()> {
cx.new(|cx| { cx.new(|cx| {
cx.observe_window_appearance(window, |_, window, cx| { cx.observe_window_appearance(window, |_, window, cx| {
cx.update_global::<app::Global, ()>(|global, cx| { cx.update_global::<app::Global, ()>(|global, cx| {
global.current_theme = window.appearance().into(); global.current_theme = global
.theme_family
.theme_for_appearance(window.appearance());
cx.notify(); cx.notify();
}); });
}) })

View File

@@ -1,6 +1,6 @@
use gpui::Rgba; use gpui::Rgba;
use crate::colors::{amber, hex, neutral, red, violet}; use crate::colors::hex;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ThemeMode { pub enum ThemeMode {
@@ -19,7 +19,7 @@ pub struct Theme {
impl Default for Theme { impl Default for Theme {
fn default() -> Self { fn default() -> Self {
Variant::default().theme() ThemeFamily::default().theme(ThemeMode::default())
} }
} }
@@ -41,83 +41,132 @@ pub struct ThemeColors {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[allow(dead_code)] #[allow(dead_code)]
pub enum Variant { pub enum ThemeFamily {
VioletLight,
#[default] #[default]
VioletDark, Catppuccin,
} }
pub(crate) fn current(cx: &gpui::App) -> &Theme { #[allow(dead_code)]
cx.global::<Theme>() impl ThemeFamily {
} pub const ALL: [Self; 1] = [Self::Catppuccin];
impl Variant { pub const fn id(self) -> &'static str {
#[allow(dead_code)] match self {
pub const ALL: [Self; 2] = [Self::VioletLight, Self::VioletDark]; Self::Catppuccin => "catppuccin",
}
}
pub const fn label(self) -> &'static str { pub const fn label(self) -> &'static str {
match self { match self {
Self::VioletLight => "Violet Light", Self::Catppuccin => "Catppuccin",
Self::VioletDark => "Violet Dark", }
}
pub const fn variant(self, mode: ThemeMode) -> ThemeVariant {
match (self, mode) {
(Self::Catppuccin, ThemeMode::Light) => ThemeVariant::CatppuccinLatte,
(Self::Catppuccin, ThemeMode::Dark) => ThemeVariant::CatppuccinMocha,
}
}
pub const fn theme(self, mode: ThemeMode) -> Theme {
self.variant(mode).theme()
}
pub fn theme_for_appearance(self, appearance: gpui::WindowAppearance) -> Theme {
self.theme(appearance.into())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[allow(dead_code)]
pub enum ThemeVariant {
CatppuccinLatte,
#[default]
CatppuccinMocha,
}
#[allow(dead_code)]
impl ThemeVariant {
pub const ALL: [Self; 2] = [Self::CatppuccinLatte, Self::CatppuccinMocha];
pub const fn family(self) -> ThemeFamily {
match self {
Self::CatppuccinLatte | Self::CatppuccinMocha => ThemeFamily::Catppuccin,
}
}
pub const fn mode(self) -> ThemeMode {
match self {
Self::CatppuccinLatte => ThemeMode::Light,
Self::CatppuccinMocha => ThemeMode::Dark,
}
}
pub const fn label(self) -> &'static str {
match self {
Self::CatppuccinLatte => "Catppuccin Latte",
Self::CatppuccinMocha => "Catppuccin Mocha",
} }
} }
pub const fn theme(self) -> Theme { pub const fn theme(self) -> Theme {
match self { match self {
Self::VioletLight => Theme { Self::CatppuccinLatte => Theme {
id: "violet-light", id: "catppuccin-latte",
name: "Violet Light", name: "Catppuccin Latte",
mode: ThemeMode::Light, mode: ThemeMode::Light,
colors: ThemeColors { colors: ThemeColors {
background: neutral(50), background: hex(0xeff1f5),
surface: neutral(100), surface: hex(0xe6e9ef),
surface_elevated: neutral(200), surface_elevated: hex(0xdce0e8),
border: neutral(200), border: hex(0xccd0da),
text: neutral(900), text: hex(0x4c4f69),
text_muted: neutral(600), text_muted: hex(0x6c6f85),
accent: violet(600), accent: hex(0x8839ef),
accent_hover: violet(500), accent_hover: hex(0x7287fd),
accent_text: neutral(100), accent_text: hex(0xeff1f5),
success: hex(0x16a34a), success: hex(0x40a02b),
warning: amber(600), warning: hex(0xdf8e1d),
danger: red(600), danger: hex(0xd20f39),
}, },
}, },
Self::VioletDark => Theme { Self::CatppuccinMocha => Theme {
id: "violet-dark", id: "catppuccin-mocha",
name: "Violet Dark", name: "Catppuccin Mocha",
mode: ThemeMode::Dark, mode: ThemeMode::Dark,
colors: ThemeColors { colors: ThemeColors {
background: neutral(950), background: hex(0x1e1e2e),
surface: neutral(900), surface: hex(0x181825),
surface_elevated: neutral(800), surface_elevated: hex(0x313244),
border: neutral(800), border: hex(0x45475a),
text: neutral(50), text: hex(0xcdd6f4),
text_muted: neutral(400), text_muted: hex(0xa6adc8),
accent: violet(600), accent: hex(0xcba6f7),
accent_hover: violet(300), accent_hover: hex(0xb4befe),
accent_text: neutral(100), accent_text: hex(0x1e1e2e),
success: hex(0x22c55e), success: hex(0xa6e3a1),
warning: amber(500), warning: hex(0xf9e2af),
danger: red(500), danger: hex(0xf38ba8),
}, },
}, },
} }
} }
} }
impl From<gpui::WindowAppearance> for ThemeMode {
fn from(value: gpui::WindowAppearance) -> Self {
match value {
gpui::WindowAppearance::Light | gpui::WindowAppearance::VibrantLight => {
ThemeMode::Light
}
gpui::WindowAppearance::Dark | gpui::WindowAppearance::VibrantDark => ThemeMode::Dark,
}
}
}
impl From<gpui::WindowAppearance> for Theme { impl From<gpui::WindowAppearance> for Theme {
fn from(value: gpui::WindowAppearance) -> Self { fn from(value: gpui::WindowAppearance) -> Self {
let variant = match value { ThemeFamily::default().theme(value.into())
gpui::WindowAppearance::Light | gpui::WindowAppearance::VibrantLight => {
Variant::VioletLight
}
gpui::WindowAppearance::Dark | gpui::WindowAppearance::VibrantDark => {
Variant::VioletDark
}
};
variant.theme()
} }
} }
impl gpui::Global for Theme {}