gpui_kit/controls/
field.rs1use gpui::{Styled, div, prelude::FluentBuilder, px};
7use gpui_kit_theme::{ControlSize, Radius, Space, Theme};
8
9use crate::foundation::StyledExt;
10
11#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
16pub struct FieldState {
17 pub focused: bool,
18 pub invalid: bool,
19 pub disabled: bool,
20}
21
22impl FieldState {
23 pub fn focused(mut self, focused: bool) -> Self {
24 self.focused = focused;
25 self
26 }
27
28 pub fn invalid(mut self, invalid: bool) -> Self {
29 self.invalid = invalid;
30 self
31 }
32
33 pub fn disabled(mut self, disabled: bool) -> Self {
34 self.disabled = disabled;
35 self
36 }
37}
38
39pub fn field_shell(theme: &Theme, size: ControlSize, state: FieldState) -> gpui::Div {
45 let metrics = theme.control.get(size);
46 div()
47 .w_full()
48 .flex()
49 .flex_row()
50 .items_center()
51 .gap(px(theme.space(Space::Sm)))
52 .min_h(px(metrics.height))
53 .px(px(metrics.padding_x))
54 .radius(theme, Radius::Control)
55 .well(theme)
56 .when(state.invalid, |field| {
62 field.border_color(theme.colors.danger)
63 })
64 .when(state.focused, |field| field.shadow(theme.focus_ring()))
65 .when(state.disabled, |field| {
66 field.opacity(theme.opacity.disabled)
67 })
68 .text_size(px(metrics.font_size))
69 .text_color(if state.disabled {
70 theme.colors.text_faint
71 } else {
72 theme.colors.text
73 })
74}