Tailwind classes in OCaml
1(* Generate index.html page linking to all examples *) 2 3open Htmlit 4open Tailwind 5 6let classes_attr tailwind_classes = 7 At.class' (Tailwind.to_string tailwind_classes) 8 9let examples = [ 10 ("hello_tailwind_01.html", "01. Hello Tailwind", 11 "Your first Tailwind OCaml program. Learn the basics of creating and using type-safe Tailwind classes.", 12 ["Basic concepts"; "Type safety"; "Class composition"]); 13 14 ("colors_and_typography_02.html", "02. Colors and Typography", 15 "Explore the comprehensive color system and typography utilities with compile-time validation.", 16 ["Color variants"; "Typography scale"; "Font weights"]); 17 18 ("layout_and_spacing_03.html", "03. Layout and Spacing", 19 "Master the box model, flexbox layouts, and spacing utilities for building structured interfaces.", 20 ["Box model"; "Flexbox"; "Spacing system"]); 21 22 ("responsive_design_04.html", "04. Responsive Design", 23 "Learn responsive design patterns with breakpoints and mobile-first utilities.", 24 ["Breakpoints"; "Mobile-first"; "Responsive utilities"]); 25 26 ("effects_and_variants_05.html", "05. Effects and Variants", 27 "Add visual effects and interactive states with shadows, borders, and hover variants.", 28 ["Visual effects"; "Interactive states"; "Hover variants"]); 29 30 ("patterns_and_components_06.html", "06. Patterns and Components", 31 "Build reusable layout patterns and component compositions for consistent design.", 32 ["Layout patterns"; "Component composition"; "Reusable utilities"]); 33 34 ("comprehensive_showcase_07.html", "07. Comprehensive Showcase", 35 "Complete application demo showcasing all library features in a real-world context.", 36 ["Complete application"; "All features"; "Best practices"]); 37] 38 39let create_index_page () = 40 let page_classes = tw [ 41 Layout.(to_class (min_height Size.screen)); 42 Color.bg (Color.make `Gray ~variant:`V50 ()); 43 ] in 44 45 let container_classes = tw [ 46 Spacing.(to_class (mx `Auto)); 47 Spacing.(to_class (p (Size.rem 2.0))); 48 ] in 49 50 let header_classes = tw [ 51 Typography.(to_class (font_size `Xl4)); 52 Typography.(to_class (font_weight `Bold)); 53 Color.text (Color.make `Gray ~variant:`V900 ()); 54 Spacing.(to_class (mb (Size.rem 2.0))); 55 Typography.(to_class (text_align `Center)); 56 ] in 57 58 let subtitle_classes = tw [ 59 Typography.(to_class (font_size `Xl)); 60 Color.text (Color.make `Gray ~variant:`V600 ()); 61 Typography.(to_class (text_align `Center)); 62 Spacing.(to_class (mb (Size.rem 3.0))); 63 ] in 64 65 let grid_classes = tw [ 66 Display.grid; 67 Grid.(to_class (template_cols (`Cols 1))); 68 Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2)))))); 69 Spacing.(to_class (gap `All (Size.rem 1.5))); 70 Spacing.(to_class (mb (Size.rem 3.0))); 71 ] in 72 73 let card_classes = tw [ 74 Color.bg Color.white; 75 Effects.rounded_lg; 76 Effects.shadow_sm; 77 Spacing.(to_class (p (Size.rem 1.5))); 78 Effects.border; 79 Color.border (Color.make `Gray ~variant:`V200 ()); 80 Effects.transition `All; 81 Variants.hover Effects.shadow_md; 82 Variants.hover (Color.border (Color.make `Blue ~variant:`V300 ())); 83 ] in 84 85 let card_title_classes = tw [ 86 Typography.(to_class (font_size `Lg)); 87 Typography.(to_class (font_weight `Semibold)); 88 Color.text (Color.make `Gray ~variant:`V900 ()); 89 Spacing.(to_class (mb (Size.rem 0.75))); 90 ] in 91 92 let card_description_classes = tw [ 93 Color.text (Color.make `Gray ~variant:`V600 ()); 94 Spacing.(to_class (mb (Size.rem 1.0))); 95 Typography.(to_class (line_height `Relaxed)); 96 ] in 97 98 let features_classes = tw [ 99 Display.flex; 100 Flexbox.(to_class (wrap `Wrap)); 101 Spacing.(to_class (gap `All (Size.rem 0.5))); 102 Spacing.(to_class (mb (Size.rem 1.0))); 103 ] in 104 105 let feature_tag_classes = tw [ 106 Color.bg (Color.make `Blue ~variant:`V50 ()); 107 Color.text (Color.make `Blue ~variant:`V700 ()); 108 Typography.(to_class (font_size `Xs)); 109 Spacing.(to_class (px (Size.rem 0.5))); 110 Spacing.(to_class (py (Size.rem 0.25))); 111 Effects.rounded_full; 112 ] in 113 114 let link_classes = tw [ 115 Color.text (Color.make `Blue ~variant:`V600 ()); 116 Typography.(to_class (font_weight `Medium)); 117 Variants.hover (Color.text (Color.make `Blue ~variant:`V800 ())); 118 Effects.transition `Colors; 119 ] in 120 121 let footer_classes = tw [ 122 Typography.(to_class (text_align `Center)); 123 Spacing.(to_class (mt (Size.rem 3.0))); 124 Color.text (Color.make `Gray ~variant:`V500 ()); 125 Typography.(to_class (font_size `Sm)); 126 ] in 127 128 let html_doc = El.html [ 129 El.head [ 130 El.meta ~at:[At.charset "utf-8"] (); 131 El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] (); 132 El.title [El.txt "Tailwind OCaml Examples"]; 133 El.link ~at:[At.rel "stylesheet"; At.href "hello_tailwind_01.css"] (); (* Reuse CSS from first example *) 134 El.style [El.txt {| 135 body { font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; } 136 a { text-decoration: none; } 137 .example-card { display: block; } 138 |}]; 139 ]; 140 El.body ~at:[classes_attr page_classes] [ 141 El.div ~at:[classes_attr container_classes] [ 142 El.h1 ~at:[classes_attr header_classes] [ 143 El.txt "Tailwind OCaml Examples" 144 ]; 145 146 El.p ~at:[classes_attr subtitle_classes] [ 147 El.txt "A progressive tutorial series demonstrating type-safe Tailwind CSS generation in OCaml" 148 ]; 149 150 El.div ~at:[classes_attr grid_classes] ( 151 List.map (fun (href, title, description, features) -> 152 El.a ~at:[At.href href; At.class' "example-card"] [ 153 El.div ~at:[classes_attr card_classes] [ 154 El.h2 ~at:[classes_attr card_title_classes] [El.txt title]; 155 El.p ~at:[classes_attr card_description_classes] [El.txt description]; 156 El.div ~at:[classes_attr features_classes] ( 157 List.map (fun feature -> 158 El.span ~at:[classes_attr feature_tag_classes] [El.txt feature] 159 ) features 160 ); 161 El.div ~at:[classes_attr link_classes] [ 162 El.txt "View Example →" 163 ]; 164 ]; 165 ] 166 ) examples 167 ); 168 169 El.div ~at:[classes_attr footer_classes] [ 170 El.p [ 171 El.txt "Built with "; 172 El.a ~at:[At.href "https://github.com/dbuenzli/htmlit"; classes_attr link_classes] [El.txt "Htmlit"]; 173 El.txt " and type-safe Tailwind CSS generation" 174 ]; 175 ]; 176 ]; 177 ]; 178 ] in 179 html_doc 180 181let () = 182 (* Output HTML to stdout *) 183 let html_doc = create_index_page () in 184 let html_string = El.to_string ~doctype:true html_doc in 185 print_string html_string