feat: improve accent_text for low contrast accent colors.

This commit is contained in:
Ashley Wulber 2025-02-17 01:17:52 -05:00 • committed by Michael Murphy
parent 580db26868
commit 25bf8f60cc
2 changed files with 108 additions and 58 deletions

View file

@ -1,11 +1,11 @@
use crate::{ use crate::{
composite::over, composite::over,
steps::{color_index, get_surface_color, get_text, steps}, steps::{color_index, get_index, get_surface_color, get_text, steps},
Component, Container, CornerRadii, CosmicPalette, CosmicPaletteInner, Spacing, ThemeMode, Component, Container, CornerRadii, CosmicPalette, CosmicPaletteInner, Spacing, ThemeMode,
DARK_PALETTE, LIGHT_PALETTE, NAME, DARK_PALETTE, LIGHT_PALETTE, NAME,
}; };
use cosmic_config::{Config, CosmicConfigEntry}; use cosmic_config::{Config, CosmicConfigEntry};
use palette::{rgb::Rgb, IntoColor, Oklcha, Srgb, Srgba}; use palette::{color_difference::Wcag21RelativeContrast, rgb::Rgb, IntoColor, Oklcha, Srgb, Srgba};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
@ -97,6 +97,9 @@ pub struct Theme {
pub is_frosted: bool, pub is_frosted: bool,
/// shade color for dialogs /// shade color for dialogs
pub shade: Srgba, pub shade: Srgba,
/// accent text colors
/// If None, accent base color is the accent text color.
pub accent_text: Option<Srgba>,
} }
impl Default for Theme { impl Default for Theme {
@ -276,7 +279,7 @@ impl Theme {
#[allow(clippy::doc_markdown)] #[allow(clippy::doc_markdown)]
/// get @accent_text_color /// get @accent_text_color
pub fn accent_text_color(&self) -> Srgba { pub fn accent_text_color(&self) -> Srgba {
self.accent.base self.accent_text.unwrap_or(self.accent.base)
} }
#[must_use] #[must_use]
#[allow(clippy::doc_markdown)] #[allow(clippy::doc_markdown)]
@ -847,39 +850,7 @@ impl ThemeBuilder {
text_steps_array.as_ref(), text_steps_array.as_ref(),
); );
let mut theme: Theme = Theme { let primary = {
name: palette.name().to_string(),
shade: if palette.is_dark() {
Srgba::new(0., 0., 0., 0.32)
} else {
Srgba::new(0., 0., 0., 0.08)
},
background: Container::new(
Component::component(
bg_component,
accent,
on_bg_component,
component_hovered_overlay,
component_pressed_overlay,
is_high_contrast,
p_ref.neutral_8,
),
bg,
get_text(
bg_index,
&step_array,
&p_ref.neutral_8,
text_steps_array.as_ref(),
),
get_surface_color(
bg_index,
5,
&neutral_steps,
bg_index <= 65,
&p_ref.neutral_6,
),
),
primary: {
let container_bg = if let Some(primary_container_bg_color) = primary_container_bg { let container_bg = if let Some(primary_container_bg_color) = primary_container_bg {
primary_container_bg_color primary_container_bg_color
} else { } else {
@ -932,7 +903,85 @@ impl ThemeBuilder {
); );
container container
};
let accent_text = if is_dark {
(primary.base.relative_contrast(accent.color) < 4.).then(|| {
let step_array = steps(accent, NonZeroUsize::new(100).unwrap());
let primary_color_index = color_index(primary.base, 100);
let steps = if is_high_contrast { 60 } else { 50 };
let accent_text = get_surface_color(
primary_color_index,
steps,
&step_array,
is_dark,
&Srgba::new(1., 1., 1., 1.),
);
if primary.base.relative_contrast(accent_text.color) < 4. {
Srgba::new(1., 1., 1., 1.)
} else {
accent_text
}
})
} else {
let darkest = if bg.relative_luminance().luma < primary.base.relative_luminance().luma {
bg
} else {
primary.base
};
(darkest.relative_contrast(accent.color) < 4.).then(|| {
let step_array = steps(accent, NonZeroUsize::new(100).unwrap());
let primary_color_index = color_index(darkest, 100);
let steps = if is_high_contrast { 60 } else { 50 };
let accent_text = get_surface_color(
primary_color_index,
steps,
&step_array,
is_dark,
&Srgba::new(1., 1., 1., 1.),
);
if darkest.relative_contrast(accent_text.color) < 4. {
Srgba::new(0., 0., 0., 1.)
} else {
accent_text
}
})
};
let mut theme: Theme = Theme {
name: palette.name().to_string(),
shade: if palette.is_dark() {
Srgba::new(0., 0., 0., 0.32)
} else {
Srgba::new(0., 0., 0., 0.08)
}, },
background: Container::new(
Component::component(
bg_component,
accent,
on_bg_component,
component_hovered_overlay,
component_pressed_overlay,
is_high_contrast,
p_ref.neutral_8,
),
bg,
get_text(
bg_index,
&step_array,
&p_ref.neutral_8,
text_steps_array.as_ref(),
),
get_surface_color(
bg_index,
5,
&neutral_steps,
bg_index <= 65,
&p_ref.neutral_6,
),
),
primary,
secondary: { secondary: {
let container_bg = if let Some(secondary_container_bg) = secondary_container_bg { let container_bg = if let Some(secondary_container_bg) = secondary_container_bg {
secondary_container_bg secondary_container_bg
@ -1098,6 +1147,7 @@ impl ThemeBuilder {
active_hint, active_hint,
window_hint, window_hint,
is_frosted, is_frosted,
accent_text,
}; };
theme.spacing = spacing; theme.spacing = spacing;
theme.corner_radii = corner_radii; theme.corner_radii = corner_radii;

2
iced

@ -1 +1 @@
Subproject commit 7b5d3057c2499ae691c1ececd6062d97c21d09da Subproject commit 654f3c33b54679c06c041be6eea2c03f6d7cfdce