summaryrefslogtreecommitdiff
path: root/material_theme
diff options
context:
space:
mode:
authorpml68 <contact@pml68.dev>2025-04-08 18:12:10 +0200
committerpml68 <contact@pml68.dev>2025-04-15 23:49:01 +0200
commit00d296b230e41dbfaf33d1ba374beadf9d113948 (patch)
tree321c1f3c40f8de8e665b830c67cf116ff29017e3 /material_theme
parentfeat(material_theme): implement Catalog for iced_dialog (`dialog` feature) (diff)
downloadiced-builder-00d296b230e41dbfaf33d1ba374beadf9d113948.tar.gz
feat(material_theme): impl `scrollable::Catalog`
Diffstat (limited to 'material_theme')
-rw-r--r--material_theme/src/button.rs54
-rw-r--r--material_theme/src/lib.rs1
-rw-r--r--material_theme/src/scrollable.rs107
-rw-r--r--material_theme/src/utils.rs19
4 files changed, 145 insertions, 36 deletions
diff --git a/material_theme/src/button.rs b/material_theme/src/button.rs
index 051d6c9..21d77b7 100644
--- a/material_theme/src/button.rs
+++ b/material_theme/src/button.rs
@@ -1,9 +1,11 @@
-#![allow(dead_code)]
use iced_widget::button::{Catalog, Status, Style, StyleFn};
-use iced_widget::core::{Background, Border, Color, Shadow, Vector};
+use iced_widget::core::{Background, Border, Color, border};
use crate::Theme;
-use crate::utils::{elevation, mix};
+use crate::utils::{
+ DISABLED_CONTAINER_OPACITY, DISABLED_TEXT_OPACITY, HOVERED_LAYER_OPACITY,
+ PRESSED_LAYER_OPACITY, elevation, mix, shadow_from_elevation,
+};
impl Catalog for Theme {
type Class<'a> = StyleFn<'a, Self>;
@@ -23,27 +25,14 @@ fn button(
tone_overlay: Color,
disabled: Color,
shadow_color: Color,
- shadow_elevation: u8,
+ elevation_level: u8,
status: Status,
) -> Style {
- let border = Border {
- radius: 400.into(),
- ..Default::default()
- };
-
let active = Style {
background: Some(Background::Color(background)),
text_color: foreground,
- border,
- shadow: Shadow {
- color: shadow_color,
- offset: Vector {
- x: 0.0,
- y: elevation(shadow_elevation),
- },
- blur_radius: elevation(shadow_elevation)
- * (1.0 + 0.4_f32.powf(elevation(shadow_elevation))),
- },
+ border: border::rounded(400),
+ shadow: shadow_from_elevation(elevation(elevation_level), shadow_color),
};
match status {
@@ -52,7 +41,7 @@ fn button(
background: Some(Background::Color(mix(
background,
tone_overlay,
- 0.08,
+ HOVERED_LAYER_OPACITY,
))),
..active
},
@@ -60,30 +49,25 @@ fn button(
background: Some(Background::Color(mix(
background,
tone_overlay,
- 0.1,
+ PRESSED_LAYER_OPACITY,
))),
text_color: foreground,
- border,
- shadow: Shadow {
- color: shadow_color,
- offset: Vector {
- x: 0.0,
- y: elevation(shadow_elevation + 1),
- },
- blur_radius: (elevation(shadow_elevation + 1))
- * (1.0 + 0.4_f32.powf(elevation(shadow_elevation + 1))),
- },
+ border: border::rounded(400),
+ shadow: shadow_from_elevation(
+ elevation(elevation_level + 1),
+ shadow_color,
+ ),
},
Status::Disabled => Style {
background: Some(Background::Color(Color {
- a: 0.12,
+ a: DISABLED_CONTAINER_OPACITY,
..disabled
})),
text_color: Color {
- a: 0.38,
+ a: DISABLED_TEXT_OPACITY,
..disabled
},
- border,
+ border: border::rounded(400),
..Default::default()
},
}
@@ -163,7 +147,7 @@ pub fn outlined(theme: &Theme, status: Status) -> Style {
},
Status::Disabled => Border {
color: Color {
- a: 0.12,
+ a: DISABLED_CONTAINER_OPACITY,
..disabled
},
width: 1.0,
diff --git a/material_theme/src/lib.rs b/material_theme/src/lib.rs
index 87cf353..273ef9a 100644
--- a/material_theme/src/lib.rs
+++ b/material_theme/src/lib.rs
@@ -6,6 +6,7 @@ use serde::Deserialize;
pub mod button;
pub mod container;
+pub mod scrollable;
pub mod text;
pub mod utils;
diff --git a/material_theme/src/scrollable.rs b/material_theme/src/scrollable.rs
new file mode 100644
index 0000000..c2dde67
--- /dev/null
+++ b/material_theme/src/scrollable.rs
@@ -0,0 +1,107 @@
+use iced_widget::core::{Border, border};
+use iced_widget::scrollable::{
+ Catalog, Rail, Scroller, Status, Style, StyleFn,
+};
+
+use super::Theme;
+use super::container::surface_container;
+use super::utils::mix;
+use crate::utils::{HOVERED_LAYER_OPACITY, PRESSED_LAYER_OPACITY};
+
+impl Catalog for Theme {
+ type Class<'a> = StyleFn<'a, Self>;
+
+ fn default<'a>() -> Self::Class<'a> {
+ Box::new(default)
+ }
+
+ fn style(&self, class: &Self::Class<'_>, status: Status) -> Style {
+ class(self, status)
+ }
+}
+
+pub fn default(theme: &Theme, status: Status) -> Style {
+ let colors = theme.colorscheme.surface;
+
+ let rail = Rail {
+ background: None,
+ scroller: Scroller {
+ color: colors.on_surface,
+ border: border::rounded(400),
+ },
+ border: Border::default(),
+ };
+
+ let style = Style {
+ container: surface_container(theme),
+ vertical_rail: rail,
+ horizontal_rail: rail,
+ gap: None,
+ };
+
+ match status {
+ Status::Active { .. } => style,
+ Status::Hovered {
+ is_horizontal_scrollbar_hovered,
+ is_vertical_scrollbar_hovered,
+ ..
+ } => {
+ let hovered_rail = Rail {
+ scroller: Scroller {
+ color: mix(
+ colors.on_surface,
+ colors.color,
+ HOVERED_LAYER_OPACITY,
+ ),
+ border: border::rounded(400),
+ },
+ ..rail
+ };
+
+ Style {
+ horizontal_rail: if is_horizontal_scrollbar_hovered {
+ hovered_rail
+ } else {
+ rail
+ },
+ vertical_rail: if is_vertical_scrollbar_hovered {
+ hovered_rail
+ } else {
+ rail
+ },
+ ..style
+ }
+ }
+ Status::Dragged {
+ is_horizontal_scrollbar_dragged,
+ is_vertical_scrollbar_dragged,
+ ..
+ } => {
+ let dragged_rail = Rail {
+ scroller: Scroller {
+ color: mix(
+ colors.on_surface,
+ colors.color,
+ PRESSED_LAYER_OPACITY,
+ ),
+ border: border::rounded(400),
+ },
+ ..rail
+ };
+
+ Style {
+ horizontal_rail: if is_horizontal_scrollbar_dragged {
+ dragged_rail
+ } else {
+ rail
+ },
+ vertical_rail: if is_vertical_scrollbar_dragged {
+ dragged_rail
+ } else {
+ rail
+ },
+ ..style
+ }
+ }
+ }
+}
diff --git a/material_theme/src/utils.rs b/material_theme/src/utils.rs
index c9eb78e..7efec9b 100644
--- a/material_theme/src/utils.rs
+++ b/material_theme/src/utils.rs
@@ -1,4 +1,10 @@
-use iced_widget::core::Color;
+use iced_widget::core::{Color, Shadow, Vector};
+
+pub const HOVERED_LAYER_OPACITY: f32 = 0.08;
+pub const PRESSED_LAYER_OPACITY: f32 = 0.1;
+
+pub const DISABLED_TEXT_OPACITY: f32 = 0.38;
+pub const DISABLED_CONTAINER_OPACITY: f32 = 0.12;
pub fn elevation(elevation_level: u8) -> f32 {
(match elevation_level {
@@ -11,6 +17,17 @@ pub fn elevation(elevation_level: u8) -> f32 {
} as f32)
}
+pub fn shadow_from_elevation(elevation: f32, color: Color) -> Shadow {
+ Shadow {
+ color,
+ offset: Vector {
+ x: 0.0,
+ y: elevation,
+ },
+ blur_radius: (elevation) * (1.0 + 0.4_f32.powf(elevation)),
+ }
+}
+
pub fn mix(color1: Color, color2: Color, p2: f32) -> Color {
if p2 <= 0.0 {
return color1;