Skip to main content

guise/layout/
stack.rs

1//! `Stack` — children laid out in a column with consistent spacing.
2
3use gpui::prelude::*;
4use gpui::{div, px, AnyElement, App, IntoElement, Window};
5
6use super::{apply_align, apply_justify, Align, Justify};
7use crate::devtools::Probed;
8use crate::theme::{theme, Size};
9
10/// A vertical flex container.
11#[derive(IntoElement)]
12pub struct Stack {
13    children: Vec<AnyElement>,
14    gap: Size,
15    align: Align,
16    justify: Justify,
17}
18
19impl Stack {
20    pub fn new() -> Self {
21        Stack {
22            children: Vec::new(),
23            gap: Size::Md,
24            align: Align::Stretch,
25            justify: Justify::Start,
26        }
27    }
28
29    /// Spacing between children.
30    pub fn gap(mut self, gap: Size) -> Self {
31        self.gap = gap;
32        self
33    }
34
35    /// Cross-axis (horizontal) alignment.
36    pub fn align(mut self, align: Align) -> Self {
37        self.align = align;
38        self
39    }
40
41    /// Main-axis (vertical) distribution.
42    pub fn justify(mut self, justify: Justify) -> Self {
43        self.justify = justify;
44        self
45    }
46}
47
48impl Default for Stack {
49    fn default() -> Self {
50        Stack::new()
51    }
52}
53
54impl ParentElement for Stack {
55    fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
56        self.children.extend(elements);
57    }
58}
59
60impl RenderOnce for Stack {
61    fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
62        let gap = theme(cx).spacing(self.gap);
63        let base = div().flex().flex_col().gap(px(gap));
64        apply_justify(apply_align(base, self.align), self.justify)
65            .children(self.children)
66            .probe("Stack")
67    }
68}