diff --git a/demo_markdown/docs/avatar/mod.md b/demo_markdown/docs/avatar/mod.md index 117633c..4ad2e7e 100644 --- a/demo_markdown/docs/avatar/mod.md +++ b/demo_markdown/docs/avatar/mod.md @@ -1,11 +1,54 @@ # Avatar +```rust demo +view! { + +} +``` + +### Name + +```rust demo +view! { + +} +``` + +### Image + +```rust demo +view! { + +} +``` + +### Shape + +```rust demo +view! { + +} +``` + +### Size + ```rust demo view! { - - - + + + + + + + + + + + + + + } ``` diff --git a/thaw/src/avatar/avatar.css b/thaw/src/avatar/avatar.css index 68f131d..d10fb3d 100644 --- a/thaw/src/avatar/avatar.css +++ b/thaw/src/avatar/avatar.css @@ -1,13 +1,55 @@ .thaw-avatar { display: inline-block; - width: var(--thaw-size); - height: var(--thaw-size); - background-color: var(--thaw-background-color); - border-radius: var(--thaw-border-radius); + flex-shrink: 0; + position: relative; + vertical-align: middle; + border-radius: var(--borderRadiusCircular); + font-family: var(--fontFamilyBase); + font-weight: var(--fontWeightSemibold); + font-size: var(--fontSizeBase300); + width: 32px; + height: 32px; } -.thaw-avatar img { +.thaw-avatar--square { + border-radius: var(--borderRadiusMedium); +} + +.thaw-avatar__icon, +.thaw-avatar__initials { + position: absolute; + box-sizing: border-box; + top: 0px; + left: 0px; width: 100%; height: 100%; - border-radius: var(--thaw-border-radius); + line-height: 1; + border: var(--strokeWidthThin) solid var(--colorTransparentStroke); + display: flex; + align-items: center; + justify-content: center; + text-align: center; + user-select: none; + border-radius: inherit; + + background-color: var(--colorNeutralBackground6); + color: var(--colorNeutralForeground3); +} + +.thaw-avatar__icon { + font-size: 20px; +} + +.thaw-avatar__image { + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + border-radius: inherit; + object-fit: cover; + vertical-align: top; + + background-color: var(--colorNeutralBackground6); + color: var(--colorNeutralForeground3); } diff --git a/thaw/src/avatar/mod.rs b/thaw/src/avatar/mod.rs index 1ea5270..ccb33ca 100644 --- a/thaw/src/avatar/mod.rs +++ b/thaw/src/avatar/mod.rs @@ -1,45 +1,107 @@ -mod theme; - -pub use theme::AvatarTheme; - -use crate::{use_theme, Theme}; use leptos::*; use thaw_components::OptionComp; -use thaw_utils::{class_list, mount_style, OptionalProp}; +use thaw_utils::{class_list, mount_style, OptionalProp, StoredMaybeSignal}; #[component] pub fn Avatar( - #[prop(optional, into)] src: Option>, - #[prop(optional, into)] round: MaybeSignal, - #[prop(default = MaybeSignal::Static(30), into)] size: MaybeSignal, + /// The Avatar's image. + #[prop(optional, into)] + src: Option>, + /// The name of the person or entity represented by this Avatar. + #[prop(optional, into)] + name: Option>, + /// Custom initials. + #[prop(optional, into)] + initials: Option>, + /// The avatar can have a circular or square shape. + #[prop(optional, into)] + shape: MaybeSignal, + /// Size of the avatar in pixels. + #[prop(optional, into)] size: Option>, #[prop(optional, into)] class: OptionalProp>, ) -> impl IntoView { - let theme = use_theme(Theme::light); - let css_vars = create_memo(move |_| { - let mut css_vars = String::new(); - css_vars.push_str(&format!("--thaw-size: {}px;", size.get())); - css_vars.push_str(&format!( - "--thaw-border-radius: {};", - if round.get() { "50%" } else { "3px" } - )); - theme.with(|theme| { - css_vars.push_str(&format!( - "--thaw-background-color: {}", - theme.avatar.background_color - )); - }); - css_vars - }); mount_style("avatar", include_str!("./avatar.css")); + let style = move || { + let size = size?.get(); + + let mut style = format!("width: {0}px; height: {0}px;", size); + + if let Some(font_size) = match size { + 0..=24 => Some(100), + 25..=28 => Some(200), + 29..=40 => None, + 41..=56 => Some(400), + 57..=96 => Some(500), + 97..=128 => Some(600), + _ => Some(600), + } { + style.push_str(&format!("font-size: var(--fontSizeBase{});", font_size)) + } + + Some(style) + }; + + let is_show_default_icon = src.is_none() && initials.is_none() && name.is_none(); + let name: Option> = name.map(|n| n.into()); + view! { + { + move || { + if let Some(initials) = initials.as_ref().map_or_else(|| name.as_ref().map(|n| initials_name(n.get())), |i| Some(i.get())) { + view! { + + {initials} + + }.into() + } else { + None + } + } + } - + + { + if is_show_default_icon { + view! { + + }.into() + } else { + None + } + } } } + +// TODO +fn initials_name(name: String) -> String { + name.split_at(2).0.to_string().to_ascii_uppercase() +} + +#[derive(Default, Clone)] +pub enum AvatarShape { + #[default] + Circular, + Square, +} + +impl AvatarShape { + pub fn as_str(&self) -> &'static str { + match self { + Self::Circular => "circular", + Self::Square => "square", + } + } +} diff --git a/thaw/src/avatar/theme.rs b/thaw/src/avatar/theme.rs deleted file mode 100644 index a335f79..0000000 --- a/thaw/src/avatar/theme.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::theme::ThemeMethod; - -#[derive(Clone)] -pub struct AvatarTheme { - pub background_color: String, -} - -impl ThemeMethod for AvatarTheme { - fn light() -> Self { - Self { - background_color: "#f7f7f7".into(), - } - } - - fn dark() -> Self { - Self { - background_color: "#424245".into(), - } - } -} diff --git a/thaw/src/theme/color.rs b/thaw/src/theme/color.rs index c7ba47c..fa259d9 100644 --- a/thaw/src/theme/color.rs +++ b/thaw/src/theme/color.rs @@ -6,6 +6,7 @@ pub struct ColorTheme { pub color_neutral_background_1: String, pub color_neutral_background_1_hover: String, pub color_neutral_background_1_pressed: String, + pub color_neutral_background_6: String, pub color_neutral_foreground_disabled: String, pub color_neutral_foreground_1: String, @@ -16,6 +17,7 @@ pub struct ColorTheme { pub color_neutral_foreground_2_pressed: String, pub color_neutral_foreground_2_brand_hover: String, pub color_neutral_foreground_2_brand_pressed: String, + pub color_neutral_foreground_3: String, pub color_neutral_foreground_4: String, pub color_neutral_foreground_on_brand: String, @@ -47,6 +49,8 @@ impl ColorTheme { color_neutral_background_1: "#fff".into(), color_neutral_background_1_hover: "#f5f5f5".into(), color_neutral_background_1_pressed: "#e0e0e0".into(), + color_neutral_background_6: "#e6e6e6".into(), + color_neutral_foreground_disabled: "#bdbdbd".into(), color_neutral_foreground_1: "#242424".into(), color_neutral_foreground_1_hover: "#242424".into(), @@ -56,6 +60,7 @@ impl ColorTheme { color_neutral_foreground_2_pressed: "#242424".into(), color_neutral_foreground_2_brand_hover: "#0f6cbd".into(), color_neutral_foreground_2_brand_pressed: "#115ea3".into(), + color_neutral_foreground_3: "#616161".into(), color_neutral_foreground_4: "#707070".into(), color_neutral_foreground_on_brand: "#fff".into(), @@ -87,6 +92,8 @@ impl ColorTheme { color_neutral_background_1: "#292929".into(), color_neutral_background_1_hover: "#3d3d3d".into(), color_neutral_background_1_pressed: "#1f1f1f".into(), + color_neutral_background_6: "#333333".into(), + color_neutral_foreground_disabled: "#5c5c5c".into(), color_neutral_foreground_1: "#fff".into(), color_neutral_foreground_1_hover: "#fff".into(), @@ -96,6 +103,7 @@ impl ColorTheme { color_neutral_foreground_2_pressed: "#fff".into(), color_neutral_foreground_2_brand_hover: "#479ef5".into(), color_neutral_foreground_2_brand_pressed: "#2886de".into(), + color_neutral_foreground_3: "#adadad".into(), color_neutral_foreground_4: "#999999".into(), color_neutral_foreground_on_brand: "#fff".into(), diff --git a/thaw/src/theme/common.rs b/thaw/src/theme/common.rs index 828ead4..a430588 100644 --- a/thaw/src/theme/common.rs +++ b/thaw/src/theme/common.rs @@ -20,9 +20,16 @@ pub struct CommonTheme { pub color_error_hover: String, pub color_error_active: String, + pub font_size_base_100: String, pub font_size_base_200: String, pub font_size_base_300: String, pub font_size_base_400: String, + pub font_size_base_500: String, + pub font_size_base_600: String, + pub font_size_base_700: String, + pub font_size_base_800: String, + pub font_size_base_900: String, + pub font_size_base_1000: String, pub line_height_base_200: String, pub line_height_base_300: String, @@ -37,7 +44,7 @@ pub struct CommonTheme { pub border_radius_none: String, pub border_radius_medium: String, pub border_radius_circular: String, - + pub spacing_horizontal_x_x_s: String, pub spacing_horizontal_s_nudge: String, pub spacing_horizontal_s: String, @@ -81,9 +88,16 @@ impl CommonTheme { color_error_hover: "".into(), color_error_active: "".into(), + font_size_base_100: "10px".into(), font_size_base_200: "12px".into(), font_size_base_300: "14px".into(), font_size_base_400: "16px".into(), + font_size_base_500: "20px".into(), + font_size_base_600: "24px".into(), + font_size_base_700: "28px".into(), + font_size_base_800: "32px".into(), + font_size_base_900: "40px".into(), + font_size_base_1000: "60px".into(), line_height_base_200: "16px".into(), line_height_base_300: "20px".into(), diff --git a/thaw/src/theme/mod.rs b/thaw/src/theme/mod.rs index e270590..ff9943f 100644 --- a/thaw/src/theme/mod.rs +++ b/thaw/src/theme/mod.rs @@ -4,7 +4,7 @@ mod common; use self::common::CommonTheme; use crate::{ mobile::{NavBarTheme, TabbarTheme}, - AlertTheme, AnchorTheme, AutoCompleteTheme, AvatarTheme, BackTopTheme, BreadcrumbTheme, + AlertTheme, AnchorTheme, AutoCompleteTheme, BackTopTheme, BreadcrumbTheme, CalendarTheme, CollapseTheme, ColorPickerTheme, DatePickerTheme, InputTheme, MenuTheme, MessageTheme, PopoverTheme, ProgressTheme, ScrollbarTheme, SelectTheme, SkeletionTheme, SliderTheme, SpinnerTheme, SwitchTheme, TableTheme, TagTheme, TimePickerTheme, TypographyTheme, @@ -29,7 +29,6 @@ pub struct Theme { pub alert: AlertTheme, pub skeletion: SkeletionTheme, pub tag: TagTheme, - pub avatar: AvatarTheme, pub message: MessageTheme, pub select: SelectTheme, pub slider: SliderTheme, @@ -65,7 +64,6 @@ impl Theme { alert: AlertTheme::light(), skeletion: SkeletionTheme::light(), tag: TagTheme::light(), - avatar: AvatarTheme::light(), message: MessageTheme::light(), select: SelectTheme::light(), slider: SliderTheme::light(), @@ -100,7 +98,6 @@ impl Theme { alert: AlertTheme::dark(), skeletion: SkeletionTheme::dark(), tag: TagTheme::dark(), - avatar: AvatarTheme::dark(), message: MessageTheme::dark(), select: SelectTheme::dark(), slider: SliderTheme::dark(),