storybook/stories/
grids.rs

1use gpui::{div, prelude::*, px, rgb, Hsla};
2use allui::prelude::*;
3
4pub fn render_grid_story() -> impl IntoElement {
5    VStack::new()
6        .spacing(16.0)
7        .alignment(HorizontalAlignment::Leading)
8        .child(Text::new("Grid - Static 2D table layout:"))
9        .child(
10            VStack::new()
11                .spacing(16.0)
12                .child(Text::new("Data table with GridRow:").foreground_color(Color::gray()))
13                .child(
14                    Grid::new()
15                        .horizontal_spacing(16.0)
16                        .vertical_spacing(8.0)
17                        .child(
18                            GridRow::new()
19                                .child(
20                                    Text::new("Name")
21                                        .bold()
22                                        .foreground_color(Color::secondary_label()),
23                                )
24                                .child(
25                                    Text::new("Type")
26                                        .bold()
27                                        .foreground_color(Color::secondary_label()),
28                                )
29                                .child(
30                                    Text::new("Size")
31                                        .bold()
32                                        .foreground_color(Color::secondary_label()),
33                                ),
34                        )
35                        .child(
36                            GridRow::new()
37                                .child(Text::new("main.rs"))
38                                .child(Text::new("Rust"))
39                                .child(Text::new("4.2 KB")),
40                        )
41                        .child(
42                            GridRow::new()
43                                .child(Text::new("Cargo.toml"))
44                                .child(Text::new("TOML"))
45                                .child(Text::new("1.1 KB")),
46                        )
47                        .child(
48                            GridRow::new()
49                                .child(Text::new("README.md"))
50                                .child(Text::new("Markdown"))
51                                .child(Text::new("8.7 KB")),
52                        )
53                        .child(
54                            GridRow::new()
55                                .child(Text::new("lib.rs"))
56                                .child(Text::new("Rust"))
57                                .child(Text::new("2.3 KB")),
58                        )
59                        .padding(16.0)
60                        .background(Color::tertiary_system_background())
61                        .corner_radius(8.0),
62                )
63                .child(
64                    Text::new("Columns auto-size based on content width.")
65                        .foreground_color(Color::gray()),
66                ),
67        )
68}
69
70pub fn render_lazy_vgrid_story() -> impl IntoElement {
71    VStack::new()
72        .spacing(16.0)
73        .alignment(HorizontalAlignment::Leading)
74        .child(Text::new(
75            "LazyVGrid - Vertically-scrolling grid with fixed columns:",
76        ))
77        .child(
78            VStack::new()
79                .spacing(8.0)
80                .child(
81                    Text::new("Photo gallery mockup (3 columns):").foreground_color(Color::gray()),
82                )
83                .child(
84                    ScrollView::new("vgrid-demo")
85                        .axes(ScrollAxes::vertical())
86                        .child(VStack::new().spacing(8.0).children((0..6).map(|row| {
87                            HStack::new().spacing(8.0).children((0..3).map(move |col| {
88                                let index = row * 3 + col;
89                                let colors = [0x007AFF, 0x34C759, 0xFF9500, 0xFF3B30, 0xAF52DE];
90                                let color = colors[index % colors.len()];
91                                VStack::new()
92                                    .child(
93                                        div().size(px(80.0)).bg(rgb(color as u32)).rounded(px(8.0)),
94                                    )
95                                    .child(
96                                        Text::new(format!("Photo {}", index + 1))
97                                            .font(Font::caption())
98                                            .foreground_color(Color::gray()),
99                                    )
100                                    .spacing(4.0)
101                            }))
102                        })))
103                        .frame(Frame::size(320.0, 300.0))
104                        .background(Color::tertiary_system_background())
105                        .corner_radius(8.0),
106                )
107                .child(
108                    Text::new("Items flow left-to-right, top-to-bottom. Scroll vertically.")
109                        .foreground_color(Color::gray()),
110                )
111                .child(
112                    VStack::new()
113                        .spacing(4.0)
114                        .child(Text::new("Usage:").bold())
115                        .child(
116                            Text::new(
117                                "LazyVGrid::new(cx.entity().clone(), \"id\", &scroll_handle)",
118                            )
119                            .font(Font::caption())
120                            .foreground_color(Color::tertiary_label()),
121                        )
122                        .child(
123                            Text::new("    .columns(vec![GridItem::flexible(); 3])")
124                                .font(Font::caption())
125                                .foreground_color(Color::tertiary_label()),
126                        )
127                        .child(
128                            Text::new("    .spacing(8.0).item_count(50)")
129                                .font(Font::caption())
130                                .foreground_color(Color::tertiary_label()),
131                        )
132                        .child(
133                            Text::new("    .render_item(|view, idx, _, _| { ... })")
134                                .font(Font::caption())
135                                .foreground_color(Color::tertiary_label()),
136                        )
137                        .child(
138                            Text::new("    .build(window, cx)")
139                                .font(Font::caption())
140                                .foreground_color(Color::tertiary_label()),
141                        )
142                        .padding(12.0)
143                        .background(Color::secondary_system_background())
144                        .corner_radius(8.0),
145                ),
146        )
147}
148
149pub fn render_lazy_hgrid_story() -> impl IntoElement {
150    VStack::new()
151        .spacing(16.0)
152        .alignment(HorizontalAlignment::Leading)
153        .child(Text::new(
154            "LazyHGrid - Horizontally-scrolling grid with fixed rows:",
155        ))
156        .child(
157            VStack::new()
158                .spacing(8.0)
159                .child(
160                    Text::new("Category carousel mockup (2 rows):").foreground_color(Color::gray()),
161                )
162                .child(
163                    ScrollView::new("hgrid-demo")
164                        .axes(ScrollAxes::horizontal())
165                        .child(HStack::new().spacing(12.0).children((0..8).map(|col| {
166                            VStack::new().spacing(12.0).children((0..2).map(move |row| {
167                                let index = col * 2 + row;
168                                let colors =
169                                    [0x007AFF, 0x34C759, 0xFF9500, 0xFF3B30, 0xAF52DE, 0x5856D6];
170                                let color = colors[index % colors.len()];
171                                let categories =
172                                    ["Music", "Movies", "Books", "Games", "Apps", "Podcasts"];
173                                VStack::new()
174                                    .child(
175                                        div()
176                                            .w(px(70.0))
177                                            .h(px(50.0))
178                                            .bg(rgb(color as u32))
179                                            .rounded(px(8.0)),
180                                    )
181                                    .child(
182                                        Text::new(categories[index % categories.len()])
183                                            .font(Font::caption())
184                                            .foreground_color(Color::gray()),
185                                    )
186                                    .spacing(4.0)
187                            }))
188                        })))
189                        .frame(Frame::size(400.0, 200.0))
190                        .background(Color::tertiary_system_background())
191                        .corner_radius(8.0),
192                )
193                .child(
194                    Text::new("Items flow top-to-bottom, left-to-right. Scroll horizontally.")
195                        .foreground_color(Color::gray()),
196                )
197                .child(
198                    VStack::new()
199                        .spacing(4.0)
200                        .child(Text::new("Usage:").bold())
201                        .child(
202                            Text::new(
203                                "LazyHGrid::new(cx.entity().clone(), \"id\", &scroll_handle)",
204                            )
205                            .font(Font::caption())
206                            .foreground_color(Color::tertiary_label()),
207                        )
208                        .child(
209                            Text::new("    .rows(vec![GridItem::fixed(90.0); 2])")
210                                .font(Font::caption())
211                                .foreground_color(Color::tertiary_label()),
212                        )
213                        .child(
214                            Text::new("    .spacing(12.0).item_count(30)")
215                                .font(Font::caption())
216                                .foreground_color(Color::tertiary_label()),
217                        )
218                        .child(
219                            Text::new("    .render_item(|view, idx, _, _| { ... })")
220                                .font(Font::caption())
221                                .foreground_color(Color::tertiary_label()),
222                        )
223                        .child(
224                            Text::new("    .build(window, cx)")
225                                .font(Font::caption())
226                                .foreground_color(Color::tertiary_label()),
227                        )
228                        .padding(12.0)
229                        .background(Color::secondary_system_background())
230                        .corner_radius(8.0),
231                ),
232        )
233}
234
235pub fn render_both_axes_scroll_story(secondary_bg: Hsla) -> impl IntoElement {
236    VStack::new()
237        .spacing(16.0)
238        .alignment(HorizontalAlignment::Leading)
239        .child(Text::new("ScrollView with both axes - Pannable 2D grid:"))
240        .child(
241            VStack::new()
242                .spacing(8.0)
243                .child(
244                    Text::new("20x20 coordinate grid (scroll/pan in any direction):")
245                        .foreground_color(Color::gray()),
246                )
247                .child(
248                    div()
249                        .id("both-axes-scroll")
250                        .overflow_scroll()
251                        .w(px(400.0))
252                        .h(px(300.0))
253                        .bg(secondary_bg)
254                        .rounded(px(8.0))
255                        .child(
256                            div()
257                                .w(px(956.0))
258                                .h(px(956.0))
259                                .flex()
260                                .flex_col()
261                                .gap(px(4.0))
262                                .children((0..20).map(|row| {
263                                    div().flex().flex_row().gap(px(4.0)).children((0..20).map(
264                                        move |col| {
265                                            let is_origin = row == 0 && col == 0;
266                                            let is_edge = row == 0 || col == 0;
267                                            div()
268                                                .size(px(44.0))
269                                                .flex()
270                                                .items_center()
271                                                .justify_center()
272                                                .rounded(px(4.0))
273                                                .bg(rgb(if is_origin {
274                                                    0xFF3B30
275                                                } else if is_edge {
276                                                    0x555555
277                                                } else {
278                                                    0x333333
279                                                }))
280                                                .text_color(rgb(if is_edge {
281                                                    0xFFFFFF
282                                                } else {
283                                                    0x888888
284                                                }))
285                                                .text_xs()
286                                                .child(format!("{},{}", col, row))
287                                        },
288                                    ))
289                                })),
290                        ),
291                )
292                .child(
293                    Text::new("Red = origin (0,0). Gray headers show row/column indices.")
294                        .foreground_color(Color::gray()),
295                ),
296        )
297}