WIP: continued improvements to skinning

This commit is contained in:
Will McCormick 2026-03-26 15:58:13 -04:00
parent 3bfc65d634
commit 551565cdd8
26 changed files with 258 additions and 187 deletions

View file

@ -32,6 +32,7 @@ pub enum Button {
MenuItem,
MenuRoot,
NavToggle,
Secondary,
#[default]
Standard,
Suggested,
@ -52,14 +53,32 @@ pub fn appearance(
let mut appearance = Style::new();
let hc = theme.theme_type.is_high_contrast();
match style {
Button::Standard
| Button::Text
| Button::Suggested
Button::Standard => {
corner_radii = &cosmic.corner_radii.radius_m;
appearance.background = Some(Background::Color(crate::theme::STATE_DEFAULT_COLOR));
appearance.text_color = Some(Color::WHITE);
appearance.icon_color = Some(Color::WHITE);
}
Button::Secondary => {
corner_radii = &cosmic.corner_radii.radius_m;
appearance.background = Some(Background::Color(Color::from_rgb8(224, 224, 224)));
appearance.text_color = Some(Color::BLACK);
appearance.icon_color = Some(Color::BLACK);
}
Button::Text => {
let (background, _, _) = color(&cosmic.text_button);
appearance.background = Some(Background::Color(background));
appearance.text_color = Some(crate::theme::STATE_DEFAULT_COLOR);
appearance.icon_color = Some(crate::theme::STATE_DEFAULT_COLOR);
corner_radii = &cosmic.corner_radii.radius_m;
}
Button::Suggested
| Button::Destructive
| Button::Transparent => {
let style_component = match style {
Button::Standard => &cosmic.button,
Button::Text => &cosmic.text_button,
Button::Suggested => &cosmic.accent_button,
Button::Destructive => &cosmic.destructive_button,
Button::Transparent => &TRANSPARENT_COMPONENT,
@ -68,13 +87,8 @@ pub fn appearance(
let (background, text, icon) = color(style_component);
appearance.background = Some(Background::Color(background));
if !matches!(style, Button::Standard) {
appearance.text_color = text;
appearance.icon_color = icon;
} else if hc {
appearance.border_color = style_component.border.into();
appearance.border_width = 1.;
}
appearance.text_color = text;
appearance.icon_color = icon;
}
Button::Icon | Button::IconVertical | Button::HeaderBar | Button::NavToggle => {
@ -254,12 +268,18 @@ impl Catalog for crate::Theme {
Some(component.on.into())
};
if matches!(style, Button::ListItem) {
if matches!(style, Button::ListItem | Button::Text) {
(
crate::theme::STATE_DEFAULT_BG,
text_color,
text_color,
)
} else if matches!(style, Button::MenuItem | Button::MenuFolder) {
(
Color::from_rgb8(230, 230, 230),
text_color,
text_color,
)
} else {
(component.hover.into(), text_color, text_color)
}
@ -283,12 +303,18 @@ impl Catalog for crate::Theme {
Some(component.on.into())
};
if matches!(style, Button::ListItem) {
if matches!(style, Button::ListItem | Button::Text) {
(
crate::theme::STATE_DEFAULT_BG,
text_color,
text_color,
)
} else if matches!(style, Button::MenuItem | Button::MenuFolder) {
(
Color::from_rgb8(220, 220, 220),
text_color,
text_color,
)
} else {
(component.pressed.into(), text_color, text_color)
}

View file

@ -654,16 +654,16 @@ impl iced_container::Catalog for Theme {
Container::Dialog => iced_container::Style {
icon_color: Some(Color::from(cosmic.primary.on)),
text_color: Some(Color::from(cosmic.primary.on)),
background: Some(iced::Background::Color(cosmic.primary.base.into())),
background: Some(iced::Background::Color(Color::from_rgb8(245, 245, 245))),
border: Border {
color: cosmic.primary.divider.into(),
width: 1.0,
color: Color::TRANSPARENT,
width: 0.0,
radius: cosmic.corner_radii.radius_m.into(),
},
shadow: Shadow {
color: cosmic.shade.into(),
offset: Vector::new(0.0, 4.0),
blur_radius: 16.0,
color: Color::from_rgba(0.0, 0.0, 0.0, 0.25),
offset: Vector::new(0.0, 8.0),
blur_radius: 32.0,
},
},
}
@ -698,7 +698,7 @@ impl slider::Catalog for Theme {
Slider::Standard =>
//TODO: no way to set rail thickness
{
let empty_track: Color = Color::from_rgb8(224, 224, 224);
let empty_track: Color = Color::from_rgb8(240, 240, 240);
slider::Style {
rail: Rail {
backgrounds: (
@ -715,7 +715,7 @@ impl slider::Catalog for Theme {
handle: slider::Handle {
shape: slider::HandleShape::Circle {
radius: 8.0,
radius: 6.0,
},
border_color: Color::from_rgba8(0, 0, 0, 0.12),
border_width: 1.0,
@ -739,7 +739,7 @@ impl slider::Catalog for Theme {
slider::Status::Hovered => match class {
Slider::Standard => {
appearance.handle.shape = slider::HandleShape::Circle {
radius: 10.0,
radius: 7.0,
};
appearance.handle.border_width = 1.0;
appearance.handle.border_color = Color::from_rgba8(0, 0, 0, 0.12);
@ -755,7 +755,7 @@ impl slider::Catalog for Theme {
slider::Status::Dragged => match class {
Slider::Standard => {
appearance.handle.shape = slider::HandleShape::Circle {
radius: 10.0,
radius: 7.0,
};
appearance.handle.border_width = 1.0;
appearance.handle.border_color = Color::from_rgba8(0, 0, 0, 0.12);
@ -897,17 +897,22 @@ impl toggler::Catalog for Theme {
fn style(&self, class: &Self::Class<'_>, status: toggler::Status) -> toggler::Style {
let cosmic = self.cosmic();
const HANDLE_MARGIN: f32 = 2.0;
let neutral_10 = cosmic.palette.neutral_10.with_alpha(0.1);
let mut active = toggler::Style {
background: if matches!(status, toggler::Status::Active { is_toggled: true }) {
cosmic.accent.base.into()
} else if cosmic.is_dark {
cosmic.palette.neutral_6.into()
} else {
cosmic.palette.neutral_5.into()
},
foreground: cosmic.palette.neutral_2.into(),
let is_toggled = matches!(
status,
toggler::Status::Active { is_toggled: true }
| toggler::Status::Hovered { is_toggled: true }
);
let track_color = if is_toggled {
crate::theme::STATE_DEFAULT_COLOR
} else {
Color::from_rgb8(224, 224, 224)
};
let mut style = toggler::Style {
background: track_color,
foreground: Color::WHITE,
border_radius: cosmic.radius_xl().into(),
handle_radius: cosmic
.radius_xl()
@ -920,30 +925,10 @@ impl toggler::Catalog for Theme {
foreground_border_color: Color::TRANSPARENT,
};
match status {
toggler::Status::Active { is_toggled } => active,
toggler::Status::Hovered { is_toggled } => {
let is_active = matches!(status, toggler::Status::Hovered { is_toggled: true });
toggler::Style {
background: if is_active {
over(neutral_10, cosmic.accent_color())
} else {
over(
neutral_10,
if cosmic.is_dark {
cosmic.palette.neutral_6
} else {
cosmic.palette.neutral_5
},
)
}
.into(),
..active
}
}
toggler::Status::Active { .. } | toggler::Status::Hovered { .. } => style,
toggler::Status::Disabled => {
active.background.a /= 2.;
active.foreground.a /= 2.;
active
style.background.a /= 2.;
style
}
}
}
@ -1334,7 +1319,6 @@ impl text_input::Catalog for Theme {
fn style(&self, class: &Self::Class<'_>, status: text_input::Status) -> text_input::Style {
let palette = self.cosmic();
let bg = self.current_container().small_widget.with_alpha(0.25);
let neutral_9 = palette.palette.neutral_9;
let value = neutral_9.into();
@ -1343,7 +1327,7 @@ impl text_input::Catalog for Theme {
let mut appearance = match class {
TextInput::Default => text_input::Style {
background: Color::from(bg).into(),
background: Color::WHITE.into(),
border: Border {
radius: palette.corner_radii.radius_s.into(),
width: 1.0,
@ -1355,7 +1339,7 @@ impl text_input::Catalog for Theme {
selection,
},
TextInput::Search => text_input::Style {
background: Color::from(bg).into(),
background: Color::WHITE.into(),
border: Border {
radius: palette.corner_radii.radius_m.into(),
..Default::default()
@ -1370,11 +1354,9 @@ impl text_input::Catalog for Theme {
match status {
text_input::Status::Active => appearance,
text_input::Status::Hovered => {
let bg = self.current_container().small_widget.with_alpha(0.25);
match class {
TextInput::Default => text_input::Style {
background: Color::from(bg).into(),
background: Color::WHITE.into(),
border: Border {
radius: palette.corner_radii.radius_s.into(),
width: 1.0,
@ -1386,7 +1368,7 @@ impl text_input::Catalog for Theme {
selection,
},
TextInput::Search => text_input::Style {
background: Color::from(bg).into(),
background: Color::WHITE.into(),
border: Border {
radius: palette.corner_radii.radius_m.into(),
..Default::default()
@ -1399,11 +1381,9 @@ impl text_input::Catalog for Theme {
}
}
text_input::Status::Focused => {
let bg = self.current_container().small_widget.with_alpha(0.25);
match class {
TextInput::Default => text_input::Style {
background: Color::from(bg).into(),
background: Color::WHITE.into(),
border: Border {
radius: palette.corner_radii.radius_s.into(),
width: 1.0,
@ -1415,7 +1395,7 @@ impl text_input::Catalog for Theme {
selection,
},
TextInput::Search => text_input::Style {
background: Color::from(bg).into(),
background: Color::WHITE.into(),
border: Border {
radius: palette.corner_radii.radius_m.into(),
..Default::default()

View file

@ -289,7 +289,7 @@ mod horizontal {
let rad_0 = cosmic.corner_radii.radius_0;
ItemStatusAppearance {
background: Some(Background::Color(
cosmic.palette.neutral_5.with_alpha(0.2).into(),
cosmic.palette.neutral_5.with_alpha(0.05).into(),
)),
first: ItemAppearance {
border: Border {
@ -381,7 +381,7 @@ mod vertical {
pub fn tab_bar_active(cosmic: &cosmic_theme::Theme) -> ItemStatusAppearance {
ItemStatusAppearance {
background: Some(Background::Color(
cosmic.palette.neutral_5.with_alpha(0.2).into(),
cosmic.palette.neutral_5.with_alpha(0.05).into(),
)),
first: ItemAppearance {
border: Border {

View file

@ -6,7 +6,6 @@
use crate::ext::ColorExt;
use crate::widget::text_input::{Appearance, StyleSheet};
use iced_core::Color;
use palette::WithAlpha;
#[derive(Default)]
pub enum TextInput {
@ -32,13 +31,11 @@ impl StyleSheet for crate::Theme {
let palette = self.cosmic();
let container = self.current_container();
let background: Color = container.small_widget.with_alpha(0.25).into();
let corner = palette.corner_radii;
let label_color = palette.palette.neutral_9;
match style {
TextInput::Default => Appearance {
background: background.into(),
background: Color::WHITE.into(),
border_radius: corner.radius_s.into(),
border_width: 2.0,
border_offset: None,
@ -47,7 +44,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -63,7 +60,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -79,14 +76,14 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Search => Appearance {
background: background.into(),
background: Color::WHITE.into(),
border_radius: corner.radius_xl.into(),
border_width: 2.0,
border_offset: None,
@ -95,7 +92,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -111,7 +108,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -125,15 +122,12 @@ impl StyleSheet for crate::Theme {
let palette = self.cosmic();
let container = self.current_container();
let mut background: Color = container.small_widget.into();
background.a = 0.25;
let corner = palette.corner_radii;
let label_color = palette.palette.neutral_9;
match style {
TextInput::Default => Appearance {
background: background.into(),
background: Color::WHITE.into(),
border_radius: corner.radius_s.into(),
border_width: 2.0,
border_offset: Some(2.0),
@ -142,14 +136,14 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Search | TextInput::ExpandableSearch => Appearance {
background: background.into(),
background: Color::WHITE.into(),
border_radius: corner.radius_xl.into(),
border_width: 0.0,
border_offset: None,
@ -158,7 +152,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -174,7 +168,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -188,15 +182,12 @@ impl StyleSheet for crate::Theme {
let palette = self.cosmic();
let container = self.current_container();
let mut background: Color = container.small_widget.into();
background.a = 0.25;
let corner = palette.corner_radii;
let label_color = palette.palette.neutral_9;
match style {
TextInput::Default => Appearance {
background: background.into(),
background: Color::WHITE.into(),
border_radius: corner.radius_s.into(),
border_width: 2.0,
border_offset: None,
@ -205,14 +196,14 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Search => Appearance {
background: background.into(),
background: Color::WHITE.into(),
border_radius: corner.radius_xl.into(),
border_offset: None,
border_width: 2.0,
@ -221,14 +212,14 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::ExpandableSearch => Appearance {
background: background.into(),
background: Color::WHITE.into(),
border_radius: corner.radius_xl.into(),
border_offset: None,
border_width: 0.0,
@ -237,7 +228,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -253,7 +244,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -269,7 +260,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -283,15 +274,12 @@ impl StyleSheet for crate::Theme {
let palette = self.cosmic();
let container = self.current_container();
let mut background: Color = container.small_widget.into();
background.a = 0.25;
let corner = palette.corner_radii;
let label_color = palette.palette.neutral_9;
match style {
TextInput::Default => Appearance {
background: background.into(),
background: Color::WHITE.into(),
border_radius: corner.radius_s.into(),
border_width: 2.0,
border_offset: Some(2.0),
@ -300,14 +288,14 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
label_color: label_color.into(),
},
TextInput::Search | TextInput::ExpandableSearch => Appearance {
background: background.into(),
background: Color::WHITE.into(),
border_radius: corner.radius_xl.into(),
border_width: 2.0,
border_offset: Some(2.0),
@ -316,7 +304,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -332,7 +320,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),
@ -348,7 +336,7 @@ impl StyleSheet for crate::Theme {
text_color: None,
placeholder_color: {
let color: Color = container.on.into();
color.blend_alpha(background, 0.7)
color.blend_alpha(Color::WHITE, 0.7)
},
selected_text_color: palette.on_accent_color().into(),
selected_fill: palette.accent_color().into(),