diff --git a/crates/ferese-theme/README.md b/crates/ferese-theme/README.md index ac39216..de0b05f 100644 --- a/crates/ferese-theme/README.md +++ b/crates/ferese-theme/README.md @@ -6,7 +6,7 @@ prompt and screen-sharing/recording chooser. - `Palette` resolves KDL colors and corners and builds the native toolkit theme. - `PRESETS` defines the six built-in color schemes. - `font` and `text` share bounded font-name storage and explicit font selection. -- `controls` supplies surfaces, navigation, buttons and input styles. +- `controls` supplies surfaces, navigation, font-aware text buttons and input styles. - `menus` supplies headings, rows, sections, separators, switches and slider styles. - `calendar` supplies date/time labels, stacked clock digits and calendar grids. Callers supply the date and navigation controls. diff --git a/crates/ferese-theme/src/controls.rs b/crates/ferese-theme/src/controls.rs index bcf7532..3acc294 100644 --- a/crates/ferese-theme/src/controls.rs +++ b/crates/ferese-theme/src/controls.rs @@ -13,6 +13,28 @@ pub fn button_style(p: Palette, selected: bool) -> theme::Button { styled_button(p, selected, false) } +pub fn text_button<'a, M: Clone + 'a>( + label: impl Into> + 'a, + font: cosmic::font::Font, + palette: Palette, + selected: bool, +) -> button::Button<'a, M> { + let theme = cosmic::theme::active(); + let native = theme.cosmic(); + let content = widget::row![ + crate::text(label, font) + .size(14) + .line_height(cosmic::iced::widget::text::LineHeight::Absolute(20.into())), + ] + .height(native.space_l()) + .padding([0, native.space_s()]) + .align_y(cosmic::iced::Alignment::Center); + + button::custom(content) + .padding(0) + .class(button_style(palette, selected)) +} + pub fn navigation_style(p: Palette, selected: bool) -> theme::Button { styled_button(p, selected, true) } diff --git a/portal/src/picker.rs b/portal/src/picker.rs index dbf3db8..adc6fed 100644 --- a/portal/src/picker.rs +++ b/portal/src/picker.rs @@ -44,7 +44,7 @@ struct Picker { prompt: Prompt, selected: Vec, background: cosmic::iced::Color, - foreground: cosmic::iced::Color, + palette: ferese_theme::Palette, font: cosmic::font::Font, } @@ -64,7 +64,7 @@ pub fn run() -> Result<(), Box> { return Err("No shareable displays".into()); } - let (theme, font, background, foreground) = appearance(); + let (theme, font, background, palette) = appearance(); let height = 180. + (prompt.sources.len().min(4) as f32 * 56.); cosmic::app::run::( Settings::default() @@ -75,7 +75,7 @@ pub fn run() -> Result<(), Box> { .default_font(font) .default_text_size(14.) .is_daemon(false), - (prompt, background, foreground, font), + (prompt, background, palette, font), )?; Ok(()) @@ -86,7 +86,7 @@ impl cosmic::Application for Picker { type Flags = ( Prompt, cosmic::iced::Color, - cosmic::iced::Color, + ferese_theme::Palette, cosmic::font::Font, ); type Message = Message; @@ -102,7 +102,7 @@ impl cosmic::Application for Picker { fn init( mut core: Core, - (prompt, background, foreground, font): Self::Flags, + (prompt, background, palette, font): Self::Flags, ) -> (Self, Task) { core.window.show_headerbar = false; core.window.border_padding = Some(0); @@ -115,7 +115,7 @@ impl cosmic::Application for Picker { prompt, selected: Vec::new(), background, - foreground, + palette, font, }; let task = app @@ -194,15 +194,11 @@ impl cosmic::Application for Picker { } fn style(&self) -> Option { - Some(cosmic::iced::theme::Style { - background_color: if self.material.is_some() { - cosmic::iced::Color::TRANSPARENT - } else { - self.background - }, - text_color: self.foreground, - icon_color: self.foreground, - }) + Some(self.palette.application_style(if self.material.is_some() { + cosmic::iced::Color::TRANSPARENT + } else { + self.background + })) } fn view(&self) -> Element<'_, Message> { @@ -265,7 +261,7 @@ impl cosmic::Application for Picker { .class(if selected { ferese_theme::accent_button() } else { - cosmic::theme::Button::Standard + ferese_theme::controls::navigation_style(self.palette, false) }) .padding(8) .width(Length::Fill) @@ -304,7 +300,7 @@ impl cosmic::Application for Picker { content = content.push( row![ button::custom(self.text("Cancel")) - .class(cosmic::theme::Button::Text) + .class(ferese_theme::controls::button_style(self.palette, false)) .on_press(Message::Cancel), share ] @@ -327,7 +323,7 @@ pub(crate) fn appearance() -> ( cosmic::Theme, cosmic::font::Font, cosmic::iced::Color, - cosmic::iced::Color, + ferese_theme::Palette, ) { let document = ferese_config::config_path() .and_then(|path| std::fs::read_to_string(path).ok()) @@ -345,6 +341,6 @@ pub(crate) fn appearance() -> ( a: ferese_theme::material_opacity(document.as_ref()), ..palette.sidebar }, - palette.text, + palette, ) } diff --git a/shell/ferese-polkit-agent/src/prompt.rs b/shell/ferese-polkit-agent/src/prompt.rs index 0f0ca4f..bab284b 100644 --- a/shell/ferese-polkit-agent/src/prompt.rs +++ b/shell/ferese-polkit-agent/src/prompt.rs @@ -2,9 +2,9 @@ use crate::PromptEvent; use cosmic::{ Element, app::{Core, Settings, Task}, - iced::{Alignment, Background, Border, Color, Length, Size, Subscription, window}, + iced::{Alignment, Color, Length, Size, Subscription, window}, theme, - widget::{self, button, column, container, row, text}, + widget::{self, button, column, container, row}, }; use std::{ collections::VecDeque, @@ -198,15 +198,15 @@ impl cosmic::Application for Prompt { } fn style(&self) -> Option { - Some(cosmic::iced::theme::Style { - background_color: if self.material.is_some() { - cosmic::iced::Color::TRANSPARENT - } else { - self.appearance.surface - }, - text_color: self.appearance.text, - icon_color: self.appearance.text, - }) + Some( + self.appearance + .palette() + .application_style(if self.material.is_some() { + cosmic::iced::Color::TRANSPARENT + } else { + self.appearance.surface + }), + ) } fn init( @@ -334,7 +334,7 @@ impl cosmic::Application for Prompt { Message::Submit }); } - let action = button::custom(text("Authenticate").font(palette.font).size(13)) + let action = button::custom(ferese_theme::text("Authenticate", palette.font).size(13)) .class(ferese_theme::accent_button()) .height(Length::Fixed(36.)) .padding([8, 16]) @@ -346,20 +346,13 @@ impl cosmic::Application for Prompt { .height(40) .center_x(40) .center_y(40) - .class(theme::Container::custom(move |_| { - widget::container::Style { - background: Some(Background::Color(palette.accent.scale_alpha(0.13))), - border: Border { - radius: 12.0.into(), - ..Default::default() - }, - ..Default::default() - } - })), + .class(ferese_theme::controls::surface( + palette.accent.scale_alpha(0.13), + 12., + )), column![ - text("Authentication required").font(palette.font).size(18), - text(format!("Confirm as {}", self.user)) - .font(palette.font) + ferese_theme::text("Authentication required", palette.font).size(18), + ferese_theme::text(format!("Confirm as {}", self.user), palette.font) .size(12) .class(theme::Text::Color(palette.muted)), ] @@ -369,30 +362,31 @@ impl cosmic::Application for Prompt { .align_y(Alignment::Center); let mut body = column![ heading, - text(&self.description).font(palette.font).size(13), + ferese_theme::text(&self.description, palette.font).size(13), input ] .spacing(14) .width(Length::Fill); if let Some(error) = &self.error { body = body.push( - text(error) - .font(palette.font) + ferese_theme::text(error, palette.font) .size(12) .class(theme::Text::Color(Color::from_rgb8(235, 98, 98))), ); } else if let Some(info) = &self.info { body = body.push( - text(info) - .font(palette.font) + ferese_theme::text(info, palette.font) .size(12) .class(theme::Text::Color(palette.muted)), ); } body = body.push( row![ - button::custom(text("Cancel").font(palette.font).size(13)) - .class(theme::Button::Text) + button::custom(ferese_theme::text("Cancel", palette.font).size(13)) + .class(ferese_theme::controls::button_style( + palette.palette(), + false + )) .padding([8, 14]) .on_press(Message::Cancel), action diff --git a/shell/ferese-shell/src/main.rs b/shell/ferese-shell/src/main.rs index 35e9414..60ae127 100644 --- a/shell/ferese-shell/src/main.rs +++ b/shell/ferese-shell/src/main.rs @@ -1514,12 +1514,14 @@ impl FereseShell { .align_x(alignment); if note.interactive { - let title = cosmic::widget::text(if note.title.is_empty() { - "⋮⋮" - } else { - ¬e.title - }) - .font(font) + let title = ferese_theme::text( + if note.title.is_empty() { + "⋮⋮" + } else { + ¬e.title + }, + font, + ) .size(note.title_size) .class(theme::Text::Color(foreground)); let header = cosmic::widget::mouse_area(container(title).width(Length::Fill)) @@ -1549,15 +1551,17 @@ impl FereseShell { ); } else if !note.title.is_empty() { body = body.push( - cosmic::widget::text(note.title.clone()) - .font(cosmic::font::Font { + ferese_theme::text( + note.title.clone(), + cosmic::font::Font { weight: cosmic::iced::font::Weight::Semibold, ..font - }) - .size(note.title_size) - .width(Length::Fill) - .align_x(alignment) - .class(theme::Text::Color(foreground)), + }, + ) + .size(note.title_size) + .width(Length::Fill) + .align_x(alignment) + .class(theme::Text::Color(foreground)), ); } @@ -1582,8 +1586,7 @@ impl FereseShell { ); } else { body = body.push( - cosmic::widget::text(note.text.clone()) - .font(font) + ferese_theme::text(note.text.clone(), font) .size(note.text_size) .width(Length::Fill) .align_x(alignment) @@ -1747,8 +1750,7 @@ impl FereseShell { if pixel && clock.show_date { labels = labels.push( - cosmic::widget::text(self.desktop_clock.1.clone()) - .font(date_font) + ferese_theme::text(self.desktop_clock.1.clone(), date_font) .size(clock.date_size) .class(theme::Text::Color(tint( &clock.date_color, @@ -1780,8 +1782,7 @@ impl FereseShell { for (position, digit) in digits.chars().enumerate() { digit_row = digit_row.push( - cosmic::widget::text(digit.to_string()) - .font(font) + ferese_theme::text(digit.to_string(), font) .size(size) .line_height(cosmic::iced::widget::text::LineHeight::Relative(0.8)) .class(theme::Text::Color(digit_colors[(line + position) % 2])), @@ -1809,8 +1810,7 @@ impl FereseShell { .min(available_height / 1.3); labels = labels.push( - cosmic::widget::text(self.desktop_clock.0.clone()) - .font(font) + ferese_theme::text(self.desktop_clock.0.clone(), font) .size(size) .width(Length::Fill) .align_x(alignment) @@ -1820,8 +1820,7 @@ impl FereseShell { if !pixel && clock.show_date { labels = labels.push( - cosmic::widget::text(self.desktop_clock.1.clone()) - .font(font) + ferese_theme::text(self.desktop_clock.1.clone(), font) .size(clock.date_size) .width(Length::Fill) .align_x(alignment) diff --git a/shell/ferese-shell/src/system_modal.rs b/shell/ferese-shell/src/system_modal.rs index 8609817..219696c 100644 --- a/shell/ferese-shell/src/system_modal.rs +++ b/shell/ferese-shell/src/system_modal.rs @@ -1,6 +1,6 @@ use super::*; use cosmic::iced::widget::Space; -use cosmic::widget::{column, text}; +use cosmic::widget::column; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(super) enum PowerAction { @@ -436,9 +436,8 @@ impl FereseShell { let rows = match &modal.content { Content::Power(action) => { let mut rows = column![ - text(action.title()).font(shell_font()).size(23), + text(action.title()).size(23), text(action.description()) - .font(shell_font()) .size(14) .class(theme::Text::Color(palette.muted)), ] @@ -448,13 +447,12 @@ impl FereseShell { { rows = rows.push( text("Applications requested that this action be prevented:") - .font(shell_font()) .size(13) .class(theme::Text::Color(palette.muted)), ); let items = inhibitors.reasons.iter().fold( column::with_capacity(inhibitors.reasons.len()).spacing(6), - |rows, reason| rows.push(text(reason).font(shell_font()).size(13)), + |rows, reason| rows.push(text(reason).size(13)), ); rows = rows.push( container(cosmic::widget::scrollable(items).height(Length::Shrink)) @@ -476,11 +474,14 @@ impl FereseShell { rows.push( row![ Space::new().width(Length::Fill), - button::text("Cancel") - .class(ferese_theme::controls::button_style(palette, false)) - .on_press(cosmic::Action::App(Message::CancelPower)), - button::text(label) - .class(ferese_theme::controls::button_style(palette, true)) + ferese_theme::controls::text_button( + "Cancel", + shell_font(), + palette, + false + ) + .on_press(cosmic::Action::App(Message::CancelPower)), + ferese_theme::controls::text_button(label, shell_font(), palette, true) .on_press_maybe( modal .inhibitors @@ -496,12 +497,8 @@ impl FereseShell { for entry in entries { bindings = bindings.push( row![ - text(&entry.keys) - .font(shell_font()) - .size(13) - .width(Length::FillPortion(1)), + text(&entry.keys).size(13).width(Length::FillPortion(1)), text(&entry.description) - .font(shell_font()) .size(13) .width(Length::FillPortion(1)), ] @@ -518,12 +515,30 @@ impl FereseShell { .saturating_sub(360) .clamp(40, 400) as f32; column![ - text("Welcome to Ferese").font(shell_font()).size(23), - text("Your active shortcuts").font(shell_font()).size(14).class(theme::Text::Color(palette.muted)), - container(cosmic::widget::scrollable(bindings).height(Length::Shrink)).max_height(height), - text("Disable this guide in Settings → Shortcuts. It appears at each login until disabled.").font(shell_font()).size(12).class(theme::Text::Color(palette.muted)), - row![Space::new().width(Length::Fill), button::text("Got it").class(ferese_theme::controls::button_style(palette, true)).on_press(cosmic::Action::App(Message::CancelPower))], - ].spacing(14) + text("Welcome to Ferese").size(23), + ferese_theme::menus::section_label( + "Your active shortcuts", + shell_font(), + palette.muted, + ) + .size(14), + container(cosmic::widget::scrollable(bindings).height(Length::Shrink)) + .max_height(height), + text("Disable this guide in Settings → Shortcuts. It appears at each login until disabled.") + .size(12) + .class(theme::Text::Color(palette.muted)), + row![ + Space::new().width(Length::Fill), + ferese_theme::controls::text_button( + "Got it", + shell_font(), + palette, + true, + ) + .on_press(cosmic::Action::App(Message::CancelPower)), + ], + ] + .spacing(14) } }; container(rows)