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/// Avatar diameter (px) across the size scale. Shared with `AvatarGroup`.
53pub(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, // full circle
71        };
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}