Skip to main content

impulse_thaw/persona/
mod.rs

1mod types;
2
3pub use types::*;
4
5use crate::Avatar;
6use leptos::{either::Either, prelude::*};
7use thaw_components::{If, Then};
8use thaw_utils::{class_list, mount_style};
9
10#[component]
11pub fn Persona(
12    #[prop(optional, into)] class: MaybeProp<String>,
13    #[prop(optional, into)] style: MaybeProp<String>,
14    /// The name of the person or entity represented by the Persona.
15    /// When primary_text is not provided, this will be used as the default value for primaryText.
16    #[prop(optional, into)]
17    name: MaybeProp<String>,
18    /// The size of a Persona and its text.
19    #[prop(optional, into)]
20    size: Signal<PersonaSize>,
21    /// The vertical alignment of the text relative to the avatar.
22    #[prop(optional, into)]
23    text_alignment: Signal<PersonaTextAlignment>,
24    /// The position of the text relative to the avatar.
25    #[prop(optional, into)]
26    text_position: Signal<PersonaTextPosition>,
27    #[prop(optional, into)] avatar_src: MaybeProp<String>,
28    /// The first line of text in the Persona, larger than the rest of the lines.
29    #[prop(optional)]
30    persona_primary_text: Option<PersonaPrimaryText>,
31    /// The second line of text in the Persona.
32    #[prop(optional)]
33    persona_secondary_text: Option<PersonaSecondaryText>,
34    /// The third line of text in the Persona.
35    #[prop(optional)]
36    persona_tertiary_text: Option<PersonaTertiaryText>,
37    /// The fourth line of text in the Persona.
38    #[prop(optional)]
39    persona_quaternary_text: Option<PersonaQuaternaryText>,
40) -> impl IntoView {
41    mount_style("persona", include_str!("./persona.css"));
42
43    let text_position_before =
44        Memo::new(move |_| text_position.get() == PersonaTextPosition::Before);
45
46    let style = move || {
47        let css_var = match size.get() {
48            PersonaSize::ExtraSmall => "spacingHorizontalSNudge",
49            PersonaSize::Small => "spacingHorizontalS",
50            PersonaSize::Medium => "spacingHorizontalS",
51            PersonaSize::Large => "spacingHorizontalMNudge",
52            PersonaSize::ExtraLarge => "spacingHorizontalMNudge",
53            PersonaSize::Huge => "spacingHorizontalM",
54        };
55
56        let mut s = format!("--thaw-persona__avatar-spacing: var(--{css_var});");
57
58        style.with(|style| {
59            if let Some(style) = style.as_ref() {
60                s.push_str(style);
61            }
62        });
63
64        s
65    };
66
67    let avatar_size = Memo::new(move |_| size.get().as_avatar_size());
68
69    view! {
70        <div
71            class=class_list![
72                "thaw-persona",
73                move || format!("thaw-persona--{}", text_alignment.get().as_str()),
74                move || format!("thaw-persona--{}", text_position.get().as_str()),
75                move || format!("thaw-persona--{}", size.get().as_str()),
76                class
77            ]
78            style=style
79        >
80            <If cond=Signal::derive(move || !text_position_before.get())>
81                <Then slot>
82                    <Avatar
83                        class="thaw-persona__avatar"
84                        name=name
85                        src=avatar_src
86                        size=avatar_size
87                    />
88                </Then>
89            </If>
90            {if let Some(text) = persona_primary_text {
91                Either::Left(
92                    view! { <span class="thaw-persona__primary-text">{(text.children)()}</span> },
93                )
94            } else {
95                Either::Right(move || {
96                    if let Some(name) = name.get() {
97                        Either::Left(
98                            view! { <span class="thaw-persona__primary-text">{name}</span> },
99                        )
100                    } else {
101                        Either::Right(())
102                    }
103                })
104            }}
105            {if let Some(text) = persona_secondary_text {
106                Either::Left(
107                    view! { <span class="thaw-persona__secondary-text">{(text.children)()}</span> },
108                )
109            } else {
110                Either::Right(())
111            }}
112            {if let Some(text) = persona_tertiary_text {
113                Either::Left(
114                    view! { <span class="thaw-persona__tertiary-text">{(text.children)()}</span> },
115                )
116            } else {
117                Either::Right(())
118            }}
119            {if let Some(text) = persona_quaternary_text {
120                Either::Left(
121                    view! { <span class="thaw-persona__quaternary-text">{(text.children)()}</span> },
122                )
123            } else {
124                Either::Right(())
125            }}
126
127            <If cond=text_position_before>
128                <Then slot>
129                    <Avatar
130                        class="thaw-persona__avatar"
131                        name=name
132                        src=avatar_src
133                        size=avatar_size
134                    />
135                </Then>
136            </If>
137        </div>
138    }
139}