mirror of
https://github.com/adoyle0/thaw.git
synced 2025-02-02 08:34:15 -05:00
✨ feat: perfect theme
This commit is contained in:
parent
c0160ff8dc
commit
277ee00d3d
6 changed files with 97 additions and 38 deletions
|
@ -7,6 +7,8 @@ fn main() {
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn App(cx: Scope) -> impl IntoView {
|
pub fn App(cx: Scope) -> impl IntoView {
|
||||||
|
let (theme, set_theme) = create_signal(cx, Theme::light());
|
||||||
|
provide_context(cx, theme);
|
||||||
let (count, set_count) = create_signal(cx, 0.0);
|
let (count, set_count) = create_signal(cx, 0.0);
|
||||||
let (open, set_open) = create_signal(cx, true);
|
let (open, set_open) = create_signal(cx, true);
|
||||||
let (button_type, set_button_type) = create_signal(cx, ButtonType::TEXT);
|
let (button_type, set_button_type) = create_signal(cx, ButtonType::TEXT);
|
||||||
|
@ -21,6 +23,7 @@ pub fn App(cx: Scope) -> impl IntoView {
|
||||||
view! { cx,
|
view! { cx,
|
||||||
<Space>
|
<Space>
|
||||||
<Input value=count_string.get() on_input=on_input/>
|
<Input value=count_string.get() on_input=on_input/>
|
||||||
|
<Button on:click=move |_| set_theme.update(move |value| *value = Theme::dark()) type_=button_type>"theme"</Button>
|
||||||
<Button on:click=move |_| set_button_type.update(move |value| *value = ButtonType::PRIMARY)>"click"</Button>
|
<Button on:click=move |_| set_button_type.update(move |value| *value = ButtonType::PRIMARY)>"click"</Button>
|
||||||
<Button on:click=move |_| set_count.update(move |value| *value += 1.0) type_=button_type>"click"</Button>
|
<Button on:click=move |_| set_count.update(move |value| *value += 1.0) type_=button_type>"click"</Button>
|
||||||
{move || count.get()}
|
{move || count.get()}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod theme;
|
mod theme;
|
||||||
use crate::{theme::Theme, utils::mount_style::mount_style};
|
use crate::{theme::*, utils::mount_style::mount_style};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use stylers::style_sheet_str;
|
use stylers::style_sheet_str;
|
||||||
pub use theme::ButtonTheme;
|
pub use theme::ButtonTheme;
|
||||||
|
@ -9,17 +9,29 @@ pub enum ButtonType {
|
||||||
#[default]
|
#[default]
|
||||||
PRIMARY,
|
PRIMARY,
|
||||||
SOLID,
|
SOLID,
|
||||||
TEXT
|
TEXT,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
pub enum ButtonColor {
|
pub enum ButtonColor {
|
||||||
#[default]
|
#[default]
|
||||||
PRIMARY,
|
PRIMARY,
|
||||||
|
SUCCESS,
|
||||||
WARNING,
|
WARNING,
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ButtonColor {
|
||||||
|
pub fn theme_color(&self, theme: &Theme) -> String {
|
||||||
|
match self {
|
||||||
|
ButtonColor::PRIMARY => theme.common.color_primary.clone(),
|
||||||
|
ButtonColor::SUCCESS => theme.common.color_success.clone(),
|
||||||
|
ButtonColor::WARNING => theme.common.color_warning.clone(),
|
||||||
|
ButtonColor::Error => theme.common.color_error.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Button(
|
pub fn Button(
|
||||||
cx: Scope,
|
cx: Scope,
|
||||||
|
@ -27,18 +39,22 @@ pub fn Button(
|
||||||
#[prop(optional, into)] color: MaybeSignal<ButtonColor>,
|
#[prop(optional, into)] color: MaybeSignal<ButtonColor>,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
// let theme = use_context::<ReadSignal<Theme>>(cx);
|
let theme = use_theme(cx, Theme::light);
|
||||||
// let css_vars = create_memo(cx, |_| format!("--font-color"));
|
let css_vars = create_memo(cx, move |_| {
|
||||||
|
let mut css_vars = String::new();
|
||||||
|
let theme = theme.get();
|
||||||
|
let bg_color = color.get().theme_color(&theme);
|
||||||
|
css_vars.push_str(&format!("--background-color: {bg_color}"));
|
||||||
|
css_vars
|
||||||
|
});
|
||||||
let class_name = mount_style("button", || style_sheet_str!("./src/button/button.css"));
|
let class_name = mount_style("button", || style_sheet_str!("./src/button/button.css"));
|
||||||
let class = move || {
|
|
||||||
if type_.get() == ButtonType::TEXT {
|
|
||||||
"melt-button melt-button--text"
|
|
||||||
} else {
|
|
||||||
"melt-button"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
view! {cx, class=class_name,
|
view! {cx, class=class_name,
|
||||||
<button class=class>
|
<button
|
||||||
|
class:melt-button=true
|
||||||
|
class=("melt-button--text", move || type_.get() == ButtonType::TEXT)
|
||||||
|
style=move || css_vars.get()
|
||||||
|
>
|
||||||
{children(cx)}
|
{children(cx)}
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::theme::ThemeMethod;
|
use crate::theme::ThemeMethod;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ButtonTheme {
|
pub struct ButtonTheme {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,3 +15,4 @@ pub use modal::*;
|
||||||
pub use progress::*;
|
pub use progress::*;
|
||||||
pub use space::*;
|
pub use space::*;
|
||||||
pub use table::*;
|
pub use table::*;
|
||||||
|
pub use theme::Theme;
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
use super::ThemeMethod;
|
use super::ThemeMethod;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct CommonTheme {
|
pub struct CommonTheme {
|
||||||
pub font_family: String,
|
pub font_family: String,
|
||||||
|
|
||||||
pub color_primary: String,
|
pub color_primary: String,
|
||||||
|
pub color_success: String,
|
||||||
|
pub color_warning: String,
|
||||||
|
pub color_error: String,
|
||||||
|
|
||||||
pub font_size: String,
|
pub font_size: String,
|
||||||
pub font_size_small: String,
|
pub font_size_small: String,
|
||||||
|
@ -22,12 +27,15 @@ pub struct CommonTheme {
|
||||||
pub border_radius_large: String,
|
pub border_radius_large: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ThemeMethod for CommonTheme {
|
impl CommonTheme {
|
||||||
fn light() -> Self {
|
fn common() -> Self {
|
||||||
Self {
|
Self {
|
||||||
font_family: "-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji'".into(),
|
font_family: "-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji'".into(),
|
||||||
|
|
||||||
color_primary: "#f5222d".into(),
|
color_primary: "".into(),
|
||||||
|
color_success: "".into(),
|
||||||
|
color_warning: "".into(),
|
||||||
|
color_error: "".into(),
|
||||||
|
|
||||||
font_size: "14px".into(),
|
font_size: "14px".into(),
|
||||||
font_size_small: "12px".into(),
|
font_size_small: "12px".into(),
|
||||||
|
@ -47,28 +55,25 @@ impl ThemeMethod for CommonTheme {
|
||||||
border_radius_large: "8px".into(),
|
border_radius_large: "8px".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ThemeMethod for CommonTheme {
|
||||||
|
fn light() -> Self {
|
||||||
|
Self {
|
||||||
|
color_primary: "#f5222d".into(),
|
||||||
|
color_success: "#18a058".into(),
|
||||||
|
color_warning: "#f0a020".into(),
|
||||||
|
color_error: "#d03050".into(),
|
||||||
|
..CommonTheme::common()
|
||||||
|
}
|
||||||
|
}
|
||||||
fn dark() -> Self {
|
fn dark() -> Self {
|
||||||
Self {
|
Self {
|
||||||
font_family: "-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji'".into(),
|
|
||||||
|
|
||||||
color_primary: "#d32029".into(),
|
color_primary: "#d32029".into(),
|
||||||
|
color_success: "#18a058".into(),
|
||||||
font_size: "14px".into(),
|
color_warning: "#f0a020".into(),
|
||||||
font_size_small: "12px".into(),
|
color_error: "#d03050".into(),
|
||||||
font_size_medium: "16px".into(),
|
..CommonTheme::common()
|
||||||
font_size_large: "20px".into(),
|
|
||||||
font_size_huge: "24px".into(),
|
|
||||||
|
|
||||||
line_height: "22px".into(),
|
|
||||||
line_height_small: "20px".into(),
|
|
||||||
line_height_medium: "24px".into(),
|
|
||||||
line_height_large: "28px".into(),
|
|
||||||
line_height_huge: "32px".into(),
|
|
||||||
|
|
||||||
border_radius: "3px".into(),
|
|
||||||
border_radius_small: "2px".into(),
|
|
||||||
border_radius_medium: "4px".into(),
|
|
||||||
border_radius_large: "8px".into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
mod common;
|
mod common;
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
use self::common::CommonTheme;
|
use self::common::CommonTheme;
|
||||||
use crate::ButtonTheme;
|
use crate::ButtonTheme;
|
||||||
|
|
||||||
|
@ -7,9 +9,25 @@ pub trait ThemeMethod {
|
||||||
fn dark() -> Self;
|
fn dark() -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
common: CommonTheme,
|
pub common: CommonTheme,
|
||||||
button: ButtonTheme,
|
pub button: ButtonTheme,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Theme {
|
||||||
|
pub fn light() -> Self {
|
||||||
|
Self {
|
||||||
|
common: CommonTheme::light(),
|
||||||
|
button: ButtonTheme::light(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn dark() -> Self {
|
||||||
|
Self {
|
||||||
|
common: CommonTheme::dark(),
|
||||||
|
button: ButtonTheme::dark(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ThemeMethod for Theme {
|
impl ThemeMethod for Theme {
|
||||||
|
@ -26,3 +44,17 @@ impl ThemeMethod for Theme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn use_theme(cx: Scope, default: impl Fn() -> Theme) -> ReadSignal<Theme> {
|
||||||
|
use_context::<ReadSignal<Theme>>(cx).unwrap_or_else(|| create_signal(cx, default()).0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::{use_theme, Theme, ThemeMethod};
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
fn t_use_theme(cx: Scope) {
|
||||||
|
use_theme(cx, Theme::dark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue