Split status UI into focused menu modules

This commit is contained in:
Samuel Onoja committed 2026-10-01 12:18:30 +01:00
1 parent 4ea1f1f222
commit 2c95e5e80f
11 files changed
+1664 -1450

No files matched your search

@@ -0,0 +1,172 @@
use cosmic::iced::{Alignment, Background, Border, Color, Length};
use cosmic::widget::{button, column, container, row, slider};
use cosmic::{Element, theme};
use crate::status::Action;
use crate::{Message, ShellTheme, accented_icon, color, motion, shell_font, text};
pub(super) fn status_summary<'a>(
source: &'static [u8],
title: &'a str,
subtitle: &'a str,
primary: Color,
muted: Color,
accent: Color,
opacity: f32,
enabled: bool,
toggle: Option<(bool, Action)>,
) -> Element<'a, cosmic::Action<Message>> {
let badge_color = if enabled { accent } else { primary };
let badge = container(accented_icon(source, 22, primary, accent))
.width(32)
.height(32)
.center_x(32)
.center_y(32)
.class(theme::Container::custom(move |_| container::Style {
background: Some(Background::Color(Color {
a: if enabled { 0.22 * opacity } else { 0.06 * opacity },
..badge_color
})),
border: Border {
radius: motion::radius(16.0).into(),
..Default::default()
},
..Default::default()
}));
let badge: Element<'_, cosmic::Action<Message>> = if let Some((_, action)) = toggle {
motion::button(
button::custom(badge)
.padding(0)
.name(if enabled { "Turn off" } else { "Turn on" })
.on_press(cosmic::Action::App(Message::Control(action))),
badge_color,
false,
opacity,
)
} else {
badge.into()
};
let summary = row![
badge,
column![
text(title).size(14),
text(subtitle).size(12).class(theme::Text::Color(muted)),
]
.spacing(4)
.width(Length::Fill)
]
.spacing(8)
.align_y(Alignment::Center);
summary.into()
}
pub(super) fn level_meter(value: u8, foreground: Color, opacity: f32) -> Element<'static, cosmic::Action<Message>> {
let segment = move |amount: u16, filled: bool| {
container(text(""))
.width(Length::FillPortion(amount))
.height(5)
.class(theme::Container::custom(move |_| container::Style {
background: Some(Background::Color(if filled {
foreground
} else {
Color {
a: 0.1 * opacity,
..foreground
}
})),
border: Border {
radius: motion::radius(2.5).into(),
..Default::default()
},
..Default::default()
}))
};
let value = u16::from(value.min(100));
let mut meter = row::with_capacity(2).width(Length::Fill);
if value > 0 {
meter = meter.push(segment(value, true));
}
if value < 100 {
meter = meter.push(segment(100 - value, false));
}
meter.into()
}
pub(super) fn control_card<'a>(
content: Element<'a, cosmic::Action<Message>>,
foreground: Color,
opacity: f32,
) -> Element<'a, cosmic::Action<Message>> {
ferese_theme::menus::section(content, foreground, opacity, motion::radius(22.))
}
pub(super) fn menu_button<'a>(
label: &'a str,
message: Message,
foreground: Color,
opacity: f32,
) -> Element<'a, cosmic::Action<Message>> {
motion::button(
ferese_theme::menus::button(label, cosmic::Action::App(message), shell_font()),
foreground,
false,
opacity,
)
}
pub(super) fn shell_switch<'a>(
label: &str,
enabled: bool,
action: Action,
palette: ShellTheme,
opacity: f32,
) -> Element<'a, cosmic::Action<Message>> {
let toggle = ferese_theme::menus::switch(enabled, palette.palette(), opacity);
motion::button(
button::custom(toggle)
.padding(4)
.name(format!("{label}: {}", if enabled { "on" } else { "off" }))
.on_press(cosmic::Action::App(Message::Control(action))),
color(palette.text_primary),
false,
opacity,
)
}
pub(super) fn toggle_row<'a>(
label: &'a str,
on: bool,
action: Action,
palette: ShellTheme,
opacity: f32,
) -> Element<'a, cosmic::Action<Message>> {
ferese_theme::menus::row(label, shell_switch(label, on, action, palette, opacity), shell_font())
}
pub(super) fn slider_row(
source: &'static [u8],
value: u8,
brightness: bool,
foreground: Color,
icon_accent: Color,
opacity: f32,
) -> Element<'static, cosmic::Action<Message>> {
let control = slider(if brightness { 1..=100 } else { 0..=100 }, value, move |value| {
cosmic::Action::App(Message::Control(if brightness {
Action::Brightness(value)
} else {
Action::Volume(value)
}))
})
.width(Length::Fill)
.height(24)
.class(ferese_theme::menus::slider(foreground, opacity));
row![
accented_icon(source, 18, foreground, icon_accent),
control,
text(format!("{value}%")).size(12).width(36)
]
.spacing(8)
.align_y(Alignment::Center)
.into()
}