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 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
182let () =
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