1use gpui::prelude::*;
4use gpui::{div, px, App, FontWeight, IntoElement, SharedString, Window};
5
6use crate::style::{surface, Variant};
7use crate::theme::{theme, ColorName, Size};
8
9#[derive(IntoElement)]
11pub struct Avatar {
12 initials: SharedString,
13 color: ColorName,
14 variant: Variant,
15 size: Size,
16 radius: Option<Size>,
18}
19
20impl Avatar {
21 pub fn new(initials: impl Into<SharedString>) -> Self {
22 Avatar {
23 initials: initials.into(),
24 color: ColorName::Gray,
25 variant: Variant::Light,
26 size: Size::Md,
27 radius: None,
28 }
29 }
30
31 pub fn color(mut self, color: ColorName) -> Self {
32 self.color = color;
33 self
34 }
35
36 pub fn variant(mut self, variant: Variant) -> Self {
37 self.variant = variant;
38 self
39 }
40
41 pub fn size(mut self, size: Size) -> Self {
42 self.size = size;
43 self
44 }
45
46 pub fn radius(mut self, radius: Size) -> Self {
47 self.radius = Some(radius);
48 self
49 }
50
51}
52
53pub(crate) fn avatar_size(size: Size) -> f32 {
55 match size {
56 Size::Xs => 16.0,
57 Size::Sm => 26.0,
58 Size::Md => 38.0,
59 Size::Lg => 56.0,
60 Size::Xl => 84.0,
61 }
62}
63
64impl RenderOnce for Avatar {
65 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
66 let t = theme(cx);
67 let s = surface(t, self.color, self.variant);
68 let dim = avatar_size(self.size);
69 let radius = match self.radius {
70 Some(r) => t.radius(r),
71 None => dim, };
73
74 let mut el = div()
75 .w(px(dim))
76 .h(px(dim))
77 .flex()
78 .items_center()
79 .justify_center()
80 .rounded(px(radius))
81 .bg(s.bg)
82 .text_color(s.fg)
83 .text_size(px(dim * 0.4))
84 .font_weight(FontWeight::SEMIBOLD)
85 .child(self.initials);
86 if let Some(border) = s.border {
87 el = el.border_1().border_color(border);
88 }
89 el
90 }
91}