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}