/themer

Non-complicated Yew theme management

Primary LanguageRustApache License 2.0Apache-2.0

Themer

A non-complicated theme management library for Yew.

Note: Themer is NOT a CSS solution. You may use any CSS styling solution you wish (e.g. Stylist).

Status

Ongoing development. No/little documentation, rapidly changing, etc.

Examples

Examples can be served with Trunk (e.g. trunk serve)

  • Minimal: Example using the browser's preferred theme.
  • Read browser preference: Display your browser's theme preference (Light/Dark) on a label (no styling applied).
  • Theme Switcher: A button which switches between 3 themes.
  • Storage: Store user-saved theme preferences with a button and load those preferences automatically on refresh.

API Foreward

Step 1: Setup a Theme and Key

The API asks you to create a Theme template struct with the #[theme] macro, and a key for access with the #[theme_key] macro. The theme key is used to reduce memory footprint and provides ergonomics.

#[theme]
pub struct MyTheme {
    // Foreground color
    fg: &'static str,
    // Background color
    bg: &'static str,
    // Font size
    fs: &'static str,
}

#[theme_key]
pub enum MyThemeChoice {
    Light,
    Dark,
}

impl ThemeKey for MyThemeChoice {
    type Theme = MyTheme;
    fn theme(&self) -> &'static Self::Theme {
        match self {
            MyThemeChoice::Light => &MyTheme {
                fg: "black",
                bg: "white",
                fs: "1.2em",
            },
            MyThemeChoice::Dark => &MyTheme {
                fg: "white",
                bg: "black",
                fs: "1.2em",
            },
        }
    }
}

Step 2: Provide your theme

To pass your theme to your app, you must register a ThemeProvider with your theme choice. This works as a Context in Yew.

In this example, <App /> is a function component containing your app.

#[function_component(Root)]
pub fn root() -> Html {
    let initial_theme = MyThemeChoice::Light;
    html! {
        <ThemeProvider<MyThemeChoice> theme={ initial_theme } >
            <App />
        </ThemeProvider<MyThemeChoice>>
    }
}

You can match your browser's theme preference (Light/Dark) to help decide on an initial theme, via themer::BrowserPreference::get()

Step 3: Use your theme

use_theme() will dereference into your theme. This works as a Hook in Yew.

#[function_component(App)]
pub fn app() -> Html {
    let theme = use_theme::<MyThemeChoice>();
    let style = format!("color:{}; background-color:{};", theme.fg, theme.bg);

    html! {
        <label {style}>
            { "I am a themed label!" }
        </label>
    }
}