# Tailwind OCaml 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 - **`tailwind-html`**: High-level HTML component library with GADT-based heterogeneous list interface built on [Htmlit](https://github.com/dbuenzli/htmlit) ## Features - **GADT-based Interface**: Succinct heterogeneous list syntax with compile-time type safety - **Zero Runtime Cost**: All CSS generation happens at compile time - **Comprehensive Grid Support**: Full CSS Grid integration with type-safe properties - **Type-Safe Colors & Spacing**: Exhaustive variants with compile-time validation - **Built-in Components**: Pre-styled buttons, cards, and layout helpers ### Complete Tailwind Coverage - **Typography**: Font sizes, weights, text alignment with type-safe variants - **Layout**: CSS Grid, Flexbox, spacing with compile-time validation - **Colors**: Full palette (gray, blue, red, green, etc.) with variant checking - **Effects**: Shadows, borders, rounded corners, transitions - **Components**: Pre-built buttons, cards, and layout helpers - **Type Safety**: GADT-based heterogeneous lists prevent invalid combinations ## Quick Start ### GADT Interface (Recommended) The new GADT-based interface provides succinct, type-safe styling with heterogeneous lists: ```ocaml open Htmlit open Tailwind_html (* Create a centered card with CSS Grid *) let create_hero_section () = div ~styles:[ grid; grid_cols 1; gap (rem 2.0); padding (rem 3.0); text_center; ] [ h1 ~styles:[ font_size `Xl3; font_weight `Bold; text_color (blue 600); margin_bottom (rem 1.5); ] [txt "Welcome to Tailwind OCaml"]; p ~styles:[ font_size `Lg; text_color (gray 600); margin_bottom (rem 2.0); ] [txt "Type-safe CSS with compile-time guarantees"]; (* Built-in button components *) btn_primary ~size:`Lg [txt "Get Started"]; ] ``` ### CSS Grid Layouts ```ocaml (* Three-column responsive grid *) div ~styles:[ grid; grid_cols 3; gap (rem 1.5); ] [ card [h3 [txt "Feature 1"]; p [txt "Description"]]; card [h3 [txt "Feature 2"]; p [txt "Description"]]; card [h3 [txt "Feature 3"]; p [txt "Description"]]; ] ``` ### Built-in Components ```ocaml (* Pre-styled components with size variants *) btn_primary ~size:`Lg [txt "Primary Action"]; btn_secondary [txt "Secondary Action"]; btn_outline ~size:`Sm [txt "Outline Button"]; (* Layout helpers *) container [ card [ h2 ~styles:[font_size `Xl; margin_bottom (rem 1.0)] [txt "Card Title"]; p ~styles:[text_color (gray 600)] [txt "Card content with automatic styling"]; ]; ] ``` ## Examples The `examples/` directory showcases the GADT interface across various use cases: ### Available Examples ```bash # Build all examples dune build examples/ # Hello World with GADT interface dune exec examples/hello_tailwind_01.exe > hello.html # Colors and Typography showcase dune exec examples/colors_and_typography_02.exe > colors.html # CSS Grid and Layout demonstrations dune exec examples/layout_and_spacing_03.exe > layout.html # Responsive design patterns dune exec examples/responsive_design_04.exe > responsive.html # Visual effects and styling dune exec examples/effects_and_variants_05.exe > effects.html # Component patterns and reusable elements dune exec examples/patterns_and_components_06.exe > patterns.html # Complete application showcase dune exec examples/comprehensive_showcase_07.exe > showcase.html # Button component demonstration dune exec examples/button_demo.exe > buttons.html # Generate index page linking all examples dune exec examples/index_html_generator.exe > index.html ``` ### Example Highlights **CSS Grid Layout (`layout_and_spacing_03.ml`)**: ```ocaml (* Three-column grid with gap variations *) div ~styles:[ grid; grid_cols 3; gap (rem 1.0); ] [ div ~styles:[bg_color (blue 100); padding (rem 1.0)] [txt "Item 1"]; div ~styles:[bg_color (green 100); padding (rem 1.0)] [txt "Item 2"]; div ~styles:[bg_color (purple 100); padding (rem 1.0)] [txt "Item 3"]; ] (* Asymmetric grid gaps *) div ~styles:[ grid; grid_cols 2; gap_x (rem 2.0); gap_y (rem 0.5); ] (List.init 4 (fun i -> div ~styles:[bg_color (purple 200); text_center] [ txt (Printf.sprintf "Box %d" (i + 1)) ] )) ``` **Built-in Components (`button_demo.ml`)**: ```ocaml (* Size variants with consistent styling *) div ~styles:[flex; flex_col; gap (rem 1.0)] [ btn_primary ~size:`Sm [txt "Small Primary"]; btn_primary [txt "Default Primary"]; btn_primary ~size:`Lg [txt "Large Primary"]; btn_secondary [txt "Secondary Button"]; btn_outline [txt "Outline Button"]; ] ``` **Responsive Cards (`comprehensive_showcase_07.ml`)**: ```ocaml section ~styles:[margin_bottom (rem 4.0)] [ h3 ~styles:[font_size `Xl2; text_center; margin_bottom (rem 3.0)] [ txt "Features" ]; div ~styles:[grid; grid_cols 1; gap (rem 2.0)] [ card [ h4 ~styles:[font_size `Xl; font_weight `Semibold; text_color (blue 600)] [ txt "🎯 Type Safety" ]; p ~styles:[text_color (gray 600)] [ txt "Catch styling errors at compile time with GADT-based type checking." ]; ]; card [ h4 ~styles:[font_size `Xl; font_weight `Semibold; text_color (green 600)] [ txt "⚡ Performance" ]; p ~styles:[text_color (gray 600)] [ txt "Zero runtime overhead with compile-time CSS generation." ]; ]; ]; ] ``` ## Tailwind v4 Support This library supports Tailwind v4's CSS-first approach: ```css /* Generated input.css - no config file needed! */ @import "tailwindcss"; @theme { --font-sans: 'Inter', system-ui, sans-serif; --color-brand-600: #2563eb; /* Custom theme extensions */ } ``` To process the CSS: ```bash npx tailwindcss@next -i input.css -o output.css ``` ## API Reference ### `Tailwind_html` (GADT Interface) The high-level GADT interface provides succinct, type-safe styling with heterogeneous lists: #### Layout Properties ```ocaml ~styles:[ (* Display *) grid | flex | block | inline | hidden; (* Grid System *) grid_cols 3 | grid_rows 2; gap (rem 1.0) | gap_x (rem 1.5) | gap_y (rem 0.5); (* Flexbox *) flex_col | flex_row; justify_center | justify_between | justify_end; items_center | items_start | items_end; (* Sizing *) width full | height screen; min_height screen | max_width (rem 64.0); ] ``` #### Typography Properties ```ocaml ~styles:[ (* Font Sizes *) font_size `Xs | font_size `Sm | font_size `Base | font_size `Lg; font_size `Xl | font_size `Xl2 | font_size `Xl3; (* Font Weights *) font_weight `Light | font_weight `Normal | font_weight `Medium; font_weight `Semibold | font_weight `Bold; (* Text Styling *) text_center | text_left | text_right; text_color (blue 600) | text_color (gray 500); ] ``` #### Color System ```ocaml ~styles:[ (* Background Colors *) bg_color (blue 50) | bg_color (gray 100) | bg_color (red 500); bg_color (Tailwind.Color.white) | bg_color (green 600); (* Text Colors *) text_color (gray 800) | text_color (blue 600) | text_color (red 500); (* Border Colors *) border_color (gray 200) | border_color (blue 300); ] ``` #### Spacing Properties ```ocaml ~styles:[ (* Padding *) padding (rem 1.0) | padding_x (rem 1.5) | padding_y (rem 2.0); (* Margin *) margin (rem 1.0) | margin_x auto | margin_bottom (rem 2.0); margin_top (rem 1.5) | margin_left (rem 0.5); ] ``` #### Visual Effects ```ocaml ~styles:[ (* Shadows *) shadow `Sm | shadow `Md | shadow `Lg | shadow `Xl; (* Borders *) border | rounded `Sm | rounded `Md | rounded `Lg | rounded `Full; (* Transitions *) transition; ] ``` #### Built-in Components ```ocaml (* Button Components *) btn_primary ~size:`Lg [txt "Primary Button"]; btn_secondary ~size:`Sm [txt "Secondary Button"]; btn_outline [txt "Outline Button"]; (* Layout Components *) container [content]; (* Max-width container with auto margins *) card [content]; (* Pre-styled card with padding and shadow *) (* HTML Elements with Styling *) h1 ~styles:[font_size `Xl3; font_weight `Bold] [txt "Heading"]; p ~styles:[text_color (gray 600); margin_bottom (rem 1.0)] [txt "Paragraph"]; div ~styles:[grid; grid_cols 2; gap (rem 1.0)] [content]; section ~styles:[margin_bottom (rem 2.0)] [content]; ``` ### Low-Level `Tailwind` Module For advanced use cases, the core `Tailwind` module provides detailed control: ```ocaml open Tailwind let classes = Css.tw [ Display.grid; Grid.(to_class (template_cols (`Cols 3))); Spacing.(to_class (gap `All (Size.rem 1.0))); Color.bg (Color.make `Blue ~variant:`V50 ()); ] let html_class = to_string classes (* "grid grid-cols-3 gap-4 bg-blue-50" *) ``` ### Getting Started Add to your `dune-project`: ```dune (package (name myproject) (depends ocaml dune tailwind tailwind-html htmlit)) ``` Then in your OCaml code: ```ocaml open Htmlit open Tailwind_html let my_page = El.html [ El.head [El.title [txt "My App"]]; El.body ~at:[classes_attr [min_height screen; bg_color (gray 50)]] [ container [ h1 ~styles:[font_size `Xl3; text_center; margin_bottom (rem 2.0)] [ txt "Welcome to Type-Safe CSS!" ]; btn_primary [txt "Get Started"]; ]; ]; ] ``` ## Testing Run the test suite: ```bash dune test ``` ## Contributing Contributions are welcome! Please: 1. Fork the repository 2. Create a feature branch 3. Make your changes with tests 4. Submit a pull request ## License MIT License - see LICENSE file for details ## Acknowledgments - Built on top of [Htmlit](https://github.com/dbuenzli/htmlit) by Daniel Bünzli - Inspired by [Tailwind CSS](https://tailwindcss.com/) ## Resources - [Tailwind CSS Documentation](https://tailwindcss.com/docs) - [Tailwind v4 Alpha](https://tailwindcss.com/blog/tailwindcss-v4-alpha) - [Htmlit Documentation](https://erratique.ch/software/htmlit/doc/)