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::theme::{theme, Size};
8
9/// A vertical flex container. The Mantine `Stack`.
10#[derive(IntoElement)]
11pub struct Stack {
12    children: Vec<AnyElement>,
13    gap: Size,
14    align: Align,
15    justify: Justify,
16}
17
18impl Stack {
19    pub fn new() -> Self {
20        Stack {
21            children: Vec::new(),
22            gap: Size::Md,
23            align: Align::Stretch,
24            justify: Justify::Start,
25        }
26    }
27
28    /// Spacing between children.
29    pub fn gap(mut self, gap: Size) -> Self {
30        self.gap = gap;
31        self
32    }
33
34    /// Cross-axis (horizontal) alignment.
35    pub fn align(mut self, align: Align) -> Self {
36        self.align = align;
37        self
38    }
39
40    /// Main-axis (vertical) distribution.
41    pub fn justify(mut self, justify: Justify) -> Self {
42        self.justify = justify;
43        self
44    }
45}
46
47impl Default for Stack {
48    fn default() -> Self {
49        Stack::new()
50    }
51}
52
53impl ParentElement for Stack {
54    fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
55        self.children.extend(elements);
56    }
57}
58
59impl RenderOnce for Stack {
60    fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
61        let gap = theme(cx).spacing(self.gap);
62        let base = div().flex().flex_col().gap(px(gap));
63        apply_justify(apply_align(base, self.align), self.justify).children(self.children)
64    }
65}