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
52pub(crate) fn avatar_size(size: Size) -> f32 {
54 match size {
55 Size::Xs => 16.0,
56 Size::Sm => 26.0,
57 Size::Md => 38.0,
58 Size::Lg => 56.0,
59 Size::Xl => 84.0,
60 }
61}
62
63impl RenderOnce for Avatar {
64 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
65 let t = theme(cx);
66 let s = surface(t, self.color, self.variant);
67 let dim = avatar_size(self.size);
68 let radius = match self.radius {
69 Some(r) => t.radius(r),
70 None => dim, };
72
73 let mut el = div()
74 .w(px(dim))
75 .h(px(dim))
76 .flex()
77 .items_center()
78 .justify_center()
79 .rounded(px(radius))
80 .bg(s.bg)
81 .text_color(s.fg)
82 .text_size(px(dim * 0.4))
83 .font_weight(FontWeight::SEMIBOLD)
84 .child(self.initials);
85 if let Some(border) = s.border {
86 el = el.border_1().border_color(border);
87 }
88 el
89 }
90}