1use gpui::prelude::*;
6use gpui::{div, px, AnyElement, App, IntoElement, SharedString, Window};
7
8use crate::devtools::Probed;
9use crate::theme::{theme, ColorName, Size};
10
11#[derive(IntoElement)]
13pub struct Field {
14 label: Option<SharedString>,
15 description: Option<SharedString>,
16 error: Option<SharedString>,
17 child: Option<AnyElement>,
18}
19
20impl Field {
21 pub fn new() -> Self {
22 Field {
23 label: None,
24 description: None,
25 error: None,
26 child: None,
27 }
28 }
29
30 pub fn label(mut self, label: impl Into<SharedString>) -> Self {
31 self.label = Some(label.into());
32 self
33 }
34
35 pub fn description(mut self, description: impl Into<SharedString>) -> Self {
36 self.description = Some(description.into());
37 self
38 }
39
40 pub fn error(mut self, error: impl Into<SharedString>) -> Self {
41 self.error = Some(error.into());
42 self
43 }
44
45 pub fn child(mut self, child: impl IntoElement) -> Self {
47 self.child = Some(child.into_any_element());
48 self
49 }
50}
51
52impl Default for Field {
53 fn default() -> Self {
54 Field::new()
55 }
56}
57
58impl RenderOnce for Field {
59 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
60 let t = theme(cx);
61 let text = t.text().hsla();
62 let dimmed = t.dimmed().hsla();
63 let error_color = t
64 .color(ColorName::Red, if t.scheme.is_dark() { 5 } else { 7 })
65 .hsla();
66 let font_sm = t.font_size(Size::Sm);
67 let font_xs = t.font_size(Size::Xs);
68
69 let mut column = div().flex().flex_col().gap(px(4.0));
70 if let Some(label) = self.label {
71 column = column.child(div().text_size(px(font_sm)).text_color(text).child(label));
72 }
73 if let Some(child) = self.child {
74 column = column.child(child);
75 }
76 if let Some(error) = self.error {
77 column = column.child(
78 div()
79 .text_size(px(font_xs))
80 .text_color(error_color)
81 .child(error),
82 );
83 } else if let Some(description) = self.description {
84 column = column.child(
85 div()
86 .text_size(px(font_xs))
87 .text_color(dimmed)
88 .child(description),
89 );
90 }
91 column.probe("Field")
92 }
93}