Skip to main content

repose_material/material3/
surface.rs

1#![allow(non_snake_case)]
2
3use std::rc::Rc;
4
5use repose_core::*;
6use repose_ui::{Box, TextStyle, ViewExt};
7
8use super::*;
9
10/// Configuration for [`Surface`].
11#[derive(Clone, Debug)]
12pub struct SurfaceConfig {
13    pub modifier: Modifier,
14    pub enabled: bool,
15    pub color: Color,
16    pub content_color: Color,
17    pub shape_radius: f32,
18    pub tonal_elevation: f32,
19    pub shadow_elevation: f32,
20    pub border: Option<(f32, Color)>,
21    pub interaction_source: Option<MutableInteractionSource>,
22}
23
24impl Default for SurfaceConfig {
25    fn default() -> Self {
26        Self {
27            modifier: Modifier::new(),
28            enabled: true,
29            color: SurfaceDefaults::color(),
30            content_color: SurfaceDefaults::content_color(),
31            shape_radius: SurfaceDefaults::SHAPE_RADIUS,
32            tonal_elevation: SurfaceDefaults::TONAL_ELEVATION,
33            shadow_elevation: SurfaceDefaults::SHADOW_ELEVATION,
34            border: None,
35            interaction_source: None,
36        }
37    }
38}
39
40/// M3 Surface - a basic container with shape, color, elevation, and border.
41/// Sets the ContentColor local for children based on the surface color.
42pub fn Surface(config: SurfaceConfig, content: impl FnOnce() -> View) -> View {
43    let sf_source: Rc<MutableInteractionSource> = config
44        .interaction_source
45        .clone()
46        .map(Rc::new)
47        .unwrap_or_else(|| remember(MutableInteractionSource::new));
48    let mut m = Modifier::new()
49        .background(config.color)
50        .clip_rounded(config.shape_radius)
51        .interaction_source(&sf_source)
52        .then(config.modifier);
53    if config.tonal_elevation > 0.0 {
54        m = m.state_elevation(StateElevation {
55            default: config.tonal_elevation,
56            hovered: config.tonal_elevation,
57            pressed: config.tonal_elevation,
58            dragged: config.tonal_elevation,
59            disabled: 0.0,
60        });
61    }
62    if config.shadow_elevation > 0.0 {
63        m = m.shadow(config.shadow_elevation, 0.0);
64    }
65    if let Some((w, c)) = config.border {
66        m = m.border(w, c, config.shape_radius);
67    }
68    Box(m).color(config.content_color).child(content())
69}