Skip to main content

ui/components/
media_object.rs

1use gpui::{AnyElement, FontWeight};
2
3use crate::Avatar;
4use crate::prelude::*;
5
6/// A flex row pairing a media element (image/avatar) with a text block —
7/// Tailwind's "Media Object" pattern.
8#[derive(IntoElement, RegisterComponent)]
9pub struct MediaObject {
10    media: AnyElement,
11    heading: SharedString,
12    description: Option<SharedString>,
13}
14
15impl MediaObject {
16    pub fn new(media: impl IntoElement, heading: impl Into<SharedString>) -> Self {
17        Self {
18            media: media.into_any_element(),
19            heading: heading.into(),
20            description: None,
21        }
22    }
23
24    pub fn description(mut self, description: impl Into<SharedString>) -> Self {
25        self.description = Some(description.into());
26        self
27    }
28}
29
30impl RenderOnce for MediaObject {
31    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
32        h_flex().items_start().gap_4().child(self.media).child(
33            v_flex()
34                .gap_1()
35                .child(Label::new(self.heading).weight(FontWeight::MEDIUM))
36                .children(
37                    self.description
38                        .map(|d| Label::new(d).size(LabelSize::Small).color(Color::Muted)),
39                ),
40        )
41    }
42}
43
44impl Component for MediaObject {
45    fn scope() -> ComponentScope {
46        ComponentScope::DataDisplay
47    }
48
49    fn description() -> Option<&'static str> {
50        Some("A flex row pairing a media element (image/avatar) with a text block.")
51    }
52
53    fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
54        let example_avatar = "https://avatars.githubusercontent.com/u/1714999?v=4";
55
56        Some(
57            v_flex()
58                .gap_4()
59                .child(MediaObject::new(
60                    Avatar::new(example_avatar).size(px(48.)),
61                    "Jane Cooper",
62                ))
63                .child(
64                    MediaObject::new(Avatar::new(example_avatar).size(px(48.)), "Cody Fisher")
65                        .description("Regional Paradigm Technician"),
66                )
67                .into_any_element(),
68        )
69    }
70}