Expand description
Theming
Freya has built-in support for Theming.
Accessing the current theme
You can access the current theme via the use_get_theme hook.
fn app() -> Element {
    rsx!(
        ThemeProvider {
            Component { }
        }
    )
}
#[allow(non_snake_case)]
fn Component() -> Element {
    let theme = use_get_theme();
    let button_theme = &theme.button;
    rsx!(
        rect {
            background: "{button_theme.background}",
        }
    )
}Custom default theme
By default, the selected theme is LIGHT_THEME. You can use the alternative, DARK_THEME.
fn app() -> Element {
    rsx!(
        ThemeProvider {
            theme: LIGHT_THEME,
            Component { }
        }
    )
}
#[allow(non_snake_case)]
fn Component() -> Element {
    let theme = use_get_theme();
    let button_theme = &theme.button;
    rsx!(
        rect {
            background: "{button_theme.background}",
        }
    )
}Change the theme
Changing the selected theme at runtime is possible by using the use_theme hook.
fn app() -> Element {
    rsx!(
        ThemeProvider {
            Component { }
        }
    )
}
#[allow(non_snake_case)]
fn Component() -> Element {
    let mut theme = use_theme();
    let onclick = move |_| {
        *theme.write() = LIGHT_THEME;
    };
    rsx!(
        Button {
            onclick,
            label {
                "Use Light theme"
            }
        }
    )
}Change theme for an individual component
Most built-in components have their own theme “override.” You can specify values to override like this:
fn app() -> Element {
    rsx! {
        Button {
            theme: ButtonThemeWith {
                background: Some("blue".into()),
                font_theme: Some(FontThemeWith {
                    color: Some("white".into()),
                    ..Default::default()
                }),
                ..Default::default()
            },
            label { "I'm blue now" }
        }
    }
}You need to use a different “type” of theme.
In the “ThemeWith” structs, each field is optional, so that the component knows what to override and
what to keep.
Also, you need to spread ..Default::default, to make all the other fields None.
To make this less verbose, you can use the theme_with! macro:
fn app() -> Element {
    rsx! {
        Button {
            theme: theme_with!(ButtonTheme {
                background: "blue".into(),
                font_theme: theme_with!(FontTheme {
                    color: "white".into(),
                }),
            }),
            label { "I'm blue now" }
        }
    }
}As you can see, it removes the need for the “With” suffix, because that is already in the macro name.
More importantly, though, it wraps each field in a Some, and adds the spread.
Custom theme
You can build themes from scratch or extended from others, like here with LIGHT_THEME:
const CUSTOM_THEME: Theme = Theme {
    button: ButtonTheme {
        background: Cow::Borrowed("rgb(230, 0, 0)"),
        hover_background: Cow::Borrowed("rgb(150, 0, 0)"),
        font_theme: FontTheme {
            color: Cow::Borrowed("white"),
        },
        ..LIGHT_THEME.button
    },
    ..LIGHT_THEME
};
fn app() -> Element {
    rsx!(
        ThemeProvider {
            theme: CUSTOM_THEME,
            rect {
                width: "100%",
                height: "100%",
                Button {
                    label {
                        "Report"
                    }
                }
            }
        }
    )
}