kitchen_ui/widgets/
section.rs1use gpui_kit::component::{h_flex, v_flex};
4use gpui_kit::prelude::FluentBuilder as _;
5use gpui_kit::{AnyElement, App, FontWeight, IntoElement, ParentElement, RenderOnce, SharedString, Styled as _, Window, div, px};
6
7use crate::theme::{self, color};
8
9#[derive(IntoElement)]
13pub struct Section {
14 title: SharedString,
15 extra: Option<AnyElement>,
16 boxed: bool,
17 children: Vec<AnyElement>,
18}
19
20impl Section {
21 pub fn new(title: impl Into<SharedString>) -> Self {
24 Self { title: title.into(), extra: None, boxed: false, children: Vec::new() }
25 }
26
27 pub fn extra(mut self, e: impl IntoElement) -> Self {
29 self.extra = Some(e.into_any_element());
30 self
31 }
32
33 pub fn boxed(mut self) -> Self {
36 self.boxed = true;
37 self
38 }
39}
40
41impl ParentElement for Section {
42 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
43 self.children.extend(elements);
44 }
45}
46
47impl RenderOnce for Section {
48 fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
49 let Self { title, extra, boxed, children } = self;
50 let head = h_flex()
51 .w_full()
52 .min_h(px(20.))
53 .gap(px(theme::SM))
54 .child(div().flex_1().min_w_0().truncate().text_xs().font_weight(FontWeight::SEMIBOLD).text_color(color::text_muted()).child(title.to_uppercase()))
55 .children(extra);
56 let body = v_flex().w_full().min_w_0().gap(px(theme::SM)).children(children).when(boxed, |d| {
57 d.p(px(theme::MD)).rounded(px(theme::RADIUS_LG)).border_1().border_color(color::border()).bg(color::raised())
58 });
59 v_flex().w_full().min_w_0().gap(px(theme::SM)).child(head).child(body)
60 }
61}