Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ web-sys = { version = "0.3.77", features = [
"Document",
"Window",
"HtmlHeadElement",
"StorageEvent",
"MediaQueryList",
]}
gloo-timers = "0.3.0"
Expand Down
178 changes: 178 additions & 0 deletions DIOXUS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# 🧬 Theme Dioxus Usage

Adding Theme to your project is simple:

1. Make sure your project is set up with **Dioxus**. Refer to the [Dioxus Getting Started Guide](https://dioxuslabs.com/learn/0.6/getting_started) for setup instructions.

1. Add the **theme** library to your dependencies by including it in your `Cargo.toml` file:

```sh
cargo add theme --features=dio
```

1. Import the `ThemeProvider` component into your Dioxus application.

## 🛠️ Usage

Follow these steps to integrate `theme` into your Dioxus application:

### 1. Import the Required Components

Import the `ThemeProvider` and related types into your Dioxus project:

```rust
use theme::dioxus::ThemeProvider;
use theme::{Theme, StorageType};
```

### 2. Define Custom Themes (Optional)

You can define and register custom themes using the `CustomTheme` type:

```rust
use std::collections::HashMap;
use std::rc::Rc;
use theme::{CustomTheme, ColorTokens};

let mut custom_themes = HashMap::new();

custom_themes.insert(
"solarized".to_string(),
Rc::new(CustomTheme {
name: "solarized".to_string(),
base: None, // or Some("light".to_string()) if you want to inherit
tokens: ColorTokens {
primary: "#268bd2".to_string(),
secondary: "#2aa198".to_string(),
background: "#fdf6e3".to_string(),
text: "#657b83".to_string(),
error: Some("#dc322f".to_string()),
warning: Some("#cb4b16".to_string()),
success: Some("#859900".to_string()),
},
}),
);
```

### 3. Wrap Your App with the `ThemeProvider`

Wrap your main app component inside the `ThemeProvider` to provide theme context and behavior to your app:

```rust
use std::collections::HashMap;
use std::rc::Rc;
use dioxus::prelude::*;
use theme::dioxus::ThemeProvider;
use theme::{Theme, StorageType, CustomTheme, ColorTokens};

#[component]
fn App() -> Element {
let mut custom_themes = HashMap::new();
custom_themes.insert(
"solarized".to_string(),
Rc::new(CustomTheme {
name: "solarized".to_string(),
base: None,
tokens: ColorTokens {
primary: "#268bd2".to_string(),
secondary: "#2aa198".to_string(),
background: "#fdf6e3".to_string(),
text: "#657b83".to_string(),
error: Some("#dc322f".to_string()),
warning: Some("#cb4b16".to_string()),
success: Some("#859900".to_string()),
},
}),
);

rsx! {
ThemeProvider {
default_theme: Theme::System,
storage_type: StorageType::LocalStorage,
storage_name: "theme",
custom_themes: custom_themes,
forced_theme: None,
MainApp {}
}
}
}

#[component]
fn MainApp() -> Element {
rsx! {
h1 { "Welcome to the themed app!" }
}
}
```

### 4. Access the Theme Context with the `use_theme` Hook

Use the `use_theme` hook to access the current theme, resolved theme, and control functions within your components:

```rust
use dioxus::prelude::*;
use theme::dioxus::use_theme;
use theme::Theme;

#[component]
fn MainApp() -> Element {
let ctx = use_theme();
let resolved_theme = (ctx.resolved_theme)();

let onclick = {
move |_| ctx.set_theme.call(Theme::Dark)
};

rsx! {
div {
h2 { "Current Theme: {resolved_theme.as_str()}" }
button { onclick: onclick, "Switch to Dark Theme" }
}
}
}
```

## 🔧 Props

### `ThemeProviderProps` Props

#### Main Props

| Property | Type | Description | Default |
| --------------- | ---------------------------------- | ------------------------------------------------------------------- | --------------- |
| `default_theme` | `Theme` | The theme to use if nothing is stored or detected. | `Theme::System` |
| `storage_type` | `StorageType` | Whether to persist the theme in `LocalStorage` or `SessionStorage`. | `LocalStorage` |
| `storage_name` | `&'static str` | Key name for storing the selected theme in browser storage. | `"theme"` |
| `forced_theme` | `Option<Theme>` | Overrides all other theme logic if provided. | `None` |
| `custom_themes` | `HashMap<String, Rc<CustomTheme>>` | Map of user-defined themes. Can be applied and previewed. | `{}` |
| `children` | `Element` | Child components that will have access to the theme context. | **Required** |

#### Behavioral Props

| Property | Type | Description | Default |
| ------------------ | --------------------------- | -------------------------------------------------------------------- | ------- |
| `reset_to_system` | `Callback<()>` | Reverts the theme to follow the system theme. | no-op |
| `apply_preview` | `Callback<Theme>` | Applies a temporary theme preview (doesn't persist or update state). | no-op |
| `set_custom_theme` | `Callback<Rc<CustomTheme>>` | Adds a new custom theme if it passes validation. | no-op |

## 💡 Notes

1. **Auto System Theme Support**: When `Theme::System` is used, the component tracks `prefers-color-scheme` and switches between light and dark automatically based on system settings.

1. **Time-Based Theme Switching**: If no preference is stored, `Theme::System` will fall back to light mode during 7 AM - 6:59 PM and dark mode otherwise.

1. **Forced Theme**: When `forced_theme` is provided, it overrides all system, storage, or runtime theme choices, effectively locking the app to that theme.

1. **Custom Themes**: Add your own themes and styles dynamically. Each must implement the `validate()` method to ensure it's structured correctly.

1. **Tailwind Compatibility (v3 or lower)**: This provider works with Tailwind CSS's `data-theme=` and `class=` bindings, making it compatible with libraries like [DaisyUI](https://daisyui.com). It sets:

- `data-theme`
- `class`
- `style="color-scheme:..."` on the root HTML element.

1. **Storage Syncing**: Theme changes are synced across tabs and windows using the `storage` event.

1. **Easy API**: Use `set_theme`, `reset_to_system`, or `apply_preview` to control appearance from any component.

1. **Hooks First**: Just use `use_theme()` to access all theme information and actions within your components.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
| Framework | Live Demo |
| --- | --- |
| Yew | [![Netlify Status](https://api.netlify.com/api/v1/badges/a0efc7e9-f20e-4dd9-93e1-c8f4fde7506f/deploy-status)](https://theme-rs.netlify.app) |
| Dioxus | TODO |
| Dioxus | [![Netlify Status](https://api.netlify.com/api/v1/badges/a0efc7e9-f20e-4dd9-93e1-c8f4fde7506f/deploy-status)](https://theme-dio.netlify.app) |
| Leptos | TODO |

## 📜 Intro
Expand All @@ -47,7 +47,7 @@
<!-- absolute url for docs.rs cause YEW.md is not included in crate -->
Refer to [our guide](https://github.com/opensass/theme/blob/main/YEW.md) to integrate this component into your Yew app.

## 🧬 Dioxus Usage (TODO)
## 🧬 Dioxus Usage

<!-- absolute url for docs.rs cause DIOXUS.md is not included in crate -->
Refer to [our guide](https://github.com/opensass/theme/blob/main/DIOXUS.md) to integrate this component into your Dioxus app.
Expand Down
Loading