gpui_component/avatar/
avatar_group.rs1use gpui::{
2 div, prelude::FluentBuilder as _, Div, InteractiveElement, Interactivity, IntoElement,
3 ParentElement as _, RenderOnce, StyleRefinement, Styled,
4};
5
6use crate::{avatar::Avatar, ActiveTheme, Sizable, Size, StyledExt as _};
7
8#[derive(IntoElement)]
10pub struct AvatarGroup {
11 base: Div,
12 style: StyleRefinement,
13 avatars: Vec<Avatar>,
14 size: Size,
15 limit: usize,
16 ellipsis: bool,
17}
18
19impl AvatarGroup {
20 pub fn new() -> Self {
22 Self {
23 base: div(),
24 style: StyleRefinement::default(),
25 avatars: Vec::new(),
26 size: Size::default(),
27 limit: 3,
28 ellipsis: false,
29 }
30 }
31
32 pub fn child(mut self, avatar: Avatar) -> Self {
34 self.avatars.push(avatar);
35 self
36 }
37
38 pub fn children(mut self, avatars: impl IntoIterator<Item = Avatar>) -> Self {
40 self.avatars.extend(avatars);
41 self
42 }
43
44 pub fn limit(mut self, limit: usize) -> Self {
46 self.limit = limit;
47 self
48 }
49
50 pub fn ellipsis(mut self) -> Self {
52 self.ellipsis = true;
53 self
54 }
55}
56
57impl Sizable for AvatarGroup {
58 fn with_size(mut self, size: impl Into<Size>) -> Self {
59 self.size = size.into();
60 self
61 }
62}
63
64impl Styled for AvatarGroup {
65 fn style(&mut self) -> &mut StyleRefinement {
66 &mut self.style
67 }
68}
69
70impl InteractiveElement for AvatarGroup {
71 fn interactivity(&mut self) -> &mut Interactivity {
72 self.base.interactivity()
73 }
74}
75
76impl RenderOnce for AvatarGroup {
77 fn render(self, _: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
78 let item_ml = -super::avatar_size(self.size) * 0.3;
79 let avatars_len = self.avatars.len();
80
81 self.base
82 .h_flex()
83 .flex_row_reverse()
84 .refine_style(&self.style)
85 .children(if self.ellipsis && avatars_len > self.limit {
86 Some(
87 Avatar::new()
88 .name("⋯")
89 .bg(cx.theme().secondary)
90 .text_color(cx.theme().muted_foreground)
91 .with_size(self.size)
92 .ml_1(),
93 )
94 } else {
95 None
96 })
97 .children(
98 self.avatars
99 .into_iter()
100 .take(self.limit)
101 .enumerate()
102 .rev()
103 .map(|(ix, item)| {
104 item.with_size(self.size)
105 .when(ix > 0, |this| this.ml(item_ml))
106 }),
107 )
108 }
109}