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