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 {
21 Self {
22 base: div(),
23 style: StyleRefinement::default(),
24 avatars: Vec::new(),
25 size: Size::default(),
26 limit: 3,
27 ellipsis: false,
28 }
29 }
30
31 pub fn child(mut self, avatar: Avatar) -> Self {
33 self.avatars.push(avatar);
34 self
35 }
36
37 pub fn children(mut self, avatars: impl IntoIterator<Item = Avatar>) -> Self {
39 self.avatars.extend(avatars);
40 self
41 }
42
43 pub fn limit(mut self, limit: usize) -> Self {
45 self.limit = limit;
46 self
47 }
48
49 pub fn ellipsis(mut self) -> Self {
51 self.ellipsis = true;
52 self
53 }
54}
55
56impl Sizable for AvatarGroup {
57 fn with_size(mut self, size: impl Into<Size>) -> Self {
58 self.size = size.into();
59 self
60 }
61}
62
63impl Styled for AvatarGroup {
64 fn style(&mut self) -> &mut StyleRefinement {
65 &mut self.style
66 }
67}
68
69impl InteractiveElement for AvatarGroup {
70 fn interactivity(&mut self) -> &mut Interactivity {
71 self.base.interactivity()
72 }
73}
74
75impl RenderOnce for AvatarGroup {
76 fn render(self, _: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
77 let item_ml = -super::avatar_size(self.size) * 0.3;
78 let avatars_len = self.avatars.len();
79
80 self.base
81 .h_flex()
82 .flex_row_reverse()
83 .refine_style(&self.style)
84 .children(if self.ellipsis && avatars_len > self.limit {
85 Some(
86 Avatar::new()
87 .name("⋯")
88 .bg(cx.theme().secondary)
89 .text_color(cx.theme().muted_foreground)
90 .with_size(self.size)
91 .ml_1(),
92 )
93 } else {
94 None
95 })
96 .children(
97 self.avatars
98 .into_iter()
99 .take(self.limit)
100 .enumerate()
101 .rev()
102 .map(|(ix, item)| {
103 item.with_size(self.size)
104 .when(ix > 0, |this| this.ml(item_ml))
105 }),
106 )
107 }
108}