update theme

This commit is contained in:
2026-10-08 13:55:23 +07:00
parent f54f5f35a8
commit 16cd0ae903
14 changed files with 49 additions and 64 deletions
+9 -9
View File
@@ -241,7 +241,7 @@ fn coop_dark() -> ThemeVariant {
appearance: Appearance::Dark,
treatment: SurfaceTreatment::Frosted,
background: "#060606",
shell: "#0d0d0d",
shell: "#16161b",
raised: "#343438",
card: "#0e0e0e",
text: "#e8e8ea",
@@ -274,18 +274,18 @@ fn coop_light() -> ThemeVariant {
name: "Coop Light",
appearance: Appearance::Light,
treatment: SurfaceTreatment::Frosted,
background: "#ffffff",
shell: "#f3f3f5",
raised: "#ededf0",
background: "#fffdf4",
shell: "#f7f3e8",
raised: "#ede8d8",
card: "#ffffff",
text: "#303035",
muted: "#62626a",
faint: "#797981",
accent: "#a19200",
text: "#33302a",
muted: "#6d675a",
faint: "#87816f",
accent: "#FFE629",
danger: "#dc2626",
warning: "#a16207",
success: "#15803d",
terminal_background: "#fafafa",
terminal_background: "#fbf8ee",
ansi: ANSI_LIGHT,
syntax: [
"#6b7280", "#5b43e8", "#15803d", "#a16207", "#7e22ce", "#2563eb", "#be185d", "#303035",
+2 -2
View File
@@ -29,7 +29,7 @@ pub fn init(cx: &mut App) {
log::warn!("theme {}: {}", issue.variant_id, issue.message);
}
Theme::sync_system_appearance(None, cx);
Theme::change(Appearance::default(), None, cx);
Theme::sync_scrollbar_appearance(cx);
}
@@ -75,7 +75,7 @@ pub fn sync_base(cx: &mut App) {
tokens.destructive_foreground = accent.on_danger;
tokens.border = colors.border;
tokens.input = colors.input;
tokens.ring = accent.primary;
tokens.ring = accent.strong;
tokens.selection = accent.selection;
}
+20 -13
View File
@@ -109,10 +109,11 @@ impl Color {
}
pub fn best_on_color(self) -> Self {
if Self::WHITE.contrast(self) >= Self::BLACK.contrast(self) {
Self::WHITE
} else {
// Dark surfaces carry white text even where black would contrast more.
if self.luminance() > 0.3 {
Self::BLACK
} else {
Self::WHITE
}
}
@@ -275,7 +276,7 @@ impl AccentPreset {
pub fn color(self, appearance: Appearance) -> Color {
let (dark, light) = match self {
Self::Coop => ("#FFE629", "#a19200"),
Self::Coop => ("#FFE629", "#FFE629"),
Self::Orange => ("#fb923c", "#c2410c"),
Self::Amber => ("#fbbf24", "#a16207"),
Self::Green => ("#4ade80", "#15803d"),
@@ -320,11 +321,17 @@ pub struct AccentRoles {
impl AccentRoles {
pub fn derive(primary: Color, appearance: Appearance, background: Color) -> Self {
let primary = primary.ensure_contrast(background, 3.0);
// Light mode keeps the raw brand accent for fills; `strong` backs strokes at 3:1.
let (primary, mut strong) = if appearance.is_dark() {
let primary = primary.ensure_contrast(background, 3.0);
(primary, primary)
} else {
(primary, primary.ensure_contrast(background, 3.0))
};
let on = primary.best_on_color();
let mut strong = primary;
if on.contrast(strong) < 4.5 {
strong = strong.ensure_contrast(on, 4.5);
// 3:1 pairing so white-on-dark accents don't force the fill darker.
if on.contrast(strong) < 3.0 {
strong = strong.ensure_contrast(on, 3.0);
}
let light = primary.mix(
if appearance.is_dark() {
@@ -528,8 +535,8 @@ impl ThemeRegistry {
validate_contrast(
&mut issues,
variant,
"accent",
variant.accent.primary,
"accent-strong",
variant.accent.strong,
variant.colors.background,
3.0,
);
@@ -539,7 +546,7 @@ impl ThemeRegistry {
"on-accent",
variant.accent.on,
variant.accent.strong,
4.5,
3.0,
);
validate_contrast(
&mut issues,
@@ -667,11 +674,11 @@ mod tests {
for preset in AccentPreset::ALL {
let roles = AccentRoles::derive(preset.color(appearance), appearance, background);
assert!(
roles.primary.contrast(background) >= 3.0,
roles.strong.contrast(background) >= 3.0,
"{appearance:?} {preset:?}"
);
assert!(
roles.on.contrast(roles.strong) >= 4.5,
roles.on.contrast(roles.strong) >= 3.0,
"{appearance:?} {preset:?}"
);
}
+3
View File
@@ -14,6 +14,8 @@ fn hsla(color: Color) -> Hsla {
#[derive(Debug, Clone, Copy)]
pub struct ResolvedAccentRoles {
pub primary: Hsla,
/// Accent for strokes, icons, and text on the background; meets 3:1 contrast.
pub strong: Hsla,
pub wash: Hsla,
pub on: Hsla,
pub selection: Hsla,
@@ -32,6 +34,7 @@ impl ResolvedAccentRoles {
let wash_background = accent.wash.blend_over(background);
Self {
primary: hsla(accent.primary),
strong: hsla(accent.strong),
wash: hsla(accent.wash),
on: hsla(accent.on),
selection: hsla(accent.selection),
-18
View File
@@ -10,15 +10,6 @@ use crate::model::{
use crate::resolved::{ResolvedAccentRoles, ResolvedColors};
use crate::{NotificationSettings, PlatformKind, ScrollbarMode, sync_base};
impl From<gpui::WindowAppearance> for Appearance {
fn from(appearance: gpui::WindowAppearance) -> Self {
match appearance {
gpui::WindowAppearance::Dark | gpui::WindowAppearance::VibrantDark => Self::Dark,
gpui::WindowAppearance::Light | gpui::WindowAppearance::VibrantLight => Self::Light,
}
}
}
#[derive(Debug, Clone)]
pub struct Theme {
pub variant: Arc<ThemeVariant>,
@@ -99,15 +90,6 @@ impl Theme {
}
}
pub fn sync_system_appearance(window: Option<&mut Window>, cx: &mut App) {
let appearance = window
.as_ref()
.map(|window| window.appearance())
.unwrap_or_else(|| cx.window_appearance());
Self::change(appearance, window, cx);
}
pub fn sync_scrollbar_appearance(cx: &mut App) {
Theme::global_mut(cx).scrollbar_mode = if cx.should_auto_hide_scrollbars() {
ScrollbarMode::Scrolling