feat: public theme

This commit is contained in:
luoxiao 2023-10-24 21:49:36 +08:00
parent 5c1943bdd4
commit 263db0c3e8
5 changed files with 67 additions and 12 deletions

View file

@ -15,7 +15,7 @@ icondata = { version = "0.1.0", features = [
] } ] }
leptos_router = { version = "0.5.1", features = ["csr"] } leptos_router = { version = "0.5.1", features = ["csr"] }
leptos_devtools = "0.0.1" leptos_devtools = "0.0.1"
prisms = { git = "https://github.com/luoxiaozero/prisms" } prisms = { git = "https://github.com/luoxiaozero/prisms", rev = "16d4d34b93fc20578ebf03137d54ecc7eafa4d4b" }
[features] [features]
tracing = ["leptos/tracing"] tracing = ["leptos/tracing"]

View file

@ -5,8 +5,10 @@ use melt_ui::*;
#[component] #[component]
pub fn App() -> impl IntoView { pub fn App() -> impl IntoView {
let theme = create_rw_signal(Theme::light());
provide_context(theme);
view! { view! {
<MessageProvider> <Provider theme=theme.split().0>
<Router base="/melt-ui"> <Router base="/melt-ui">
<Routes base="/melt-ui".to_string()> <Routes base="/melt-ui".to_string()>
<Route path="/" view=Home/> <Route path="/" view=Home/>
@ -47,6 +49,21 @@ pub fn App() -> impl IntoView {
<Route path="/mobile/toast" view=ToastDemoPage/> <Route path="/mobile/toast" view=ToastDemoPage/>
</Routes> </Routes>
</Router> </Router>
</MessageProvider> </Provider>
} }
} }
#[component]
fn Provider(theme: ReadSignal<Theme>, children: Children) -> impl IntoView {
view! {
<ThemeProvider theme>
<MessageProvider>
{children()}
</MessageProvider>
</ThemeProvider>
}
}
pub fn use_rw_theme() -> RwSignal<Theme> {
expect_context::<RwSignal<Theme>>()
}

View file

@ -1,9 +1,19 @@
use crate::app::use_rw_theme;
use leptos::*; use leptos::*;
use leptos_router::use_navigate; use leptos_router::use_navigate;
use melt_ui::*; use melt_ui::*;
#[component] #[component]
pub fn SiteHeader() -> impl IntoView { pub fn SiteHeader() -> impl IntoView {
let theme = use_rw_theme();
let theme_name = create_memo(move |_| theme.with(|theme| theme.name.clone()));
let on_theme = move |_| {
if theme_name.get_untracked() != "Light".to_string() {
theme.set(Theme::light())
} else {
theme.set(Theme::dark())
}
};
view! { view! {
<LayoutHeader style="height: 54px; display: flex; align-items: center; justify-content: space-between; padding: 0 20px; border-bottom: 1px solid #e5e8eb"> <LayoutHeader style="height: 54px; display: flex; align-items: center; justify-content: space-between; padding: 0 20px; border-bottom: 1px solid #e5e8eb">
<span <span
@ -16,15 +26,24 @@ pub fn SiteHeader() -> impl IntoView {
"Melt UI" "Melt UI"
</span> </span>
<Button <Space>
variant=ButtonVariant::Text <Button
on:click=move |_| { variant=ButtonVariant::Text
_ = window().open_with_url("http://github.com/luoxiaozero/melt-ui"); on:click=on_theme
} >
> {move || theme_name.get()}
</Button>
<Button
variant=ButtonVariant::Text
on:click=move |_| {
_ = window().open_with_url("http://github.com/luoxiaozero/melt-ui");
}
>
"Github"
</Button>
</Space>
"Github"
</Button>
</LayoutHeader> </LayoutHeader>
} }
} }

View file

@ -64,7 +64,7 @@ pub use switch::*;
pub use table::*; pub use table::*;
pub use tabs::*; pub use tabs::*;
pub use tag::*; pub use tag::*;
pub use theme::Theme; pub use theme::*;
pub use upload::*; pub use upload::*;
pub use utils::{mount_style::mount_style, signal::SignalWatch}; pub use utils::{mount_style::mount_style, signal::SignalWatch};
pub use wave::*; pub use wave::*;

View file

@ -11,6 +11,7 @@ pub trait ThemeMethod {
#[derive(Clone)] #[derive(Clone)]
pub struct Theme { pub struct Theme {
pub name: String,
pub common: CommonTheme, pub common: CommonTheme,
pub button: ButtonTheme, pub button: ButtonTheme,
pub input: InputTheme, pub input: InputTheme,
@ -24,6 +25,7 @@ pub struct Theme {
impl Theme { impl Theme {
pub fn light() -> Self { pub fn light() -> Self {
Self { Self {
name: "Light".into(),
common: CommonTheme::light(), common: CommonTheme::light(),
button: ButtonTheme::light(), button: ButtonTheme::light(),
input: InputTheme::light(), input: InputTheme::light(),
@ -36,6 +38,7 @@ impl Theme {
} }
pub fn dark() -> Self { pub fn dark() -> Self {
Self { Self {
name: "Dark".into(),
common: CommonTheme::dark(), common: CommonTheme::dark(),
button: ButtonTheme::dark(), button: ButtonTheme::dark(),
input: InputTheme::dark(), input: InputTheme::dark(),
@ -51,6 +54,7 @@ impl Theme {
impl ThemeMethod for Theme { impl ThemeMethod for Theme {
fn light() -> Self { fn light() -> Self {
Self { Self {
name: "Light".into(),
common: CommonTheme::light(), common: CommonTheme::light(),
button: ButtonTheme::light(), button: ButtonTheme::light(),
input: InputTheme::light(), input: InputTheme::light(),
@ -63,6 +67,7 @@ impl ThemeMethod for Theme {
} }
fn dark() -> Self { fn dark() -> Self {
Self { Self {
name: "Dark".into(),
common: CommonTheme::dark(), common: CommonTheme::dark(),
button: ButtonTheme::dark(), button: ButtonTheme::dark(),
input: InputTheme::dark(), input: InputTheme::dark(),
@ -75,6 +80,20 @@ impl ThemeMethod for Theme {
} }
} }
#[component]
pub fn ThemeProvider(
#[prop(optional, into)] theme: Option<ReadSignal<Theme>>,
children: Children,
) -> impl IntoView {
let theme = if let Some(theme) = theme {
theme
} else {
create_signal(Theme::light()).0
};
provide_context(theme);
children()
}
pub fn use_theme(default: impl Fn() -> Theme) -> ReadSignal<Theme> { pub fn use_theme(default: impl Fn() -> Theme) -> ReadSignal<Theme> {
use_context::<ReadSignal<Theme>>().unwrap_or_else(|| create_signal(default()).0) use_context::<ReadSignal<Theme>>().unwrap_or_else(|| create_signal(default()).0)
} }