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.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