114 lines
3.6 KiB
Rust
114 lines
3.6 KiB
Rust
use gpui::Hsla;
|
|
|
|
use crate::model::{AccentRoles, Color, ThemeColors, ThemeVariant};
|
|
|
|
fn hsla(color: Color) -> Hsla {
|
|
let packed = ((color.r as u32) << 24)
|
|
| ((color.g as u32) << 16)
|
|
| ((color.b as u32) << 8)
|
|
| color.a as u32;
|
|
Hsla::from(gpui::rgba(packed))
|
|
}
|
|
|
|
/// Accent roles resolved to [`Hsla`], with derived interaction states precomputed.
|
|
#[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,
|
|
pub hover: Hsla,
|
|
pub active: Hsla,
|
|
pub selected: Hsla,
|
|
/// Text guaranteed 4.5:1 readable on `wash`.
|
|
pub text_on_wash: Hsla,
|
|
/// Text guaranteed readable on the flat `danger` color.
|
|
pub on_danger: Hsla,
|
|
}
|
|
|
|
impl ResolvedAccentRoles {
|
|
pub fn resolve(accent: &AccentRoles, colors: &ThemeColors) -> Self {
|
|
let background = colors.background;
|
|
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),
|
|
hover: hsla(accent.primary.mix(background, 0.12)),
|
|
active: hsla(accent.primary.mix(background, 0.2)),
|
|
selected: hsla(accent.primary.mix(background, 0.28)),
|
|
text_on_wash: hsla(accent.primary.ensure_contrast(wash_background, 4.5)),
|
|
on_danger: hsla(colors.danger.best_on_color()),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// The `Hsla` snapshot components render from, rebuilt on every theme change.
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct ResolvedColors {
|
|
pub background: Hsla,
|
|
pub shell: Hsla,
|
|
pub raised: Hsla,
|
|
pub card: Hsla,
|
|
pub dialog: Hsla,
|
|
pub overlay: Hsla,
|
|
pub hover: Hsla,
|
|
pub active: Hsla,
|
|
pub border: Hsla,
|
|
pub border_strong: Hsla,
|
|
pub text: Hsla,
|
|
pub text_muted: Hsla,
|
|
pub text_faint: Hsla,
|
|
pub solid: Hsla,
|
|
pub on_solid: Hsla,
|
|
pub danger: Hsla,
|
|
pub danger_muted: Hsla,
|
|
pub warning: Hsla,
|
|
pub warning_muted: Hsla,
|
|
pub success: Hsla,
|
|
pub success_muted: Hsla,
|
|
pub input: Hsla,
|
|
pub cursor: Hsla,
|
|
pub diff_add: Hsla,
|
|
pub diff_delete: Hsla,
|
|
pub diff_hunk: Hsla,
|
|
}
|
|
|
|
impl ResolvedColors {
|
|
pub fn resolve(variant: &ThemeVariant) -> Self {
|
|
let colors = &variant.colors;
|
|
Self {
|
|
background: hsla(colors.background),
|
|
shell: hsla(colors.shell),
|
|
raised: hsla(colors.raised),
|
|
card: hsla(colors.card),
|
|
dialog: hsla(colors.dialog),
|
|
overlay: hsla(colors.overlay),
|
|
hover: hsla(colors.hover),
|
|
active: hsla(colors.active),
|
|
border: hsla(colors.border),
|
|
border_strong: hsla(colors.border_strong),
|
|
text: hsla(colors.text),
|
|
text_muted: hsla(colors.text_muted),
|
|
text_faint: hsla(colors.text_faint),
|
|
solid: hsla(colors.solid),
|
|
on_solid: hsla(colors.on_solid),
|
|
danger: hsla(colors.danger),
|
|
danger_muted: hsla(colors.danger_muted),
|
|
warning: hsla(colors.warning),
|
|
warning_muted: hsla(colors.warning_muted),
|
|
success: hsla(colors.success),
|
|
success_muted: hsla(colors.success_muted),
|
|
input: hsla(colors.input),
|
|
cursor: hsla(colors.cursor),
|
|
diff_add: hsla(colors.diff_add),
|
|
diff_delete: hsla(colors.diff_delete),
|
|
diff_hunk: hsla(colors.diff_hunk),
|
|
}
|
|
}
|
|
}
|