···
3
-
An OCaml library for generating Tailwind CSS classes with compile-time
4
-
validation and a companion HTML generation library using Htmlit.
3
+
Type-safe Tailwind CSS generation for OCaml with a revolutionary GADT-based interface for succinct, compile-time validated styling.
This project provides two main libraries:
- **`tailwind`**: Core library for type-safe Tailwind CSS class generation
9
-
- **`tailwind-html`**: HTML component library built on top of [Htmlit](https://github.com/dbuenzli/htmlit)
8
+
- **`tailwind-html`**: High-level HTML component library with GADT-based heterogeneous list interface built on [Htmlit](https://github.com/dbuenzli/htmlit)
13
-
- Compile-time validation of Tailwind classes
14
-
- Type-safe color variants and sizes
15
-
- Exhaustive pattern matching for all utility classes
12
+
- **GADT-based Interface**: Succinct heterogeneous list syntax with compile-time type safety
13
+
- **Zero Runtime Cost**: All CSS generation happens at compile time
14
+
- **Comprehensive Grid Support**: Full CSS Grid integration with type-safe properties
15
+
- **Type-Safe Colors & Spacing**: Exhaustive variants with compile-time validation
16
+
- **Built-in Components**: Pre-styled buttons, cards, and layout helpers
17
-
### Comprehensive Coverage
18
-
- **Typography**: Font sizes, weights, line heights, text alignment, decorations
19
-
- **Layout**: Display, position, flexbox, grid, spacing
20
-
- **Colors**: Full color palette with variants
18
+
### Complete Tailwind Coverage
19
+
- **Typography**: Font sizes, weights, text alignment with type-safe variants
20
+
- **Layout**: CSS Grid, Flexbox, spacing with compile-time validation
21
+
- **Colors**: Full palette (gray, blue, red, green, etc.) with variant checking
- **Effects**: Shadows, borders, rounded corners, transitions
22
-
- **Responsive**: Breakpoint-based responsive utilities
23
-
- **Variants**: Hover, focus, and other state variants
23
+
- **Components**: Pre-built buttons, cards, and layout helpers
24
+
- **Type Safety**: GADT-based heterogeneous lists prevent invalid combinations
27
-
Add to your `dune-project`:
28
+
### GADT Interface (Recommended)
30
+
The new GADT-based interface provides succinct, type-safe styling with heterogeneous lists:
47
-
(* Create a styled div *)
51
-
Flexbox.(to_class (justify `Center));
52
-
Flexbox.(to_class (align_items `Center));
53
-
Color.bg (Color.make `Gray ~variant:`V100 ());
54
-
Spacing.(to_class (p (Size.rem 2.0)));
56
-
Printf.sprintf "<div class=\"%s\">Content</div>" (to_string classes)
36
+
(* Create a centered card with CSS Grid *)
37
+
let create_hero_section () =
48
+
text_color (blue 600);
49
+
margin_bottom (rem 1.5);
50
+
] [txt "Welcome to Tailwind OCaml"];
54
+
text_color (gray 600);
55
+
margin_bottom (rem 2.0);
56
+
] [txt "Type-safe CSS with compile-time guarantees"];
58
+
(* Built-in button components *)
59
+
btn_primary ~size:`Lg [txt "Get Started"];
59
-
### With Htmlit Integration
63
+
### CSS Grid Layouts
66
+
(* Three-column responsive grid *)
72
+
card [h3 [txt "Feature 1"]; p [txt "Description"]];
73
+
card [h3 [txt "Feature 2"]; p [txt "Description"]];
74
+
card [h3 [txt "Feature 3"]; p [txt "Description"]];
65
-
let classes_attr tailwind_classes =
66
-
At.class' (Tailwind.to_string tailwind_classes)
78
+
### Built-in Components
68
-
let create_card title content =
69
-
El.div ~at:[classes_attr (tw [
71
-
Spacing.(to_class (p (Size.rem 1.5)));
74
-
El.h2 ~at:[classes_attr (tw [
75
-
Typography.(to_class (font_size `Xl));
76
-
Typography.(to_class (font_weight `Bold));
77
-
Spacing.(to_class (mb (Size.rem 1.0)));
79
-
El.p [El.txt content];
81
+
(* Pre-styled components with size variants *)
82
+
btn_primary ~size:`Lg [txt "Primary Action"];
83
+
btn_secondary [txt "Secondary Action"];
84
+
btn_outline ~size:`Sm [txt "Outline Button"];
86
+
(* Layout helpers *)
89
+
h2 ~styles:[font_size `Xl; margin_bottom (rem 1.0)] [txt "Card Title"];
90
+
p ~styles:[text_color (gray 600)] [txt "Card content with automatic styling"];
85
-
The `examples/` directory contains several demonstration files:
97
+
The `examples/` directory showcases the GADT interface across various use cases:
87
-
### Running Examples
99
+
### Available Examples
93
-
# Run comprehensive showcase (generates HTML + CSS)
94
-
dune exec examples/comprehensive_showcase.exe
105
+
# Hello World with GADT interface
106
+
dune exec examples/hello_tailwind_01.exe > hello.html
108
+
# Colors and Typography showcase
109
+
dune exec examples/colors_and_typography_02.exe > colors.html
111
+
# CSS Grid and Layout demonstrations
112
+
dune exec examples/layout_and_spacing_03.exe > layout.html
96
-
# Run basic usage example
97
-
dune exec examples/basic_usage.exe
114
+
# Responsive design patterns
115
+
dune exec examples/responsive_design_04.exe > responsive.html
99
-
# Run HTML integration example
100
-
dune exec examples/tailwind_html_example.exe
117
+
# Visual effects and styling
118
+
dune exec examples/effects_and_variants_05.exe > effects.html
120
+
# Component patterns and reusable elements
121
+
dune exec examples/patterns_and_components_06.exe > patterns.html
123
+
# Complete application showcase
124
+
dune exec examples/comprehensive_showcase_07.exe > showcase.html
126
+
# Button component demonstration
127
+
dune exec examples/button_demo.exe > buttons.html
129
+
# Generate index page linking all examples
130
+
dune exec examples/index_html_generator.exe > index.html
103
-
### Comprehensive Showcase
133
+
### Example Highlights
135
+
**CSS Grid Layout (`layout_and_spacing_03.ml`)**:
137
+
(* Three-column grid with gap variations *)
143
+
div ~styles:[bg_color (blue 100); padding (rem 1.0)] [txt "Item 1"];
144
+
div ~styles:[bg_color (green 100); padding (rem 1.0)] [txt "Item 2"];
145
+
div ~styles:[bg_color (purple 100); padding (rem 1.0)] [txt "Item 3"];
105
-
The comprehensive showcase demonstrates all library features and generates:
106
-
- `showcase.html` - Complete HTML page with all Tailwind classes
107
-
- `input.css` - Tailwind v4 CSS with custom theme extensions
148
+
(* Asymmetric grid gaps *)
154
+
] (List.init 4 (fun i ->
155
+
div ~styles:[bg_color (purple 200); text_center] [
156
+
txt (Printf.sprintf "Box %d" (i + 1))
110
-
dune exec examples/comprehensive_showcase.exe
111
-
# Then open showcase.html in your browser
161
+
**Built-in Components (`button_demo.ml`)**:
163
+
(* Size variants with consistent styling *)
164
+
div ~styles:[flex; flex_col; gap (rem 1.0)] [
165
+
btn_primary ~size:`Sm [txt "Small Primary"];
166
+
btn_primary [txt "Default Primary"];
167
+
btn_primary ~size:`Lg [txt "Large Primary"];
168
+
btn_secondary [txt "Secondary Button"];
169
+
btn_outline [txt "Outline Button"];
173
+
**Responsive Cards (`comprehensive_showcase_07.ml`)**:
175
+
section ~styles:[margin_bottom (rem 4.0)] [
176
+
h3 ~styles:[font_size `Xl2; text_center; margin_bottom (rem 3.0)] [
180
+
div ~styles:[grid; grid_cols 1; gap (rem 2.0)] [
182
+
h4 ~styles:[font_size `Xl; font_weight `Semibold; text_color (blue 600)] [
183
+
txt "🎯 Type Safety"
185
+
p ~styles:[text_color (gray 600)] [
186
+
txt "Catch styling errors at compile time with GADT-based type checking."
190
+
h4 ~styles:[font_size `Xl; font_weight `Semibold; text_color (green 600)] [
191
+
txt "⚡ Performance"
193
+
p ~styles:[text_color (gray 600)] [
194
+
txt "Zero runtime overhead with compile-time CSS generation."
···
npx tailwindcss@next -i input.css -o output.css
134
-
## Module Documentation
223
+
### `Tailwind_html` (GADT Interface)
139
-
Main module that exports all utilities and provides the `tw` function for composing classes.
225
+
The high-level GADT interface provides succinct, type-safe styling with heterogeneous lists:
142
-
Type-safe color system with variants:
227
+
#### Layout Properties
144
-
Color.bg (Color.make `Blue ~variant:`V600 ())
145
-
Color.text Color.white
146
-
Color.border (Color.make `Gray ~variant:`V200 ())
231
+
grid | flex | block | inline | hidden;
234
+
grid_cols 3 | grid_rows 2;
235
+
gap (rem 1.0) | gap_x (rem 1.5) | gap_y (rem 0.5);
238
+
flex_col | flex_row;
239
+
justify_center | justify_between | justify_end;
240
+
items_center | items_start | items_end;
243
+
width full | height screen;
244
+
min_height screen | max_width (rem 64.0);
248
+
#### Typography Properties
152
-
Typography.(to_class (font_size `Xl2))
153
-
Typography.(to_class (font_weight `Bold))
154
-
Typography.(to_class (line_height `Relaxed))
252
+
font_size `Xs | font_size `Sm | font_size `Base | font_size `Lg;
253
+
font_size `Xl | font_size `Xl2 | font_size `Xl3;
256
+
font_weight `Light | font_weight `Normal | font_weight `Medium;
257
+
font_weight `Semibold | font_weight `Bold;
260
+
text_center | text_left | text_right;
261
+
text_color (blue 600) | text_color (gray 500);
158
-
Margin and padding utilities:
160
-
Spacing.(to_class (p (Size.rem 1.0))) (* padding *)
161
-
Spacing.(to_class (mx Size.auto)) (* margin-x auto *)
162
-
Spacing.(to_class (gap `All (Size.px 16.0))) (* gap *)
268
+
(* Background Colors *)
269
+
bg_color (blue 50) | bg_color (gray 100) | bg_color (red 500);
270
+
bg_color (Tailwind.Color.white) | bg_color (green 600);
273
+
text_color (gray 800) | text_color (blue 600) | text_color (red 500);
275
+
(* Border Colors *)
276
+
border_color (gray 200) | border_color (blue 300);
280
+
#### Spacing Properties
168
-
Layout.(to_class (width (Size.percent 100.0)))
169
-
Layout.(to_class (height Size.screen))
170
-
Layout.(to_class (max_width (Size.rem 64.0)))
284
+
padding (rem 1.0) | padding_x (rem 1.5) | padding_y (rem 2.0);
287
+
margin (rem 1.0) | margin_x auto | margin_bottom (rem 2.0);
288
+
margin_top (rem 1.5) | margin_left (rem 0.5);
292
+
#### Visual Effects
177
-
Flexbox.(to_class (justify `Between))
178
-
Flexbox.(to_class (align_items `Center))
179
-
Flexbox.(to_class (direction `Col))
296
+
shadow `Sm | shadow `Md | shadow `Lg | shadow `Xl;
299
+
border | rounded `Sm | rounded `Md | rounded `Lg | rounded `Full;
183
-
CSS Grid utilities:
306
+
#### Built-in Components
186
-
Grid.(to_class (template_cols (`Cols 3)))
187
-
Grid.(to_class (gap (Size.rem 1.0)))
308
+
(* Button Components *)
309
+
btn_primary ~size:`Lg [txt "Primary Button"];
310
+
btn_secondary ~size:`Sm [txt "Secondary Button"];
311
+
btn_outline [txt "Outline Button"];
313
+
(* Layout Components *)
314
+
container [content]; (* Max-width container with auto margins *)
315
+
card [content]; (* Pre-styled card with padding and shadow *)
196
-
Effects.transition `All
317
+
(* HTML Elements with Styling *)
318
+
h1 ~styles:[font_size `Xl3; font_weight `Bold] [txt "Heading"];
319
+
p ~styles:[text_color (gray 600); margin_bottom (rem 1.0)] [txt "Paragraph"];
320
+
div ~styles:[grid; grid_cols 2; gap (rem 1.0)] [content];
321
+
section ~styles:[margin_bottom (rem 2.0)] [content];
200
-
Responsive utilities:
202
-
Responsive.(to_class (at_breakpoint `Md Display.flex))
203
-
Responsive.(to_class (at_breakpoint `Lg (Grid.(to_class (template_cols (`Cols 4))))))
324
+
### Low-Level `Tailwind` Module
209
-
Variants.hover (Color.bg (Color.make `Blue ~variant:`V700 ()))
210
-
Variants.focus Effects.ring
326
+
For advanced use cases, the core `Tailwind` module provides detailed control:
214
-
Common layout patterns:
216
-
Patterns.container ()
218
-
Patterns.flex_center
219
-
Patterns.stack ~gap:(Size.rem 1.0) ()
220
-
Patterns.sticky_header
331
+
let classes = Css.tw [
333
+
Grid.(to_class (template_cols (`Cols 3)));
334
+
Spacing.(to_class (gap `All (Size.rem 1.0)));
335
+
Color.bg (Color.make `Blue ~variant:`V50 ());
338
+
let html_class = to_string classes (* "grid grid-cols-3 gap-4 bg-blue-50" *)
223
-
### HTML Components (`tailwind-html`)
341
+
### Getting Started
225
-
Pre-built components using Htmlit:
343
+
Add to your `dune-project`:
355
+
Then in your OCaml code:
230
-
(* Button component *)
231
-
Button.primary ~text:"Click me" ~onclick:"handleClick()"
233
-
(* Card component *)
234
-
Card.simple ~title:"Card Title" ~content:"Card content here"
236
-
(* Layout components *)
239
-
Layout.col ~span:6 [content];
240
-
Layout.col ~span:6 [content];
360
+
let my_page = El.html [
361
+
El.head [El.title [txt "My App"]];
362
+
El.body ~at:[classes_attr [min_height screen; bg_color (gray 50)]] [
364
+
h1 ~styles:[font_size `Xl3; text_center; margin_bottom (rem 2.0)] [
365
+
txt "Welcome to Type-Safe CSS!"
367
+
btn_primary [txt "Get Started"];