Coffee journaling on ATProto (alpha)
alpha.arabica.social
coffee
1package components
2
3import "strconv"
4
5// TextInputProps defines properties for text inputs
6type TextInputProps struct {
7 Name string
8 Value string
9 Placeholder string
10 Required bool
11 Class string
12 Type string // "text", "email", "url", etc. Defaults to "text"
13}
14
15// TextInput renders a text input field
16templ TextInput(props TextInputProps) {
17 <input
18 type={ getInputType(props.Type) }
19 name={ props.Name }
20 value={ props.Value }
21 placeholder={ props.Placeholder }
22 class={ "form-input " + props.Class }
23 if props.Required {
24 required
25 }
26 />
27}
28
29// Helper function to get input type, defaults to "text"
30func getInputType(t string) string {
31 if t == "" {
32 return "text"
33 }
34 return t
35}
36
37// NumberInputProps defines properties for number inputs
38type NumberInputProps struct {
39 Name string
40 Value string
41 Placeholder string
42 Required bool
43 Step string
44 Min string
45 Max string
46 Class string
47}
48
49// NumberInput renders a number input field
50templ NumberInput(props NumberInputProps) {
51 <input
52 type="number"
53 name={ props.Name }
54 value={ props.Value }
55 placeholder={ props.Placeholder }
56 class={ "form-input " + props.Class }
57 if props.Required {
58 required
59 }
60 if props.Step != "" {
61 step={ props.Step }
62 }
63 if props.Min != "" {
64 min={ props.Min }
65 }
66 if props.Max != "" {
67 max={ props.Max }
68 }
69 />
70}
71
72// TextAreaProps defines properties for textarea inputs
73type TextAreaProps struct {
74 Name string
75 Value string
76 Placeholder string
77 Required bool
78 Rows int
79 Class string
80}
81
82// TextArea renders a textarea input field
83templ TextArea(props TextAreaProps) {
84 <textarea
85 name={ props.Name }
86 placeholder={ props.Placeholder }
87 class={ "form-textarea " + props.Class }
88 rows={ getRowsAttr(props.Rows) }
89 if props.Required {
90 required
91 }
92 >{ props.Value }</textarea>
93}
94
95// Helper function to get rows attribute
96func getRowsAttr(rows int) string {
97 if rows <= 0 {
98 return "3"
99 }
100 return strconv.Itoa(rows)
101}
102
103// SelectOption represents an option in a select dropdown
104type SelectOption struct {
105 Value string
106 Label string
107 Selected bool
108}
109
110// SelectProps defines properties for select dropdowns
111type SelectProps struct {
112 Name string
113 Options []SelectOption
114 Placeholder string
115 Required bool
116 Class string
117}
118
119// Select renders a select dropdown
120templ Select(props SelectProps) {
121 <select
122 name={ props.Name }
123 class={ "form-select " + props.Class }
124 if props.Required {
125 required
126 }
127 >
128 if props.Placeholder != "" {
129 <option value="">{ props.Placeholder }</option>
130 }
131 for _, opt := range props.Options {
132 <option
133 value={ opt.Value }
134 if opt.Selected {
135 selected
136 }
137 >
138 { opt.Label }
139 </option>
140 }
141 </select>
142}
143
144// FormFieldProps defines properties for a complete form field (label + input + helper)
145type FormFieldProps struct {
146 Label string
147 HelperText string
148 Required bool
149}
150
151// FormField wraps a form input with label and helper text
152templ FormField(props FormFieldProps, input templ.Component) {
153 <div>
154 if props.Label != "" {
155 <label class="form-label">
156 { props.Label }
157 if props.Required {
158 <span class="text-red-600">*</span>
159 }
160 </label>
161 }
162 @input
163 if props.HelperText != "" {
164 <p class="text-helper">{ props.HelperText }</p>
165 }
166 </div>
167}