Skip to main content

ui/components/
aspect_ratio.rs

1use gpui::AnyElement;
2
3use crate::prelude::*;
4
5/// A layout wrapper that preserves a fixed width-to-height ratio.
6#[derive(IntoElement, RegisterComponent)]
7pub struct AspectRatio {
8    ratio: f32,
9    child: AnyElement,
10}
11
12impl AspectRatio {
13    /// Creates a wrapper with the given aspect ratio (width / height).
14    ///
15    /// For example, `16.0 / 9.0` for widescreen media.
16    pub fn new(ratio: f32, child: impl IntoElement) -> Self {
17        Self {
18            ratio,
19            child: child.into_any_element(),
20        }
21    }
22
23    pub fn ratio(mut self, ratio: f32) -> Self {
24        self.ratio = ratio;
25        self
26    }
27}
28
29impl RenderOnce for AspectRatio {
30    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
31        div()
32            .id("aspect-ratio")
33            .w_full()
34            .aspect_ratio(self.ratio)
35            .overflow_hidden()
36            .child(self.child)
37    }
38}
39
40impl Component for AspectRatio {
41    fn scope() -> ComponentScope {
42        ComponentScope::Layout
43    }
44
45    fn description() -> Option<&'static str> {
46        Some("A layout wrapper that preserves a fixed width-to-height ratio.")
47    }
48
49    fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
50        Some(
51            v_flex()
52                .gap_4()
53                .w(px(320.))
54                .child(
55                    AspectRatio::new(
56                        16.0 / 9.0,
57                        div()
58                            .w_full()
59                            .h_full()
60                            .bg(semantic::muted_bg(cx))
61                            .flex()
62                            .items_center()
63                            .justify_center()
64                            .child(Label::new("16:9").color(Color::Muted)),
65                    )
66                    .into_any_element(),
67                )
68                .child(
69                    AspectRatio::new(
70                        1.0,
71                        div()
72                            .w_full()
73                            .h_full()
74                            .bg(semantic::secondary_bg(cx))
75                            .flex()
76                            .items_center()
77                            .justify_center()
78                            .child(Label::new("1:1").color(Color::Muted)),
79                    )
80                    .into_any_element(),
81                )
82                .into_any_element(),
83        )
84    }
85}