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