facepile.rs

  1use crate::prelude::*;
  2use gpui::{AnyElement, StyleRefinement};
  3use smallvec::SmallVec;
  4
  5/// A facepile is a collection of faces stacked horizontally–
  6/// always with the leftmost face on top and descending in z-index
  7///
  8/// Facepiles are used to display a group of people or things,
  9/// such as a list of participants in a collaboration session.
 10#[derive(IntoElement)]
 11pub struct Facepile {
 12    base: Div,
 13    faces: SmallVec<[AnyElement; 2]>,
 14}
 15
 16impl Facepile {
 17    /// Creates a new empty facepile.
 18    pub fn empty() -> Self {
 19        Self::new(SmallVec::new())
 20    }
 21
 22    /// Creates a new facepile with the given faces.
 23    pub fn new(faces: SmallVec<[AnyElement; 2]>) -> Self {
 24        Self { base: div(), faces }
 25    }
 26}
 27
 28impl ParentElement for Facepile {
 29    fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
 30        self.faces.extend(elements);
 31    }
 32}
 33
 34// Style methods.
 35impl Facepile {
 36    fn style(&mut self) -> &mut StyleRefinement {
 37        self.base.style()
 38    }
 39
 40    gpui::padding_style_methods!({
 41        visibility: pub
 42    });
 43}
 44
 45impl RenderOnce for Facepile {
 46    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
 47        // Lay the faces out in reverse so they overlap in the desired order (left to right, front to back)
 48        self.base
 49            .flex()
 50            .flex_row_reverse()
 51            .items_center()
 52            .justify_start()
 53            .children(
 54                self.faces
 55                    .into_iter()
 56                    .enumerate()
 57                    .rev()
 58                    .map(|(ix, player)| div().when(ix > 0, |div| div.ml_neg_1()).child(player)),
 59            )
 60    }
 61}
 62
 63// impl ComponentPreview for Facepile {
 64//     fn description() -> impl Into<Option<&'static str>> {
 65//         "A facepile is a collection of faces stacked horizontally–\
 66//         always with the leftmost face on top and descending in z-index.\
 67//         \n\nFacepiles are used to display a group of people or things,\
 68//         such as a list of participants in a collaboration session."
 69//     }
 70//     fn examples(_window: &mut Window, _: &mut App) -> Vec<ComponentExampleGroup<Self>> {
 71//         let few_faces: [&'static str; 3] = [
 72//             "https://avatars.githubusercontent.com/u/1714999?s=60&v=4",
 73//             "https://avatars.githubusercontent.com/u/67129314?s=60&v=4",
 74//             "https://avatars.githubusercontent.com/u/482957?s=60&v=4",
 75//         ];
 76
 77//         let many_faces: [&'static str; 6] = [
 78//             "https://avatars.githubusercontent.com/u/326587?s=60&v=4",
 79//             "https://avatars.githubusercontent.com/u/2280405?s=60&v=4",
 80//             "https://avatars.githubusercontent.com/u/1789?s=60&v=4",
 81//             "https://avatars.githubusercontent.com/u/67129314?s=60&v=4",
 82//             "https://avatars.githubusercontent.com/u/482957?s=60&v=4",
 83//             "https://avatars.githubusercontent.com/u/1714999?s=60&v=4",
 84//         ];
 85
 86//         vec![example_group_with_title(
 87//             "Examples",
 88//             vec![
 89//                 single_example(
 90//                     "Few Faces",
 91//                     Facepile::new(
 92//                         few_faces
 93//                             .iter()
 94//                             .map(|&url| Avatar::new(url).into_any_element())
 95//                             .collect(),
 96//                     ),
 97//                 ),
 98//                 single_example(
 99//                     "Many Faces",
100//                     Facepile::new(
101//                         many_faces
102//                             .iter()
103//                             .map(|&url| Avatar::new(url).into_any_element())
104//                             .collect(),
105//                     ),
106//                 ),
107//                 single_example(
108//                     "Custom Size",
109//                     Facepile::new(
110//                         few_faces
111//                             .iter()
112//                             .map(|&url| Avatar::new(url).size(px(24.)).into_any_element())
113//                             .collect(),
114//                     ),
115//                 ),
116//             ],
117//         )]
118//     }
119// }