refactor: updates for buttons and checkboxes

This commit is contained in:
Ashley Wulber 2023-08-07 13:48:01 -04:00 committed by Ashley Wulber
parent dae262f466
commit ff83f893ef
4 changed files with 159 additions and 114 deletions

View file

@ -70,6 +70,10 @@ pub struct Component<C> {
pub disabled: C,
/// the color of text in the widget when it is disabled
pub on_disabled: C,
/// the color of the border for the widget
pub border: C,
/// the color of the border for the widget when it is disabled
pub disabled_border: C,
}
impl<C> Component<C>
@ -109,6 +113,8 @@ where
on: self.on.into(),
disabled: self.disabled.into(),
on_disabled: self.on_disabled.into(),
border: self.border.into(),
disabled_border: self.disabled_border.into(),
}
}
@ -124,7 +130,7 @@ where
let base: Srgba = base.into();
let mut base_50 = base.clone();
base_50.alpha = 0.5;
base_50.alpha *= 0.5;
let on_20 = neutral.clone();
let mut on_50 = on_20.clone();
@ -142,6 +148,8 @@ where
disabled: base_50.into(),
on_disabled: on_50.into(),
focus: accent,
border: base.into(),
disabled_border: base_50.into(),
}
}
@ -152,6 +160,7 @@ where
accent: C,
on_component: C,
is_high_contrast: bool,
border: C,
) -> Self {
let component_state_overlay = component_state_overlay.clone().into();
let mut component_state_overlay_10 = component_state_overlay.clone();
@ -161,7 +170,7 @@ where
let base = base.into();
let mut base_50 = base.clone();
base_50.alpha = 0.5;
base_50.alpha *= 0.5;
let mut on_20 = on_component.clone().into();
let mut on_50 = on_20.clone();
@ -169,6 +178,10 @@ where
on_20.alpha = 0.2;
on_50.alpha = 0.5;
let border = border.into();
let mut disabled_border = border;
disabled_border.alpha *= 0.5;
Component {
base: base.clone().into(),
hover: over(component_state_overlay_10, base).into(),
@ -184,6 +197,8 @@ where
on: on_component.clone(),
disabled: base_50.into(),
on_disabled: on_50.into(),
border: border.into(),
disabled_border: disabled_border.into(),
}
}
}

View file

@ -4,8 +4,8 @@ use crate::{
};
use cosmic_config::{Config, ConfigGet, ConfigSet, CosmicConfigEntry};
use palette::{IntoColor, Srgb, Srgba};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::{fmt, num::NonZeroUsize};
use serde::{Deserialize, Serialize};
use std::num::NonZeroUsize;
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
/// Theme layer type
@ -38,6 +38,8 @@ pub struct Theme<C> {
pub destructive: Component<C>,
/// warning element colors
pub warning: Component<C>,
/// button component styling
pub button: Component<C>,
/// palette
pub palette: CosmicPaletteInner<C>,
/// spacing
@ -162,10 +164,27 @@ impl<C> Theme<C> {
}
}
impl<C> Theme<C>
where
C: Clone + fmt::Debug + Default + Into<Srgba> + From<Srgba> + Serialize + DeserializeOwned,
{
impl Theme<Srgba> {
/// get the built in light theme
pub fn light_default() -> Self {
LIGHT_PALETTE.clone().into()
}
/// get the built in dark theme
pub fn dark_default() -> Self {
DARK_PALETTE.clone().into()
}
/// get the built in high contrast dark theme
pub fn high_contrast_dark_default() -> Self {
CosmicPalette::HighContrastDark(DARK_PALETTE.as_ref().clone()).into()
}
/// get the built in high contrast light theme
pub fn high_contrast_light_default() -> Self {
CosmicPalette::HighContrastLight(LIGHT_PALETTE.as_ref().clone()).into()
}
/// Convert the theme to a high-contrast variant
pub fn to_high_contrast(&self) -> Self {
todo!();
@ -174,134 +193,142 @@ where
// TODO convenient getter functions for each named color variable
/// get @accent_color
pub fn accent_color(&self) -> Srgba {
self.accent.base.clone().into()
self.accent.base.clone()
}
/// get @success_color
pub fn success_color(&self) -> Srgba {
self.success.base.clone().into()
self.success.base.clone()
}
/// get @destructive_color
pub fn destructive_color(&self) -> Srgba {
self.destructive.base.clone().into()
self.destructive.base.clone()
}
/// get @warning_color
pub fn warning_color(&self) -> Srgba {
self.warning.base.clone().into()
self.warning.base.clone()
}
// Containers
/// get @bg_color
pub fn bg_color(&self) -> Srgba {
self.background.base.clone().into()
self.background.base.clone()
}
/// get @bg_component_color
pub fn bg_component_color(&self) -> Srgba {
self.background.component.base.clone().into()
self.background.component.base.clone()
}
/// get @primary_container_color
pub fn primary_container_color(&self) -> Srgba {
self.primary.base.clone().into()
self.primary.base.clone()
}
/// get @primary_component_color
pub fn primary_component_color(&self) -> Srgba {
self.primary.component.base.clone().into()
self.primary.component.base.clone()
}
/// get @secondary_container_color
pub fn secondary_container_color(&self) -> Srgba {
self.secondary.base.clone().into()
self.secondary.base.clone()
}
/// get @secondary_component_color
pub fn secondary_component_color(&self) -> Srgba {
self.secondary.component.base.clone().into()
self.secondary.component.base.clone()
}
/// get @button_bg_color
pub fn button_bg_color(&self) -> Srgba {
self.button.base.clone()
}
// Text
/// get @on_bg_color
pub fn on_bg_color(&self) -> Srgba {
self.background.on.clone().into()
self.background.on.clone()
}
/// get @on_bg_component_color
pub fn on_bg_component_color(&self) -> Srgba {
self.background.component.on.clone().into()
self.background.component.on.clone()
}
/// get @on_primary_color
pub fn on_primary_container_color(&self) -> Srgba {
self.primary.on.clone().into()
self.primary.on.clone()
}
/// get @on_primary_component_color
pub fn on_primary_component_color(&self) -> Srgba {
self.primary.component.on.clone().into()
self.primary.component.on.clone()
}
/// get @on_secondary_color
pub fn on_secondary_container_color(&self) -> Srgba {
self.secondary.on.clone().into()
self.secondary.on.clone()
}
/// get @on_secondary_component_color
pub fn on_secondary_component_color(&self) -> Srgba {
self.secondary.component.on.clone().into()
self.secondary.component.on.clone()
}
/// get @accent_text_color
pub fn accent_text_color(&self) -> Srgba {
self.accent.base.clone().into()
self.accent.base.clone()
}
/// get @success_text_color
pub fn success_text_color(&self) -> Srgba {
self.success.base.clone().into()
self.success.base.clone()
}
/// get @warning_text_color
pub fn warning_text_color(&self) -> Srgba {
self.warning.base.clone().into()
self.warning.base.clone()
}
/// get @destructive_text_color
pub fn destructive_text_color(&self) -> Srgba {
self.destructive.base.clone().into()
self.destructive.base.clone()
}
/// get @on_accent_color
pub fn on_accent_color(&self) -> Srgba {
self.accent.on.clone().into()
self.accent.on.clone()
}
/// get @on_success_color
pub fn on_success_color(&self) -> Srgba {
self.success.on.clone().into()
self.success.on.clone()
}
/// get @oon_warning_color
pub fn on_warning_color(&self) -> Srgba {
self.warning.on.clone().into()
self.warning.on.clone()
}
/// get @on_destructive_color
pub fn on_destructive_color(&self) -> Srgba {
self.destructive.on.clone().into()
self.destructive.on.clone()
}
/// get @button_color
pub fn button_color(&self) -> Srgba {
self.button.on.clone()
}
// Borders and Dividers
/// get @bg_divider
pub fn bg_divider(&self) -> Srgba {
self.background.divider.clone().into()
self.background.divider.clone()
}
/// get @bg_component_divider
pub fn bg_component_divider(&self) -> Srgba {
self.background.component.divider.clone().into()
self.background.component.divider.clone()
}
/// get @primary_container_divider
pub fn primary_container_divider(&self) -> Srgba {
self.primary.divider.clone().into()
self.primary.divider.clone()
}
/// get @primary_component_divider
pub fn primary_component_divider(&self) -> Srgba {
self.primary.component.divider.clone().into()
self.primary.component.divider.clone()
}
/// get @secondary_container_divider
pub fn secondary_container_divider(&self) -> Srgba {
self.secondary.divider.clone().into()
self.secondary.divider.clone()
}
/// get @secondary_component_divider
pub fn secondary_component_divider(&self) -> Srgba {
self.secondary.component.divider.clone().into()
/// get @button_divider
pub fn button_divider(&self) -> Srgba {
self.button.divider.clone()
}
/// get @window_header_bg
pub fn window_header_bg(&self) -> Srgba {
self.background.base.clone().into()
self.background.base.clone()
}
/// get @space_none
@ -371,28 +398,6 @@ where
}
}
impl Theme<Srgba> {
/// get the built in light theme
pub fn light_default() -> Self {
LIGHT_PALETTE.clone().into()
}
/// get the built in dark theme
pub fn dark_default() -> Self {
DARK_PALETTE.clone().into()
}
/// get the built in high contrast dark theme
pub fn high_contrast_dark_default() -> Self {
CosmicPalette::HighContrastDark(DARK_PALETTE.as_ref().clone()).into()
}
/// get the built in high contrast light theme
pub fn high_contrast_light_default() -> Self {
CosmicPalette::HighContrastLight(LIGHT_PALETTE.as_ref().clone()).into()
}
}
impl<C> From<CosmicPalette<C>> for Theme<Srgba>
where
CosmicPalette<C>: Into<CosmicPalette<Srgba>>,
@ -643,6 +648,7 @@ impl ThemeBuilder {
accent.clone(),
on_bg_component,
is_high_contrast,
p_ref.neutral_8,
);
let primary_index = color_index(primary_container_bg, step_array.len());
@ -661,6 +667,7 @@ impl ThemeBuilder {
accent.clone(),
on_primary_component,
is_high_contrast,
p_ref.neutral_8,
);
let secondary_index = color_index(secondary_container_bg, step_array.len());
@ -679,7 +686,22 @@ impl ThemeBuilder {
accent.clone(),
on_secondary_component,
is_high_contrast,
p_ref.neutral_8,
);
let neutral_7 = p_ref.neutral_7;
let mut button_bg = neutral_7;
button_bg.alpha = 0.25;
let neutral_10 = p_ref.neutral_10;
let mut button_hover_overlay = neutral_10;
button_hover_overlay.alpha = 0.10;
let mut button_press_overlay = neutral_10;
button_press_overlay.alpha = 0.20;
let mut button_disabled_bg = button_bg;
button_disabled_bg.alpha *= 0.5;
let button_border = p_ref.neutral_8.clone();
let mut button_disabled_border = button_border;
button_disabled_border.alpha *= 0.5;
let mut theme: Theme<Srgba> = Theme {
name: palette.name().to_string(),
@ -736,6 +758,14 @@ impl ThemeBuilder {
p_ref.neutral_0.to_owned(),
accent.clone(),
),
button: Component::component(
button_bg,
p_ref.neutral_10,
accent,
p_ref.neutral_9,
is_high_contrast,
p_ref.neutral_8,
),
palette: palette.inner(),
spacing,
corner_radii,

View file

@ -492,7 +492,7 @@ impl State {
))
.layer(cosmic::cosmic_theme::Layer::Secondary)
.padding(16)
.style(cosmic::theme::Container::Secondary)
.style(cosmic::theme::Container::Background)
.into(),
text_input(
"Type to search apps or type “?” for more options...",

View file

@ -62,6 +62,8 @@ lazy_static::lazy_static! {
on: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
on_disabled: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
divider: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
border: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
disabled_border: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
};
}
@ -355,69 +357,69 @@ impl checkbox::StyleSheet for Theme {
type Style = Checkbox;
fn active(&self, style: &Self::Style, is_checked: bool) -> checkbox::Appearance {
let palette = self.cosmic();
let neutral_7 = palette.palette.neutral_10;
let cosmic = self.cosmic();
let corners = &cosmic.corner_radii;
match style {
Checkbox::Primary => checkbox::Appearance {
background: Background::Color(if is_checked {
palette.accent.base.into()
cosmic.accent.base.into()
} else {
palette.background.base.into()
cosmic.button.base.into()
}),
icon_color: palette.accent.on.into(),
border_radius: 4.0.into(),
icon_color: cosmic.accent.on.into(),
border_radius: corners.radius_xs.into(),
border_width: if is_checked { 0.0 } else { 1.0 },
border_color: if is_checked {
palette.accent.base
cosmic.accent.base
} else {
neutral_7
cosmic.button.border
}
.into(),
text_color: None,
},
Checkbox::Secondary => checkbox::Appearance {
background: Background::Color(if is_checked {
palette.background.component.base.into()
cosmic.background.component.base.into()
} else {
palette.background.base.into()
cosmic.background.base.into()
}),
icon_color: palette.background.on.into(),
border_radius: 4.0.into(),
icon_color: cosmic.background.on.into(),
border_radius: corners.radius_xs.into(),
border_width: if is_checked { 0.0 } else { 1.0 },
border_color: neutral_7.into(),
border_color: cosmic.button.border.into(),
text_color: None,
},
Checkbox::Success => checkbox::Appearance {
background: Background::Color(if is_checked {
palette.success.base.into()
cosmic.success.base.into()
} else {
palette.background.base.into()
cosmic.button.base.into()
}),
icon_color: palette.success.on.into(),
border_radius: 4.0.into(),
icon_color: cosmic.success.on.into(),
border_radius: corners.radius_xs.into(),
border_width: if is_checked { 0.0 } else { 1.0 },
border_color: if is_checked {
palette.success.base
cosmic.success.base
} else {
neutral_7
cosmic.button.border
}
.into(),
text_color: None,
},
Checkbox::Danger => checkbox::Appearance {
background: Background::Color(if is_checked {
palette.destructive.base.into()
cosmic.destructive.base.into()
} else {
palette.background.base.into()
cosmic.button.base.into()
}),
icon_color: palette.destructive.on.into(),
border_radius: 4.0.into(),
icon_color: cosmic.destructive.on.into(),
border_radius: corners.radius_xs.into(),
border_width: if is_checked { 0.0 } else { 1.0 },
border_color: if is_checked {
palette.destructive.base
cosmic.destructive.base
} else {
neutral_7
cosmic.button.border
}
.into(),
text_color: None,
@ -426,25 +428,23 @@ impl checkbox::StyleSheet for Theme {
}
fn hovered(&self, style: &Self::Style, is_checked: bool) -> checkbox::Appearance {
let palette = self.cosmic();
let mut neutral_10 = palette.palette.neutral_10;
let neutral_7 = palette.palette.neutral_10;
let cosmic = self.cosmic();
let corners = &cosmic.corner_radii;
neutral_10.alpha = 0.1;
match style {
Checkbox::Primary => checkbox::Appearance {
background: Background::Color(if is_checked {
palette.accent.base.into()
cosmic.accent.base.into()
} else {
neutral_10.into()
cosmic.button.base.into()
}),
icon_color: palette.accent.on.into(),
border_radius: 4.0.into(),
icon_color: cosmic.accent.on.into(),
border_radius: corners.radius_xs.into(),
border_width: if is_checked { 0.0 } else { 1.0 },
border_color: if is_checked {
palette.accent.base
cosmic.accent.base
} else {
neutral_7
cosmic.button.border
}
.into(),
text_color: None,
@ -453,49 +453,49 @@ impl checkbox::StyleSheet for Theme {
background: Background::Color(if is_checked {
self.current_container().base.into()
} else {
neutral_10.into()
cosmic.button.base.into()
}),
icon_color: self.current_container().on.into(),
border_radius: 4.0.into(),
border_radius: corners.radius_xs.into(),
border_width: if is_checked { 0.0 } else { 1.0 },
border_color: if is_checked {
self.current_container().base
} else {
neutral_7
cosmic.button.border
}
.into(),
text_color: None,
},
Checkbox::Success => checkbox::Appearance {
background: Background::Color(if is_checked {
palette.success.base.into()
cosmic.success.base.into()
} else {
neutral_10.into()
cosmic.button.base.into()
}),
icon_color: palette.success.on.into(),
border_radius: 4.0.into(),
icon_color: cosmic.success.on.into(),
border_radius: corners.radius_xs.into(),
border_width: if is_checked { 0.0 } else { 1.0 },
border_color: if is_checked {
palette.success.base
cosmic.success.base
} else {
neutral_7
cosmic.button.border
}
.into(),
text_color: None,
},
Checkbox::Danger => checkbox::Appearance {
background: Background::Color(if is_checked {
palette.destructive.base.into()
cosmic.destructive.base.into()
} else {
neutral_10.into()
cosmic.button.base.into()
}),
icon_color: palette.destructive.on.into(),
border_radius: 4.0.into(),
icon_color: cosmic.destructive.on.into(),
border_radius: corners.radius_xs.into(),
border_width: if is_checked { 0.0 } else { 1.0 },
border_color: if is_checked {
palette.destructive.base
cosmic.destructive.base
} else {
neutral_7
cosmic.button.border
}
.into(),
text_color: None,