Tailwind classes in OCaml

Add index.html generator for examples showcase

- Create index_html_generator.ml that generates a beautiful index page
- Add comprehensive example descriptions and feature tags
- Link to all numbered tutorial examples (01-07) with descriptions
- Include responsive grid layout using type-safe Tailwind classes
- Add hover effects and proper styling for better user experience
- Integrate with dune build system to generate index.html automatically
- Add index.html to examples-html alias and install rules
- Reuse CSS from hello_tailwind_01.css to minimize dependencies

The index page provides:
- Progressive tutorial overview with clear descriptions
- Visual feature tags for each example
- Direct links to individual example pages
- Professional styling consistent with library design
- Mobile-responsive layout

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

+201
+15
examples/dune
··· 21 21 (package tailwind) 22 22 (libraries tailwind tailwind-html htmlit unix)) 23 23 24 + ;; HTML index generator 25 + (executable 26 + (public_name index_html_generator) 27 + (name index_html_generator) 28 + (package tailwind) 29 + (libraries tailwind htmlit)) 30 + 24 31 25 32 ;; Generate HTML files from examples 26 33 (rule ··· 115 122 (action 116 123 (run npx @tailwindcss/cli --input input.css --output %{targets} --content comprehensive_showcase_07.html --minify))) 117 124 125 + ;; Generate index.html page 126 + (rule 127 + (target index.html) 128 + (deps (:exe index_html_generator.exe)) 129 + (action (with-stdout-to %{target} (run %{exe})))) 130 + 118 131 ;; Alias to build all HTML files 119 132 (alias 120 133 (name examples-html) 121 134 (deps 135 + index.html 122 136 hello_tailwind_01.html 123 137 colors_and_typography_02.html 124 138 layout_and_spacing_03.html ··· 146 160 (section doc) 147 161 (package tailwind) 148 162 (files 163 + (index.html as examples/index.html) 149 164 (hello_tailwind_01.html as examples/hello_tailwind_01.html) 150 165 (hello_tailwind_01.css as examples/hello_tailwind_01.css) 151 166 (colors_and_typography_02.html as examples/colors_and_typography_02.html)
+186
examples/index_html_generator.ml
··· 1 + (* Generate index.html page linking to all examples *) 2 + 3 + open Htmlit 4 + open Tailwind 5 + 6 + let classes_attr tailwind_classes = 7 + At.class' (Tailwind.to_string tailwind_classes) 8 + 9 + let 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 + 39 + let 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 + Layout.(to_class (max_width (Size.rem 72.0))); (* max-w-6xl *) 47 + Spacing.(to_class (mx `Auto)); 48 + Spacing.(to_class (p (Size.rem 2.0))); 49 + ] in 50 + 51 + let header_classes = tw [ 52 + Typography.(to_class (font_size `Xl4)); 53 + Typography.(to_class (font_weight `Bold)); 54 + Color.text (Color.make `Gray ~variant:`V900 ()); 55 + Spacing.(to_class (mb (Size.rem 2.0))); 56 + Typography.(to_class (text_align `Center)); 57 + ] in 58 + 59 + let subtitle_classes = tw [ 60 + Typography.(to_class (font_size `Xl)); 61 + Color.text (Color.make `Gray ~variant:`V600 ()); 62 + Typography.(to_class (text_align `Center)); 63 + Spacing.(to_class (mb (Size.rem 3.0))); 64 + ] in 65 + 66 + let grid_classes = tw [ 67 + Display.grid; 68 + Grid.(to_class (template_cols (`Cols 1))); 69 + Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2)))))); 70 + Spacing.(to_class (gap `All (Size.rem 1.5))); 71 + Spacing.(to_class (mb (Size.rem 3.0))); 72 + ] in 73 + 74 + let card_classes = tw [ 75 + Color.bg Color.white; 76 + Effects.rounded_lg; 77 + Effects.shadow_sm; 78 + Spacing.(to_class (p (Size.rem 1.5))); 79 + Effects.border; 80 + Color.border (Color.make `Gray ~variant:`V200 ()); 81 + Effects.transition `All; 82 + Variants.hover Effects.shadow_md; 83 + Variants.hover (Color.border (Color.make `Blue ~variant:`V300 ())); 84 + ] in 85 + 86 + let card_title_classes = tw [ 87 + Typography.(to_class (font_size `Lg)); 88 + Typography.(to_class (font_weight `Semibold)); 89 + Color.text (Color.make `Gray ~variant:`V900 ()); 90 + Spacing.(to_class (mb (Size.rem 0.75))); 91 + ] in 92 + 93 + let card_description_classes = tw [ 94 + Color.text (Color.make `Gray ~variant:`V600 ()); 95 + Spacing.(to_class (mb (Size.rem 1.0))); 96 + Typography.(to_class (line_height `Relaxed)); 97 + ] in 98 + 99 + let features_classes = tw [ 100 + Display.flex; 101 + Flexbox.(to_class (wrap `Wrap)); 102 + Spacing.(to_class (gap `All (Size.rem 0.5))); 103 + Spacing.(to_class (mb (Size.rem 1.0))); 104 + ] in 105 + 106 + let feature_tag_classes = tw [ 107 + Color.bg (Color.make `Blue ~variant:`V50 ()); 108 + Color.text (Color.make `Blue ~variant:`V700 ()); 109 + Typography.(to_class (font_size `Xs)); 110 + Spacing.(to_class (px (Size.rem 0.5))); 111 + Spacing.(to_class (py (Size.rem 0.25))); 112 + Effects.rounded_full; 113 + ] in 114 + 115 + let link_classes = tw [ 116 + Color.text (Color.make `Blue ~variant:`V600 ()); 117 + Typography.(to_class (font_weight `Medium)); 118 + Variants.hover (Color.text (Color.make `Blue ~variant:`V800 ())); 119 + Effects.transition `Colors; 120 + ] in 121 + 122 + let footer_classes = tw [ 123 + Typography.(to_class (text_align `Center)); 124 + Spacing.(to_class (mt (Size.rem 3.0))); 125 + Color.text (Color.make `Gray ~variant:`V500 ()); 126 + Typography.(to_class (font_size `Sm)); 127 + ] in 128 + 129 + let html_doc = El.html [ 130 + El.head [ 131 + El.meta ~at:[At.charset "utf-8"] (); 132 + El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] (); 133 + El.title [El.txt "Tailwind OCaml Examples"]; 134 + El.link ~at:[At.rel "stylesheet"; At.href "hello_tailwind_01.css"] (); (* Reuse CSS from first example *) 135 + El.style [El.txt {| 136 + body { font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; } 137 + a { text-decoration: none; } 138 + .example-card { display: block; } 139 + |}]; 140 + ]; 141 + El.body ~at:[classes_attr page_classes] [ 142 + El.div ~at:[classes_attr container_classes] [ 143 + El.h1 ~at:[classes_attr header_classes] [ 144 + El.txt "Tailwind OCaml Examples" 145 + ]; 146 + 147 + El.p ~at:[classes_attr subtitle_classes] [ 148 + El.txt "A progressive tutorial series demonstrating type-safe Tailwind CSS generation in OCaml" 149 + ]; 150 + 151 + El.div ~at:[classes_attr grid_classes] ( 152 + List.map (fun (href, title, description, features) -> 153 + El.a ~at:[At.href href; At.class' "example-card"] [ 154 + El.div ~at:[classes_attr card_classes] [ 155 + El.h2 ~at:[classes_attr card_title_classes] [El.txt title]; 156 + El.p ~at:[classes_attr card_description_classes] [El.txt description]; 157 + El.div ~at:[classes_attr features_classes] ( 158 + List.map (fun feature -> 159 + El.span ~at:[classes_attr feature_tag_classes] [El.txt feature] 160 + ) features 161 + ); 162 + El.div ~at:[classes_attr link_classes] [ 163 + El.txt "View Example →" 164 + ]; 165 + ]; 166 + ] 167 + ) examples 168 + ); 169 + 170 + El.div ~at:[classes_attr footer_classes] [ 171 + El.p [ 172 + El.txt "Built with "; 173 + El.a ~at:[At.href "https://github.com/dbuenzli/htmlit"; classes_attr link_classes] [El.txt "Htmlit"]; 174 + El.txt " and type-safe Tailwind CSS generation" 175 + ]; 176 + ]; 177 + ]; 178 + ]; 179 + ] in 180 + html_doc 181 + 182 + let () = 183 + (* Output HTML to stdout *) 184 + let html_doc = create_index_page () in 185 + let html_string = El.to_string ~doctype:true html_doc in 186 + print_string html_string