Skip to main content

guise/data/
avatar.rs

1//! `Avatar` — a circular initials/placeholder badge.
2
3use 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/// A user avatar showing initials. The Mantine `Avatar` (image variants aside).
10#[derive(IntoElement)]
11pub struct Avatar {
12    initials: SharedString,
13    color: ColorName,
14    variant: Variant,
15    size: Size,
16    /// `None` renders a full circle; `Some` sets a square corner radius.
17    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
53/// Avatar diameter (px) across the size scale. Shared with `AvatarGroup`.
54pub(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, // full circle
72        };
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}