Tailwind classes in OCaml
1open Htmlit
2
3(* Component configuration *)
4type t = {
5 classes: Tailwind.t option;
6 attributes: (string * string) list;
7 id: string option;
8 data: (string * string) list;
9}
10
11(* Helper function to convert Tailwind classes to Htmlit attributes *)
12let classes_attr tailwind_classes =
13 At.class' (Tailwind.to_string tailwind_classes)
14
15(* Create a component with classes and attributes *)
16let make ?classes ?attributes ?id ?data () = {
17 classes;
18 attributes = (match attributes with Some a -> a | None -> []);
19 id;
20 data = (match data with Some d -> d | None -> []);
21}
22
23(* Add classes to a component *)
24let add_classes new_classes comp = {
25 comp with classes = match comp.classes with
26 | Some existing -> Some (Tailwind.Css.tw [existing; new_classes])
27 | None -> Some new_classes
28}
29
30(* Add attributes to a component *)
31let add_attributes new_attrs comp = {
32 comp with attributes = comp.attributes @ new_attrs
33}
34
35(* Convert component to Htmlit attributes *)
36let to_htmlit_atts comp =
37 let class_attrs = match comp.classes with
38 | Some c -> [classes_attr c]
39 | None -> []
40 in
41 let attr_list = List.map (fun (k, v) -> At.v k v) comp.attributes in
42 let id_attrs = match comp.id with
43 | Some i -> [At.id i]
44 | None -> []
45 in
46 let data_attrs = List.map (fun (k, v) -> At.v ("data-" ^ k) v) comp.data in
47 class_attrs @ attr_list @ id_attrs @ data_attrs
48
49(* Apply component to an Htmlit element *)
50let apply _comp element =
51 (* This is a simplified implementation - in reality we'd need to traverse the element *)
52 element
53
54(* Create HTML elements with component styling *)
55let div comp children =
56 let attrs = to_htmlit_atts comp in
57 El.div ~at:attrs children
58
59let span comp children =
60 let attrs = to_htmlit_atts comp in
61 El.span ~at:attrs children
62
63let section comp children =
64 let attrs = to_htmlit_atts comp in
65 El.section ~at:attrs children
66
67let article comp children =
68 let attrs = to_htmlit_atts comp in
69 El.article ~at:attrs children
70
71(* Utility functions for common HTML elements *)
72let p ?classes ?attrs children =
73 let base_attrs = match classes with
74 | Some c -> [classes_attr c]
75 | None -> []
76 in
77 let all_attrs = match attrs with
78 | Some a -> base_attrs @ a
79 | None -> base_attrs
80 in
81 El.p ?at:(if all_attrs = [] then None else Some all_attrs) children
82
83let h1 ?classes ?attrs children =
84 let base_attrs = match classes with
85 | Some c -> [classes_attr c]
86 | None -> []
87 in
88 let all_attrs = match attrs with
89 | Some a -> base_attrs @ a
90 | None -> base_attrs
91 in
92 El.h1 ?at:(if all_attrs = [] then None else Some all_attrs) children
93
94let h2 ?classes ?attrs children =
95 let base_attrs = match classes with
96 | Some c -> [classes_attr c]
97 | None -> []
98 in
99 let all_attrs = match attrs with
100 | Some a -> base_attrs @ a
101 | None -> base_attrs
102 in
103 El.h2 ?at:(if all_attrs = [] then None else Some all_attrs) children
104
105let h3 ?classes ?attrs children =
106 let base_attrs = match classes with
107 | Some c -> [classes_attr c]
108 | None -> []
109 in
110 let all_attrs = match attrs with
111 | Some a -> base_attrs @ a
112 | None -> base_attrs
113 in
114 El.h3 ?at:(if all_attrs = [] then None else Some all_attrs) children
115
116let img ?classes ?attrs ~src ~alt () =
117 let base_attrs = match classes with
118 | Some c -> [classes_attr c]
119 | None -> []
120 in
121 let required_attrs = [At.src src; At.alt alt] in
122 let all_attrs = match attrs with
123 | Some a -> base_attrs @ required_attrs @ a
124 | None -> base_attrs @ required_attrs
125 in
126 El.img ~at:all_attrs ()
127
128let a ?classes ?attrs ~href children =
129 let base_attrs = match classes with
130 | Some c -> [classes_attr c]
131 | None -> []
132 in
133 let required_attrs = [At.href href] in
134 let all_attrs = match attrs with
135 | Some a -> base_attrs @ required_attrs @ a
136 | None -> base_attrs @ required_attrs
137 in
138 El.a ~at:all_attrs children
139
140let ul ?classes ?attrs children =
141 let base_attrs = match classes with
142 | Some c -> [classes_attr c]
143 | None -> []
144 in
145 let all_attrs = match attrs with
146 | Some a -> base_attrs @ a
147 | None -> base_attrs
148 in
149 El.ul ?at:(if all_attrs = [] then None else Some all_attrs) children
150
151let ol ?classes ?attrs children =
152 let base_attrs = match classes with
153 | Some c -> [classes_attr c]
154 | None -> []
155 in
156 let all_attrs = match attrs with
157 | Some a -> base_attrs @ a
158 | None -> base_attrs
159 in
160 El.ol ?at:(if all_attrs = [] then None else Some all_attrs) children
161
162let li ?classes ?attrs children =
163 let base_attrs = match classes with
164 | Some c -> [classes_attr c]
165 | None -> []
166 in
167 let all_attrs = match attrs with
168 | Some a -> base_attrs @ a
169 | None -> base_attrs
170 in
171 El.li ?at:(if all_attrs = [] then None else Some all_attrs) children
172
173let header ?classes ?attrs children =
174 let base_attrs = match classes with
175 | Some c -> [classes_attr c]
176 | None -> []
177 in
178 let all_attrs = match attrs with
179 | Some a -> base_attrs @ a
180 | None -> base_attrs
181 in
182 El.header ?at:(if all_attrs = [] then None else Some all_attrs) children
183
184let footer ?classes ?attrs children =
185 let base_attrs = match classes with
186 | Some c -> [classes_attr c]
187 | None -> []
188 in
189 let all_attrs = match attrs with
190 | Some a -> base_attrs @ a
191 | None -> base_attrs
192 in
193 El.footer ?at:(if all_attrs = [] then None else Some all_attrs) children
194
195let nav ?classes ?attrs children =
196 let base_attrs = match classes with
197 | Some c -> [classes_attr c]
198 | None -> []
199 in
200 let all_attrs = match attrs with
201 | Some a -> base_attrs @ a
202 | None -> base_attrs
203 in
204 El.nav ?at:(if all_attrs = [] then None else Some all_attrs) children
205
206let main ?classes ?attrs children =
207 let base_attrs = match classes with
208 | Some c -> [classes_attr c]
209 | None -> []
210 in
211 let all_attrs = match attrs with
212 | Some a -> base_attrs @ a
213 | None -> base_attrs
214 in
215 El.main ?at:(if all_attrs = [] then None else Some all_attrs) children
216
217(* Simplified div function that matches existing usage *)
218let div_simple ?classes ?attrs children =
219 let base_attrs = match classes with
220 | Some c -> [classes_attr c]
221 | None -> []
222 in
223 let all_attrs = match attrs with
224 | Some a -> base_attrs @ a
225 | None -> base_attrs
226 in
227 El.div ?at:(if all_attrs = [] then None else Some all_attrs) children