diff --git a/demo/src/pages/components.rs b/demo/src/pages/components.rs index 70e5811..491ec12 100644 --- a/demo/src/pages/components.rs +++ b/demo/src/pages/components.rs @@ -143,6 +143,10 @@ pub(crate) fn gen_menu_data() -> Vec { value: "/components/avatar".into(), label: "Avatar".into(), }, + MenuItemOption { + value: "/components/badge".into(), + label: "Badge".into(), + }, MenuItemOption { value: "/components/breadcrumb".into(), label: "Breadcrumb".into(), @@ -259,10 +263,6 @@ pub(crate) fn gen_menu_data() -> Vec { value: "/components/alert".into(), label: "Alert".into(), }, - MenuItemOption { - value: "/components/badge".into(), - label: "Badge".into(), - }, MenuItemOption { value: "/components/drawer".into(), label: "Drawer".into(), diff --git a/demo_markdown/docs/badge/mod.md b/demo_markdown/docs/badge/mod.md index 72365a0..a5a8111 100644 --- a/demo_markdown/docs/badge/mod.md +++ b/demo_markdown/docs/badge/mod.md @@ -1,33 +1,92 @@ # Badge ```rust demo -let value = create_rw_signal(0); +view! { + +} +``` +### Appearance + +```rust demo view! { - - - - - - - - - - - - - - - "value:" - {move || value.get()} + "999+" + "999+" + "999+" + "999+" + +} +``` + +### Sizes + +```rust demo +view! { + + + + + + + + +} +``` + +### Color + +```rust demo +view! { + + + "999+" + "999+" + "999+" + "999+" + + + "999+" + "999+" + "999+" + "999+" + + + "999+" + "999+" + "999+" + "999+" + + + "999+" + "999+" + "999+" + "999+" + + + "999+" + "999+" + "999+" + "999+" + + + "999+" + "999+" + "999+" + "999+" + + + "999+" + "999+" + "999+" + "999+" + + + "999+" + "999+" + "999+" + "999+" + } ``` diff --git a/thaw/src/badge/badge.css b/thaw/src/badge/badge.css index e245bbc..950e519 100644 --- a/thaw/src/badge/badge.css +++ b/thaw/src/badge/badge.css @@ -1,28 +1,220 @@ .thaw-badge { + display: inline-flex; + box-sizing: border-box; + align-items: center; + justify-content: center; position: relative; - display: inline-block; -} -.thaw-badge__sup { - position: absolute; - color: var(--thaw-font-color); - background-color: var(--thaw-background-color); - z-index: 10; -} -.thaw-badge__sup--value { - top: -9px; - right: -9px; - font-size: 12px; - height: 18px; - line-height: 18px; - border-radius: 9px; - padding: 0 6px; - text-align: center; + font-family: var(--fontFamilyBase); + font-size: var(--fontSizeBase200); + font-weight: var(--fontWeightSemibold); + line-height: var(--lineHeightBase200); + height: 20px; + width: 20px; + min-width: max-content; + padding: 0 calc(var(--spacingHorizontalXS) + var(--spacingHorizontalXXS)); + border-radius: var(--borderRadiusCircular); + border-color: var(--colorTransparentStroke); } -.thaw-badge__sup--dot { - top: -5px; - right: -5px; +.thaw-badge--filled { + color: var(--colorNeutralForegroundOnBrand); + background-color: var(--colorBrandBackground); +} + +.thaw-badge--filled.thaw-badge--danger { + background-color: var(--colorPaletteRedBackground3); +} + +.thaw-badge--filled.thaw-badge--important { + color: var(--colorNeutralBackground1); + background-color: var(--colorNeutralForeground1); +} + +.thaw-badge--filled.thaw-badge--informative { + color: var(--colorNeutralForeground3); + background-color: var(--colorNeutralBackground5); +} + +.thaw-badge--filled.thaw-badge--severe { + background-color: var(--colorPaletteDarkOrangeBackground3); +} + +.thaw-badge--filled.thaw-badge--subtle { + color: var(--colorNeutralForeground1); + background-color: var(--colorNeutralBackground1); +} + +.thaw-badge--filled.thaw-badge--success { + background-color: var(--colorPaletteGreenBackground3); +} + +.thaw-badge--filled.thaw-badge--warning { + color: var(--colorNeutralForeground1Static); + background-color: var(--colorPaletteYellowBackground3); +} + +.thaw-badge--ghost { + color: var(--colorBrandForeground1); +} + +.thaw-badge--ghost.thaw-badge--danger { + color: var(--colorPaletteRedForeground3); +} + +.thaw-badge--ghost.thaw-badge--important { + color: var(--colorNeutralForeground1); +} + +.thaw-badge--ghost.thaw-badge--informative { + color: var(--colorNeutralForeground3); +} + +.thaw-badge--ghost.thaw-badge--severe { + color: var(--colorPaletteDarkOrangeForeground3); +} + +.thaw-badge--ghost.thaw-badge--subtle { + color: var(--colorNeutralForegroundStaticInverted); +} + +.thaw-badge--ghost.thaw-badge--success { + color: var(--colorPaletteGreenForeground3); +} + +.thaw-badge--ghost.thaw-badge--warning { + color: var(--colorPaletteYellowForeground2); +} + +.thaw-badge--outline { + color: var(--colorBrandForeground1); + border-color: currentcolor; +} + +.thaw-badge--outline.thaw-badge--danger { + color: var(--colorPaletteRedForeground3); + border-color: var(--colorPaletteRedBorder2); +} + +.thaw-badge--outline.thaw-badge--important { + color: var(--colorNeutralForeground3); + border-color: var(--colorNeutralStrokeAccessible); +} + +.thaw-badge--outline.thaw-badge--informative { + color: var(--colorNeutralForeground3); + border-color: var(--colorNeutralStroke2); +} + +.thaw-badge--outline.thaw-badge--severe { + color: var(--colorPaletteDarkOrangeForeground3); +} + +.thaw-badge--outline.thaw-badge--subtle { + color: var(--colorNeutralForegroundStaticInverted); +} + +.thaw-badge--outline.thaw-badge--success { + color: var(--colorPaletteGreenForeground3); + border-color: var(--colorPaletteGreenBorder2); +} + +.thaw-badge--outline.thaw-badge--warning { + color: var(--colorPaletteYellowForeground2); +} + +.thaw-badge--tint { + color: var(--colorBrandForeground2); + background-color: var(--colorBrandBackground2); + border-color: var(--colorBrandStroke2); +} + +.thaw-badge--tint.thaw-badge--danger { + background-color: var(--colorPaletteRedBackground1); + color: var(--colorPaletteRedForeground1); + border-color: var(--colorPaletteRedBorder1); +} + +.thaw-badge--tint.thaw-badge--important { + background-color: var(--colorNeutralForeground3); + color: var(--colorNeutralBackground1); + border-color: var(--colorTransparentStroke); +} + +.thaw-badge--tint.thaw-badge--informative { + background-color: var(--colorNeutralBackground4); + color: var(--colorNeutralForeground3); + border-color: var(--colorNeutralStroke2); +} + +.thaw-badge--tint.thaw-badge--severe { + background-color: var(--colorPaletteDarkOrangeBackground1); + color: var(--colorPaletteDarkOrangeForeground1); + border-color: var(--colorPaletteDarkOrangeBorder1); +} + +.thaw-badge--tint.thaw-badge--subtle { + background-color: var(--colorNeutralBackground1); + color: var(--colorNeutralForeground3); + border-color: var(--colorNeutralStroke2); +} + +.thaw-badge--tint.thaw-badge--success { + background-color: var(--colorPaletteGreenBackground1); + color: var(--colorPaletteGreenForeground1); + border-color: var(--colorPaletteGreenBorder1); +} + +.thaw-badge--tint.thaw-badge--warning { + background-color: var(--colorPaletteYellowBackground1); + color: var(--colorPaletteYellowForeground1); + border-color: var(--colorPaletteYellowBorder1); +} + +.thaw-badge--tiny { + min-width: unset; + line-height: 4px; + font-size: 4px; + height: 6px; + width: 6px; + padding: unset; +} + +.thaw-badge--extra-small { + min-width: unset; + line-height: 6px; + font-size: 6px; height: 10px; width: 10px; - border-radius: 50%; + padding: unset; +} + +.thaw-badge--small { + line-height: var(--lineHeightBase100); + font-size: var(--fontSizeBase100); + height: 16px; + width: 16px; + padding: 0 calc(var(--spacingHorizontalXXS) + var(--spacingHorizontalXXS)); +} + +.thaw-badge--large { + height: 24px; + width: 24px; + padding: 0 calc(var(--spacingHorizontalXS) + var(--spacingHorizontalXXS)); +} + +.thaw-badge--extra-large { + height: 32px; + width: 32px; + padding: 0 + calc(var(--spacingHorizontalSNudge) + var(--spacingHorizontalXXS)); +} + +.thaw-badge::after { + content: ""; + position: absolute; + inset: 0px; + border-style: solid; + border-color: inherit; + border-width: var(--strokeWidthThin); + border-radius: inherit; } diff --git a/thaw/src/badge/badge.rs b/thaw/src/badge/badge.rs new file mode 100644 index 0000000..9c8b67d --- /dev/null +++ b/thaw/src/badge/badge.rs @@ -0,0 +1,106 @@ +use leptos::*; +use thaw_components::OptionComp; +use thaw_utils::{class_list, mount_style}; + +#[component] +pub fn Badge( + #[prop(optional, into)] class: MaybeProp, + /// A Badge can be filled, outline, ghost, inverted + #[prop(optional, into)] + appearance: MaybeSignal, + /// A Badge can be on of several preset sizes. + #[prop(optional, into)] + size: MaybeSignal, + /// A Badge can be one of preset colors. + #[prop(optional, into)] + color: MaybeSignal, + #[prop(optional)] children: Option, +) -> impl IntoView { + mount_style("badge", include_str!("./badge.css")); + + view! { +
+ + {children()} + +
+ } +} + +#[derive(Default, Clone)] +pub enum BadgeAppearance { + #[default] + Filled, + Ghost, + Outline, + Tint, +} + +impl BadgeAppearance { + pub fn as_str(&self) -> &'static str { + match self { + BadgeAppearance::Filled => "filled", + BadgeAppearance::Ghost => "ghost", + BadgeAppearance::Outline => "outline", + BadgeAppearance::Tint => "tint", + } + } +} + +#[derive(Default, Clone)] +pub enum BadgeSize { + Tiny, + ExtraSmall, + Small, + #[default] + Medium, + Large, + ExtraLarge, +} + +impl BadgeSize { + pub fn as_str(&self) -> &'static str { + match self { + BadgeSize::Tiny => "tiny", + BadgeSize::ExtraSmall => "extra-small", + BadgeSize::Small => "small", + BadgeSize::Medium => "medium", + BadgeSize::Large => "large", + BadgeSize::ExtraLarge => "extra-large", + } + } +} + +#[derive(Default, Clone)] +pub enum BadgeColor { + #[default] + Brand, + Danger, + Important, + Informative, + Severe, + Subtle, + Success, + Warning, +} + +impl BadgeColor { + pub fn as_str(&self) -> &'static str { + match self { + BadgeColor::Brand => "brand", + BadgeColor::Danger => "danger", + BadgeColor::Important => "important", + BadgeColor::Informative => "informative", + BadgeColor::Severe => "severe", + BadgeColor::Subtle => "subtle", + BadgeColor::Success => "success", + BadgeColor::Warning => "warning", + } + } +} diff --git a/thaw/src/badge/mod.rs b/thaw/src/badge/mod.rs index 9af81d6..130902d 100644 --- a/thaw/src/badge/mod.rs +++ b/thaw/src/badge/mod.rs @@ -1,67 +1,3 @@ -use crate::{theme::use_theme, Theme}; -use leptos::*; -use thaw_utils::{class_list, mount_style, OptionalProp}; +mod badge; -#[derive(Default, Clone)] -pub enum BadgeVariant { - Success, - Warning, - #[default] - Error, -} - -impl BadgeVariant { - fn theme_color(&self, theme: &Theme) -> String { - match self { - BadgeVariant::Success => theme.common.color_success.clone(), - BadgeVariant::Warning => theme.common.color_warning.clone(), - BadgeVariant::Error => theme.common.color_error.clone(), - } - } -} - -#[component] -pub fn Badge( - #[prop(optional, into)] value: MaybeSignal, - #[prop(default = MaybeSignal::Static(u32::MAX), into)] max: MaybeSignal, - #[prop(optional, into)] variant: MaybeSignal, - #[prop(optional, into)] dot: MaybeSignal, - #[prop(optional, into)] class: OptionalProp>, - children: Children, -) -> impl IntoView { - let theme = use_theme(Theme::light); - mount_style("badge", include_str!("./badge.css")); - let css_vars = create_memo(move |_| { - let mut css_vars = String::new(); - css_vars.push_str("--thaw-font-color: #fff;"); - theme.with(|theme| { - css_vars.push_str(&format!( - "--thaw-background-color: {};", - variant.get().theme_color(theme) - )); - }); - css_vars - }); - let value = create_memo(move |_| { - let value = value.get(); - let max_value = max.get(); - if value == 0 { - String::new() - } else if max_value < value { - format!("{max_value}+") - } else { - value.to_string() - } - }); - - view! { -
-
{move || value.get()}
- {children()} -
- } -} +pub use badge::*; \ No newline at end of file diff --git a/thaw/src/theme/color.rs b/thaw/src/theme/color.rs index f5148bf..95ef5bd 100644 --- a/thaw/src/theme/color.rs +++ b/thaw/src/theme/color.rs @@ -12,6 +12,7 @@ pub struct ColorTheme { pub color_neutral_background_4: String, pub color_neutral_background_4_hover: String, pub color_neutral_background_4_pressed: String, + pub color_neutral_background_5: String, pub color_neutral_background_6: String, pub color_neutral_foreground_disabled: String, @@ -50,9 +51,37 @@ pub struct ColorTheme { pub color_brand_background: String, pub color_brand_background_hover: String, pub color_brand_background_pressed: String, + pub color_brand_background_2: String, + pub color_brand_foreground_1: String, + pub color_brand_foreground_2: String, pub color_brand_stroke_1: String, + pub color_brand_stroke_2: String, pub color_brand_stroke_2_contrast: String, + pub color_palette_red_background_1: String, + pub color_palette_red_background_3: String, + pub color_palette_red_foreground_1: String, + pub color_palette_red_foreground_3: String, + pub color_palette_red_border_1: String, + pub color_palette_red_border_2: String, + pub color_palette_green_background_1: String, + pub color_palette_green_background_3: String, + pub color_palette_green_foreground_1: String, + pub color_palette_green_foreground_3: String, + pub color_palette_green_border_1: String, + pub color_palette_green_border_2: String, + pub color_palette_yellow_background_1: String, + pub color_palette_yellow_background_3: String, + pub color_palette_yellow_foreground_1: String, + pub color_palette_yellow_foreground_2: String, + pub color_palette_yellow_border_1: String, + + pub color_palette_dark_orange_background_1: String, + pub color_palette_dark_orange_background_3: String, + pub color_palette_dark_orange_foreground_1: String, + pub color_palette_dark_orange_foreground_3: String, + pub color_palette_dark_orange_border_1: String, + pub color_subtle_background: String, pub color_subtle_background_hover: String, pub color_subtle_background_pressed: String, @@ -77,6 +106,7 @@ impl ColorTheme { color_neutral_background_4: "#f0f0f0".into(), color_neutral_background_4_hover: "#fafafa".into(), color_neutral_background_4_pressed: "#f5f5f5".into(), + color_neutral_background_5: "#ebebeb".into(), color_neutral_background_6: "#e6e6e6".into(), color_neutral_foreground_disabled: "#bdbdbd".into(), @@ -116,8 +146,37 @@ impl ColorTheme { color_brand_background: "#0f6cbd".into(), color_brand_background_hover: "#115ea3".into(), color_brand_background_pressed: "#0c3b5e".into(), + color_brand_background_2: "#ebf3fc".into(), + color_brand_foreground_1: "#0f6cbd".into(), + color_brand_foreground_2: "#115ea3".into(), color_brand_stroke_1: "#0f6cbd".into(), + color_brand_stroke_2: "#b4d6fa".into(), color_brand_stroke_2_contrast: "#b4d6fa".into(), + + color_palette_red_background_1: "#fdf6f6".into(), + color_palette_red_background_3: "#d13438".into(), + color_palette_red_foreground_1: "#bc2f32".into(), + color_palette_red_foreground_3: "#d13438".into(), + color_palette_red_border_1: "#f1bbbc".into(), + color_palette_red_border_2: "#d13438".into(), + color_palette_green_background_1: "#f1faf1".into(), + color_palette_green_background_3: "#107c10".into(), + color_palette_green_foreground_1: "#0e700e".into(), + color_palette_green_foreground_3: "#107c10".into(), + color_palette_green_border_1: "#9fd89f".into(), + color_palette_green_border_2: "#107c10".into(), + color_palette_yellow_background_1: "#fffef5".into(), + color_palette_yellow_background_3: "#fde300".into(), + color_palette_yellow_foreground_1: "#817400".into(), + color_palette_yellow_foreground_2: "#817400".into(), + color_palette_yellow_border_1: "#fef7b2".into(), + + color_palette_dark_orange_background_1: "#fdf6f3".into(), + color_palette_dark_orange_background_3: "#da3b01".into(), + color_palette_dark_orange_foreground_1: "#c43501".into(), + color_palette_dark_orange_foreground_3: "#da3b01".into(), + color_palette_dark_orange_border_1: "#f4bfab".into(), + color_subtle_background: "transparent".into(), color_subtle_background_hover: "#f5f5f5".into(), color_subtle_background_pressed: "#e0e0e0".into(), @@ -142,6 +201,7 @@ impl ColorTheme { color_neutral_background_4: "#0a0a0a".into(), color_neutral_background_4_hover: "#1f1f1f".into(), color_neutral_background_4_pressed: "#000000".into(), + color_neutral_background_5: "#000000".into(), color_neutral_background_6: "#333333".into(), color_neutral_foreground_disabled: "#5c5c5c".into(), @@ -181,9 +241,37 @@ impl ColorTheme { color_brand_background: "#115ea3".into(), color_brand_background_hover: "#0f6cbd".into(), color_brand_background_pressed: "#0c3b5e".into(), + color_brand_background_2: "#082338".into(), + color_brand_foreground_1: "#479ef5".into(), + color_brand_foreground_2: "#62abf5".into(), color_brand_stroke_1: "#479ef5".into(), + color_brand_stroke_2: "#0e4775".into(), color_brand_stroke_2_contrast: "#0e4775".into(), + color_palette_red_background_1: "#3f1011".into(), + color_palette_red_background_3: "#d13438".into(), + color_palette_red_foreground_1: "#e37d80".into(), + color_palette_red_foreground_3: "#e37d80".into(), + color_palette_red_border_1: "#d13438".into(), + color_palette_red_border_2: "#e37d80".into(), + color_palette_green_background_1: "#052505".into(), + color_palette_green_background_3: "#107c10".into(), + color_palette_green_foreground_1: "#54b054".into(), + color_palette_green_foreground_3: "#9fd89f".into(), + color_palette_green_border_1: "#107c10".into(), + color_palette_green_border_2: "#9fd89f".into(), + color_palette_yellow_background_1: "#4c4400".into(), + color_palette_yellow_background_3: "#fde300".into(), + color_palette_yellow_foreground_1: "#feee66".into(), + color_palette_yellow_foreground_2: "#fef7b2".into(), + color_palette_yellow_border_1: "#fde300".into(), + + color_palette_dark_orange_background_1: "#411200".into(), + color_palette_dark_orange_background_3: "#da3b01".into(), + color_palette_dark_orange_foreground_1: "#e9835e".into(), + color_palette_dark_orange_foreground_3: "#e9835e".into(), + color_palette_dark_orange_border_1: "#da3b01".into(), + color_subtle_background: "transparent".into(), color_subtle_background_hover: "#383838".into(), color_subtle_background_pressed: "#2e2e2e".into(),