Tailwind classes in OCaml

Refactor library API: integrate V4 functions into relevant submodules and move tw to Css

- Remove separate V4 module (library is Tailwind v4 only)
- Move V4 functions to appropriate submodules:
• text_shadow, mask, perspective → Effects module
• starting_style → Variants module (convenience function)
- Move accessibility functions to Layout module:
• sr_only, focus_ring → Layout module
- Move tw function from top-level to Css module (better logical organization)
- Update all examples and tests to use Css.tw instead of tw
- Update tailwind-html library to use Tailwind.Css.tw

Breaking change: tw function moved from Tailwind.tw to Css.tw
Migration: Replace `tw [...]` with `Css.tw [...]` or `Tailwind.Css.tw [...]`

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

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

examples/.hello_tailwind_01.ml.swp

This is a binary file and will not be displayed.

+24 -24
examples/colors_and_typography_02.ml
···
];
El.body ~at:[At.class' "min-h-screen bg-gray-50 p-8"] [
El.div ~at:[At.class' "max-w-4xl mx-auto"] [
-
El.h1 ~at:[classes_attr (tw [
+
El.h1 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl2));
Typography.(to_class (font_weight `Bold));
Color.text (Color.make `Gray ~variant:`V800 ());
]); At.class' "mb-8 text-center"] [El.txt "Colors and Typography Demo"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Color.text (Color.make `Gray ~variant:`V600 ());
]); At.class' "text-center mb-12"] [
···
(* Color Palette Section *)
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-8"] [El.txt "Color Palette"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.grid;
Grid.(to_class (template_cols (`Cols 1)));
Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2))))));
Responsive.(to_class (at_breakpoint `Lg (Grid.(to_class (template_cols (`Cols 3))))));
Spacing.(to_class (gap `All (Size.rem 1.5)));
])] (List.map (fun (name, color) ->
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.5)));
Effects.rounded_lg;
Effects.shadow_sm;
]); At.class' "text-center"] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.text color;
Typography.(to_class (font_size `Xl2));
Typography.(to_class (font_weight `Bold));
]); At.class' "mb-4"] [El.txt "Aa"];
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V800 ());
]); At.class' "mb-2"] [El.txt name];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Sm));
Color.text (Color.make `Gray ~variant:`V500 ());
-
]); At.class' "mb-3"] [El.txt (to_string (tw [Color.text color]))];
-
El.p ~at:[classes_attr (tw [Color.text color])] [
+
]); At.class' "mb-3"] [El.txt (to_string (Css.tw [Color.text color]))];
+
El.p ~at:[classes_attr (Css.tw [Color.text color])] [
El.txt "The quick brown fox jumps over the lazy dog"
];
]
···
(* Typography Scale Section *)
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-8"] [El.txt "Typography Scale"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 2.0)));
Effects.rounded_lg;
Effects.shadow_sm;
]); At.class' "mb-8"] (List.map (fun (name, typ_class) ->
El.div ~at:[At.class' "mb-6 last:mb-0"] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.flex;
Flexbox.(to_class (align_items `Center));
Flexbox.(to_class (justify `Between));
Spacing.(to_class (gap `All (Size.rem 1.0)));
]); At.class' "mb-2"] [
-
El.span ~at:[classes_attr (tw [
+
El.span ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Sm));
Typography.(to_class (font_weight `Medium));
Color.text (Color.make `Gray ~variant:`V500 ());
])] [El.txt name];
-
El.code ~at:[classes_attr (tw [
+
El.code ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xs));
Color.bg (Color.make `Gray ~variant:`V100 ());
Spacing.(to_class (px (Size.rem 0.5)));
Spacing.(to_class (py (Size.rem 0.25)));
Effects.rounded_sm;
-
])] [El.txt (to_string (tw [typ_class]))];
+
])] [El.txt (to_string (Css.tw [typ_class]))];
];
-
El.p ~at:[classes_attr (tw [typ_class])] [
+
El.p ~at:[classes_attr (Css.tw [typ_class])] [
El.txt "The quick brown fox jumps over the lazy dog"
];
]
···
(* Font Weights Section *)
El.section [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
···
("Extrabold", Typography.(to_class (font_weight `Extrabold)));
] in
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 2.0)));
Effects.rounded_lg;
Effects.shadow_sm;
])] (List.map (fun (name, weight_class) ->
El.div ~at:[At.class' "mb-6 last:mb-0"] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.flex;
Flexbox.(to_class (align_items `Center));
Flexbox.(to_class (justify `Between));
Spacing.(to_class (gap `All (Size.rem 1.0)));
]); At.class' "mb-2"] [
-
El.span ~at:[classes_attr (tw [
+
El.span ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Sm));
Typography.(to_class (font_weight `Medium));
Color.text (Color.make `Gray ~variant:`V500 ());
])] [El.txt name];
-
El.code ~at:[classes_attr (tw [
+
El.code ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xs));
Color.bg (Color.make `Gray ~variant:`V100 ());
Spacing.(to_class (px (Size.rem 0.5)));
Spacing.(to_class (py (Size.rem 0.25)));
Effects.rounded_sm;
-
])] [El.txt (to_string (tw [weight_class]))];
+
])] [El.txt (to_string (Css.tw [weight_class]))];
];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
weight_class;
Typography.(to_class (font_size `Lg));
])] [
+14 -14
examples/comprehensive_showcase_07.ml
···
El.link ~at:[At.rel "stylesheet"; At.href "comprehensive_showcase_07.css"] ();
];
-
El.body ~at:[classes_attr (Tailwind.tw [
+
El.body ~at:[classes_attr (Tailwind.Css.tw [
Color.bg (Color.make `Gray ~variant:`V50 ());
Typography.(to_class (font_size `Base));
Typography.(to_class (line_height `Normal));
])] [
(* Header with navigation *)
-
El.header ~at:[classes_attr (Tailwind.tw [
+
El.header ~at:[classes_attr (Tailwind.Css.tw [
Color.bg Color.white;
Effects.shadow_lg;
Effects.border;
Color.border (Color.make `Gray ~variant:`V200 ());
Patterns.sticky_header;
])] [
-
El.div ~at:[classes_attr (Tailwind.tw [
+
El.div ~at:[classes_attr (Tailwind.Css.tw [
Patterns.container ();
Spacing.(to_class (px (Size.rem 1.0)));
])] [
-
El.div ~at:[classes_attr (Tailwind.tw [
+
El.div ~at:[classes_attr (Tailwind.Css.tw [
Display.flex;
Flexbox.(to_class (justify `Between));
Flexbox.(to_class (align_items `Center));
Layout.(to_class (height (Size.rem 4.0)));
])] [
(* Brand with gradient text *)
-
El.h1 ~at:[classes_attr (Tailwind.tw [
+
El.h1 ~at:[classes_attr (Tailwind.Css.tw [
Typography.(to_class (font_size `Xl2));
Typography.(to_class (font_weight `Bold));
Color.text (Color.make `Blue ~variant:`V600 ());
])] [El.txt "Tailwind OCaml"];
(* Navigation items with hover effects *)
-
El.nav ~at:[classes_attr (Tailwind.tw [
+
El.nav ~at:[classes_attr (Tailwind.Css.tw [
Display.flex;
Spacing.(to_class (gap `All (Size.rem 2.0)));
Flexbox.(to_class (align_items `Center));
])] [
-
El.a ~at:[At.href "#typography"; classes_attr (Tailwind.tw [
+
El.a ~at:[At.href "#typography"; classes_attr (Tailwind.Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
Variants.hover (Color.text (Color.make `Gray ~variant:`V900 ()));
Effects.transition `All;
])] [El.txt "Typography"];
-
El.a ~at:[At.href "#layout"; classes_attr (Tailwind.tw [
+
El.a ~at:[At.href "#layout"; classes_attr (Tailwind.Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
Variants.hover (Color.text (Color.make `Gray ~variant:`V900 ()));
Effects.transition `All;
])] [El.txt "Layout"];
-
El.a ~at:[At.href "#components"; classes_attr (Tailwind.tw [
+
El.a ~at:[At.href "#components"; classes_attr (Tailwind.Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
Variants.hover (Color.text (Color.make `Gray ~variant:`V900 ()));
Effects.transition `All;
])] [El.txt "Components"];
(* CTA Button *)
-
El.button ~at:[classes_attr (Tailwind.tw [
+
El.button ~at:[classes_attr (Tailwind.Css.tw [
Color.bg (Color.make `Blue ~variant:`V600 ());
Color.text Color.white;
Spacing.(to_class (px (Size.rem 1.0)));
···
(* Main Content *)
El.main [
(* Hero Section *)
-
El.section ~at:[At.id "hero"; classes_attr (Tailwind.tw [
+
El.section ~at:[At.id "hero"; classes_attr (Tailwind.Css.tw [
Layout.(to_class (min_height Size.screen));
Display.flex;
Flexbox.(to_class (align_items `Center));
···
Color.text Color.white;
])] [
El.div ~at:[At.class' "text-center container px-8"] [
-
El.h1 ~at:[classes_attr (Tailwind.tw [
+
El.h1 ~at:[classes_attr (Tailwind.Css.tw [
Typography.(to_class (font_size `Xl5));
Typography.(to_class (font_weight `Extrabold));
Spacing.(to_class (mb (Size.rem 1.5)));
])] [El.txt "Type-Safe Tailwind CSS"];
-
El.p ~at:[classes_attr (Tailwind.tw [
+
El.p ~at:[classes_attr (Tailwind.Css.tw [
Typography.(to_class (font_size `Xl));
Color.text (Color.make `Gray ~variant:`V100 ());
Spacing.(to_class (mb (Size.rem 2.0)));
···
El.pre ~at:[At.class' "text-sm overflow-x-auto"] [
El.code [El.txt {|open Tailwind
-
let button_classes = tw [
+
let button_classes = Css.tw [
Color.bg (Color.make `Blue ~variant:`V600 ());
Color.text Color.white;
Spacing.(to_class (px (Size.rem 1.0)));
+43 -43
examples/effects_and_variants_05.ml
···
];
El.body ~at:[At.class' "min-h-screen bg-gray-50 p-8"] [
El.div ~at:[At.class' "max-w-6xl mx-auto"] [
-
El.h1 ~at:[classes_attr (tw [
+
El.h1 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl2));
Typography.(to_class (font_weight `Bold));
Color.text (Color.make `Gray ~variant:`V800 ());
···
(* Shadow Effects *)
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Shadow Effects"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.grid;
Grid.(to_class (template_cols (`Cols 1)));
Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 3))))));
Spacing.(to_class (gap `All (Size.rem 1.5)));
])] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.5)));
Effects.shadow_sm;
Effects.rounded_lg;
]); At.class' "text-center"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-2"] [El.txt "Small Shadow"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Sm));
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "shadow-sm"];
];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.5)));
Effects.shadow_md;
Effects.rounded_lg;
]); At.class' "text-center"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-2"] [El.txt "Medium Shadow"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Sm));
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "shadow-md"];
];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.5)));
Effects.shadow_lg;
Effects.rounded_lg;
]); At.class' "text-center"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-2"] [El.txt "Large Shadow"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Sm));
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "shadow-lg"];
···
(* Rounded Corners *)
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Border Radius"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.flex;
Flexbox.(to_class (wrap `Wrap));
Spacing.(to_class (gap `All (Size.rem 1.0)));
Flexbox.(to_class (justify `Center));
])] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Blue ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.0)));
(* No rounded corners *)
]); At.class' "text-center"] [El.txt "No Radius"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Green ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_sm;
]); At.class' "text-center"] [El.txt "Small"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Purple ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_md;
]); At.class' "text-center"] [El.txt "Medium"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Red ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_lg;
]); At.class' "text-center"] [El.txt "Large"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Yellow ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_full;
···
(* Interactive Buttons *)
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Interactive Buttons"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.flex;
Flexbox.(to_class (wrap `Wrap));
Spacing.(to_class (gap `All (Size.rem 1.0)));
Flexbox.(to_class (justify `Center));
])] [
(* Hover color change *)
-
El.button ~at:[classes_attr (tw [
+
El.button ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Blue ~variant:`V500 ());
Color.text Color.white;
Spacing.(to_class (px (Size.rem 1.5)));
···
])] [El.txt "Hover Color"];
(* Hover shadow *)
-
El.button ~at:[classes_attr (tw [
+
El.button ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Green ~variant:`V500 ());
Color.text Color.white;
Spacing.(to_class (px (Size.rem 1.5)));
···
])] [El.txt "Hover Shadow"];
(* Scale effect *)
-
El.button ~at:[classes_attr (tw [
+
El.button ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Purple ~variant:`V500 ());
Color.text Color.white;
Spacing.(to_class (px (Size.rem 1.5)));
···
]); At.class' "hover:scale-105 active:scale-95"] [El.txt "Scale Effect"];
(* Focus ring *)
-
El.button ~at:[classes_attr (tw [
+
El.button ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Red ~variant:`V500 ());
Color.text Color.white;
Spacing.(to_class (px (Size.rem 1.5)));
···
(* Card Hover Effects *)
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Card Hover Effects"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.grid;
Grid.(to_class (template_cols (`Cols 1)));
Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2))))));
Spacing.(to_class (gap `All (Size.rem 1.5)));
])] [
(* Hover shadow card *)
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.5)));
Effects.rounded_lg;
···
Effects.transition `All;
Variants.hover Effects.shadow_lg;
]); At.class' "cursor-pointer"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V800 ());
]); At.class' "mb-2"] [El.txt "Shadow Lift"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "Hover to see the shadow increase. This creates a lifting effect."];
];
(* Scale and shadow card *)
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.5)));
Effects.rounded_lg;
Effects.shadow_md;
Effects.transition `All;
]); At.class' "cursor-pointer hover:scale-105 hover:shadow-xl"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V800 ());
]); At.class' "mb-2"] [El.txt "Scale + Shadow"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "This card both scales up and increases shadow on hover."];
];
···
(* Border Effects *)
El.section [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Border Effects"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.grid;
Grid.(to_class (template_cols (`Cols 1)));
Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 3))))));
Spacing.(to_class (gap `All (Size.rem 1.5)));
])] [
(* Regular border *)
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.5)));
Effects.border;
Color.border (Color.make `Gray ~variant:`V200 ());
Effects.rounded_lg;
]); At.class' "text-center"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-2"] [El.txt "Regular Border"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Sm));
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "border border-gray-200"];
];
(* Colored border *)
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.5)));
Effects.border;
Color.border (Color.make `Blue ~variant:`V300 ());
Effects.rounded_lg;
]); At.class' "text-center"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Blue ~variant:`V600 ());
]); At.class' "mb-2"] [El.txt "Colored Border"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Sm));
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "border border-blue-300"];
···
(* Thick border *)
El.div ~at:[At.class' "bg-white p-6 border-2 border-purple-300 rounded-lg text-center"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Purple ~variant:`V600 ());
]); At.class' "mb-2"] [El.txt "Thick Border"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Sm));
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "border-2 border-purple-300"];
+14 -14
examples/hello_tailwind_01.ml
···
open Tailwind
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
+
At.class' @@ Tailwind.to_string tailwind_classes
let create_page () =
-
let hello_classes = tw [
+
let hello_classes = Css.tw [
Color.text (Color.make `Blue ~variant:`V600 ());
Typography.(to_class (font_size `Xl2));
Typography.(to_class (font_weight `Bold));
Spacing.(to_class (mb (Size.rem 1.0)));
] in
-
let body_classes = tw [
+
let body_classes = Css.tw [
Layout.(to_class (min_height Size.screen));
Color.bg (Color.make `Gray ~variant:`V50 ());
Display.flex;
···
Spacing.(to_class (p (Size.rem 2.0)));
] in
-
let container_classes = tw [
+
let container_classes = Css.tw [
Spacing.(to_class (mx `Auto));
Typography.(to_class (text_align `Center));
Spacing.(to_class (px (Size.rem 1.0)));
] in
-
let paragraph_classes = tw [
+
let paragraph_classes = Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
Spacing.(to_class (mb (Size.rem 1.5)));
] in
-
let card_classes = tw [
+
let card_classes = Css.tw [
Color.bg Color.white;
Effects.rounded_lg;
Effects.shadow_sm;
···
Typography.(to_class (text_align `Left));
] in
-
let subheading_classes = tw [
+
let subheading_classes = Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V800 ());
Spacing.(to_class (mb (Size.rem 0.75)));
] in
-
let code_block_classes = tw [
+
let code_block_classes = Css.tw [
Color.bg (Color.make `Gray ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 0.75)));
Effects.rounded_sm;
···
Layout.(to_class (overflow `X `Auto));
] in
-
let code_classes = tw [
+
let code_classes = Css.tw [
Color.text (Color.make `Blue ~variant:`V600 ());
] in
-
let section_classes = tw [
+
let section_classes = Css.tw [
Spacing.(to_class (mt (Size.rem 2.0)));
Spacing.(to_class (gap `Y (Size.rem 1.0)));
] in
-
let list_classes = tw [
+
let list_classes = Css.tw [
Typography.(to_class (text_align `Left));
Spacing.(to_class (gap `Y (Size.rem 0.5)));
Color.text (Color.make `Gray ~variant:`V600 ());
] in
-
let list_item_classes = tw [
+
let list_item_classes = Css.tw [
Display.flex;
Flexbox.(to_class (align_items `Start));
] in
-
let checkmark_classes = tw [
+
let checkmark_classes = Css.tw [
Color.text (Color.make `Green ~variant:`V500 ());
Spacing.(to_class (mr (Size.rem 0.5)));
] in
···
let () =
(* Output HTML to stdout *)
let html = create_page () in
-
print_string (El.to_string ~doctype:true html)
+
print_string (El.to_string ~doctype:true html)
+12 -12
examples/index_html_generator.ml
···
]
let create_index_page () =
-
let page_classes = tw [
+
let page_classes = Css.tw [
Layout.(to_class (min_height Size.screen));
Color.bg (Color.make `Gray ~variant:`V50 ());
] in
-
let container_classes = tw [
+
let container_classes = Css.tw [
Spacing.(to_class (mx `Auto));
Spacing.(to_class (p (Size.rem 2.0)));
] in
-
let header_classes = tw [
+
let header_classes = Css.tw [
Typography.(to_class (font_size `Xl4));
Typography.(to_class (font_weight `Bold));
Color.text (Color.make `Gray ~variant:`V900 ());
···
Typography.(to_class (text_align `Center));
] in
-
let subtitle_classes = tw [
+
let subtitle_classes = Css.tw [
Typography.(to_class (font_size `Xl));
Color.text (Color.make `Gray ~variant:`V600 ());
Typography.(to_class (text_align `Center));
Spacing.(to_class (mb (Size.rem 3.0)));
] in
-
let grid_classes = tw [
+
let grid_classes = Css.tw [
Display.grid;
Grid.(to_class (template_cols (`Cols 1)));
Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2))))));
···
Spacing.(to_class (mb (Size.rem 3.0)));
] in
-
let card_classes = tw [
+
let card_classes = Css.tw [
Color.bg Color.white;
Effects.rounded_lg;
Effects.shadow_sm;
···
Variants.hover (Color.border (Color.make `Blue ~variant:`V300 ()));
] in
-
let card_title_classes = tw [
+
let card_title_classes = Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V900 ());
Spacing.(to_class (mb (Size.rem 0.75)));
] in
-
let card_description_classes = tw [
+
let card_description_classes = Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
Spacing.(to_class (mb (Size.rem 1.0)));
Typography.(to_class (line_height `Relaxed));
] in
-
let features_classes = tw [
+
let features_classes = Css.tw [
Display.flex;
Flexbox.(to_class (wrap `Wrap));
Spacing.(to_class (gap `All (Size.rem 0.5)));
Spacing.(to_class (mb (Size.rem 1.0)));
] in
-
let feature_tag_classes = tw [
+
let feature_tag_classes = Css.tw [
Color.bg (Color.make `Blue ~variant:`V50 ());
Color.text (Color.make `Blue ~variant:`V700 ());
Typography.(to_class (font_size `Xs));
···
Effects.rounded_full;
] in
-
let link_classes = tw [
+
let link_classes = Css.tw [
Color.text (Color.make `Blue ~variant:`V600 ());
Typography.(to_class (font_weight `Medium));
Variants.hover (Color.text (Color.make `Blue ~variant:`V800 ()));
Effects.transition `Colors;
] in
-
let footer_classes = tw [
+
let footer_classes = Css.tw [
Typography.(to_class (text_align `Center));
Spacing.(to_class (mt (Size.rem 3.0)));
Color.text (Color.make `Gray ~variant:`V500 ());
+31 -31
examples/layout_and_spacing_03.ml
···
];
El.body ~at:[At.class' "min-h-screen bg-gray-50 p-8"] [
El.div ~at:[At.class' "max-w-6xl mx-auto"] [
-
El.h1 ~at:[classes_attr (tw [
+
El.h1 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl2));
Typography.(to_class (font_weight `Bold));
Color.text (Color.make `Gray ~variant:`V800 ());
]); At.class' "mb-8 text-center"] [El.txt "Layout and Spacing Demo"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Color.text (Color.make `Gray ~variant:`V600 ());
]); At.class' "text-center mb-12"] [
···
(* Flexbox Examples *)
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
···
(* Centered content *)
El.div ~at:[At.class' "mb-8"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-4"] [El.txt "Centered Content"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.flex;
Flexbox.(to_class (justify `Center));
Flexbox.(to_class (align_items `Center));
···
Layout.(to_class (height (Size.rem 8.0)));
Effects.rounded_lg;
])] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.5)));
Effects.rounded_md;
···
(* Space between items *)
El.div ~at:[At.class' "mb-8"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-4"] [El.txt "Space Between"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.flex;
Flexbox.(to_class (justify `Between));
Flexbox.(to_class (align_items `Center));
···
Spacing.(to_class (p (Size.rem 1.5)));
Effects.rounded_lg;
])] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_md;
])] [El.txt "Left"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_md;
])] [El.txt "Center"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_md;
···
(* Flex direction example *)
El.div [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-4"] [El.txt "Flex Direction Column"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.flex;
Flexbox.(to_class (direction `Col));
Spacing.(to_class (gap `All (Size.rem 1.0)));
···
Spacing.(to_class (p (Size.rem 1.5)));
Effects.rounded_lg;
])] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_md;
]); At.class' "text-center"] [El.txt "Item 1"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_md;
]); At.class' "text-center"] [El.txt "Item 2"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_md;
···
(* Grid Examples *)
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
···
(* 2-column grid *)
El.div ~at:[At.class' "mb-8"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-4"] [El.txt "Two Column Grid"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.grid;
Grid.(to_class (template_cols (`Cols 2)));
Spacing.(to_class (gap `All (Size.rem 1.5)));
])] (List.init 4 (fun i ->
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Red ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.5)));
Effects.rounded_lg;
···
(* 3-column grid *)
El.div ~at:[At.class' "mb-8"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-4"] [El.txt "Three Column Grid"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.grid;
Grid.(to_class (template_cols (`Cols 3)));
Spacing.(to_class (gap `All (Size.rem 1.5)));
])] (List.init 6 (fun i ->
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Yellow ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.5)));
Effects.rounded_lg;
···
(* Spacing Examples *)
El.section [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-8"] [El.txt "Spacing System"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.grid;
Grid.(to_class (template_cols (`Cols 1)));
Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2))))));
Spacing.(to_class (gap `All (Size.rem 2.0)));
])] [
(* Padding example *)
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Indigo ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.5)));
Effects.rounded_lg;
])] [
-
El.h4 ~at:[classes_attr (tw [
+
El.h4 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Base));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-3"] [El.txt "Padding Example"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 2.0)));
Effects.rounded_md;
···
];
(* Margin example *)
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Cyan ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.5)));
Effects.rounded_lg;
])] [
-
El.h4 ~at:[classes_attr (tw [
+
El.h4 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Base));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-3"] [El.txt "Margin Example"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.0)));
Spacing.(to_class (m (Size.rem 1.5)));
+27 -27
examples/patterns_and_components_06.ml
···
];
El.body ~at:[At.class' "min-h-screen bg-gray-50 p-8"] [
El.div ~at:[At.class' "max-w-6xl mx-auto"] [
-
El.h1 ~at:[classes_attr (tw [
+
El.h1 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl2));
Typography.(to_class (font_weight `Bold));
Color.text (Color.make `Gray ~variant:`V800 ());
···
(* Container Pattern *)
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Container Pattern"];
-
El.div ~at:[classes_attr (tw [Patterns.container ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [
-
El.p ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [Patterns.container ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [
+
El.p ~at:[classes_attr (Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "This content is inside a container pattern that centers content and provides responsive padding."];
];
···
(* Card Pattern *)
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Card Pattern"];
El.div ~at:[At.class' "grid grid-cols-1 md:grid-cols-3 gap-6"] [
-
El.div ~at:[classes_attr (tw [Patterns.card]); At.class' "p-6"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [Patterns.card]); At.class' "p-6"] [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V800 ());
]); At.class' "mb-2"] [El.txt "Card One"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "This is a card using the built-in card pattern."];
];
-
El.div ~at:[classes_attr (tw [Patterns.card]); At.class' "p-6"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [Patterns.card]); At.class' "p-6"] [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V800 ());
]); At.class' "mb-2"] [El.txt "Card Two"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "Another card with the same styling pattern applied."];
];
-
El.div ~at:[classes_attr (tw [Patterns.card]); At.class' "p-6"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [Patterns.card]); At.class' "p-6"] [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V800 ());
]); At.class' "mb-2"] [El.txt "Card Three"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
])] [El.txt "A third card demonstrating consistent styling."];
];
···
(* Flex Center Pattern *)
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Flex Center Pattern"];
-
El.div ~at:[classes_attr (tw [Patterns.flex_center]); At.class' "bg-blue-50 rounded-lg h-32"] [
-
El.p ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [Patterns.flex_center]); At.class' "bg-blue-50 rounded-lg h-32"] [
+
El.p ~at:[classes_attr (Css.tw [
Color.text (Color.make `Blue ~variant:`V600 ());
Typography.(to_class (font_weight `Medium));
])] [El.txt "This content is perfectly centered using flex_center pattern"];
···
(* Stack Pattern *)
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Stack Pattern"];
-
El.div ~at:[classes_attr (tw [Patterns.stack ~gap:(Size.rem 1.0) ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [Patterns.stack ~gap:(Size.rem 1.0) ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Green ~variant:`V50 ());
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_md;
])] [El.txt "Stack Item 1"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Blue ~variant:`V50 ());
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_md;
])] [El.txt "Stack Item 2"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Purple ~variant:`V50 ());
Spacing.(to_class (p (Size.rem 1.0)));
Effects.rounded_md;
···
(* Inline Stack Pattern *)
El.section [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Inline Stack Pattern"];
-
El.div ~at:[classes_attr (tw [Patterns.inline_stack ~gap:(Size.rem 1.0) ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [
-
El.span ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [Patterns.inline_stack ~gap:(Size.rem 1.0) ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [
+
El.span ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Red ~variant:`V50 ());
Color.text (Color.make `Red ~variant:`V600 ());
Spacing.(to_class (px (Size.rem 0.75)));
···
Typography.(to_class (font_size `Sm));
])] [El.txt "Tag 1"];
-
El.span ~at:[classes_attr (tw [
+
El.span ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Yellow ~variant:`V50 ());
Color.text (Color.make `Yellow ~variant:`V600 ());
Spacing.(to_class (px (Size.rem 0.75)));
···
Typography.(to_class (font_size `Sm));
])] [El.txt "Tag 2"];
-
El.span ~at:[classes_attr (tw [
+
El.span ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Indigo ~variant:`V50 ());
Color.text (Color.make `Indigo ~variant:`V600 ());
Spacing.(to_class (px (Size.rem 0.75)));
+18 -18
examples/responsive_design_04.ml
···
];
El.body ~at:[At.class' "min-h-screen bg-gray-50 p-8"] [
El.div ~at:[At.class' "max-w-6xl mx-auto"] [
-
El.h1 ~at:[classes_attr (tw [
+
El.h1 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl2));
Responsive.(to_class (at_breakpoint `Md (Typography.(to_class (font_size `Xl3)))));
Typography.(to_class (font_weight `Bold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-8 text-center"] [El.txt "Responsive Design Demo"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Lg));
Color.text (Color.make `Gray ~variant:`V600 ());
]); At.class' "text-center mb-8"] [
···
(* Responsive Grid *)
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Responsive Grid"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Color.text (Color.make `Gray ~variant:`V600 ());
]); At.class' "mb-4"] [
El.txt "1 column → 2 columns (md) → 3 columns (lg) → 4 columns (xl)"
];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.grid;
Grid.(to_class (template_cols (`Cols 1)));
Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2))))));
···
Color.make `Red ~variant:`V100 ();
Color.make `Yellow ~variant:`V100 ();
|] in
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg colors.(i mod (Array.length colors));
Spacing.(to_class (p (Size.rem 1.5)));
]); At.class' "rounded-lg text-center"] [
···
(* Responsive Typography *)
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Responsive Typography"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Gray ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.5)));
]); At.class' "rounded-lg text-center"] [
-
El.h3 ~at:[classes_attr (tw [
+
El.h3 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Base));
Responsive.(to_class (at_breakpoint `Md (Typography.(to_class (font_size `Lg)))));
Responsive.(to_class (at_breakpoint `Lg (Typography.(to_class (font_size `Xl2)))));
···
Color.text (Color.make `Blue ~variant:`V600 ());
]); At.class' "mb-4"] [El.txt "Responsive Heading"];
-
El.p ~at:[classes_attr (tw [
+
El.p ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Sm));
Responsive.(to_class (at_breakpoint `Md (Typography.(to_class (font_size `Base)))));
Color.text (Color.make `Gray ~variant:`V600 ());
···
(* Show/Hide Elements *)
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Responsive Visibility"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Display.flex;
Flexbox.(to_class (direction `Col));
Responsive.(to_class (at_breakpoint `Md (Flexbox.(to_class (direction `Row)))));
Spacing.(to_class (gap `All (Size.rem 1.0)));
])] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Blue ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.5)));
]); At.class' "rounded-lg text-center"] [
El.txt "Always visible"
];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Green ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.5)));
Display.hidden;
···
El.txt "Hidden on mobile, visible on md+"
];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Purple ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.5)));
Display.hidden;
···
(* Responsive Spacing *)
El.section [
-
El.h2 ~at:[classes_attr (tw [
+
El.h2 ~at:[classes_attr (Css.tw [
Typography.(to_class (font_size `Xl));
Typography.(to_class (font_weight `Semibold));
Color.text (Color.make `Gray ~variant:`V700 ());
]); At.class' "mb-6"] [El.txt "Responsive Spacing"];
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg (Color.make `Gray ~variant:`V100 ());
Spacing.(to_class (p (Size.rem 1.0)));
Responsive.(to_class (at_breakpoint `Md (Spacing.(to_class (p (Size.rem 1.5))))));
Responsive.(to_class (at_breakpoint `Lg (Spacing.(to_class (p (Size.rem 2.0))))));
]); At.class' "rounded-lg"] [
-
El.div ~at:[classes_attr (tw [
+
El.div ~at:[classes_attr (Css.tw [
Color.bg Color.white;
Spacing.(to_class (p (Size.rem 1.0)));
]); At.class' "rounded"] [
+14 -14
lib/tailwind-html/button.ml
···
let classes_attr tailwind_classes =
At.class' (Tailwind.to_string tailwind_classes)
-
let base_button_classes = Tailwind.tw [
+
let base_button_classes = Tailwind.Css.tw [
Tailwind.Display.inline_flex;
Tailwind.Flexbox.(to_class (align_items `Center));
Tailwind.Flexbox.(to_class (justify `Center));
···
]
let variant_classes = function
-
| `Primary -> Tailwind.tw [
+
| `Primary -> Tailwind.Css.tw [
Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V600 ());
Tailwind.Color.text Tailwind.Color.white;
Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V700 ()));
]
-
| `Secondary -> Tailwind.tw [
+
| `Secondary -> Tailwind.Css.tw [
Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V200 ());
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V900 ());
Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V300 ()));
]
-
| `Outline -> Tailwind.tw [
+
| `Outline -> Tailwind.Css.tw [
Tailwind.Effects.border;
Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V300 ());
Tailwind.Color.bg Tailwind.Color.transparent;
Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V100 ()));
]
-
| `Ghost -> Tailwind.tw [
+
| `Ghost -> Tailwind.Css.tw [
Tailwind.Color.bg Tailwind.Color.transparent;
Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V100 ()));
]
-
| `Link -> Tailwind.tw [
+
| `Link -> Tailwind.Css.tw [
Tailwind.Color.bg Tailwind.Color.transparent;
Tailwind.Color.text (Tailwind.Color.make `Blue ~variant:`V600 ());
Tailwind.Css.make "underline-offset-4";
···
]
let size_classes = function
-
| `Default -> Tailwind.tw [
+
| `Default -> Tailwind.Css.tw [
Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 1.0)));
Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 0.5)));
]
-
| `Sm -> Tailwind.tw [
+
| `Sm -> Tailwind.Css.tw [
Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 0.75)));
Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 0.375)));
]
-
| `Lg -> Tailwind.tw [
+
| `Lg -> Tailwind.Css.tw [
Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 2.0)));
Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 0.75)));
]
-
| `Icon -> Tailwind.tw [
+
| `Icon -> Tailwind.Css.tw [
Tailwind.Layout.(to_class (width (Tailwind.Size.rem 2.5)));
Tailwind.Layout.(to_class (height (Tailwind.Size.rem 2.5)));
]
let state_classes = function
| `Default -> Tailwind.Css.empty
-
| `Loading -> Tailwind.tw [
+
| `Loading -> Tailwind.Css.tw [
Tailwind.Css.make "cursor-not-allowed";
Tailwind.Effects.(to_class (opacity 75));
]
-
| `Disabled -> Tailwind.tw [
+
| `Disabled -> Tailwind.Css.tw [
Tailwind.Css.make "cursor-not-allowed";
Tailwind.Effects.(to_class (opacity 50));
]
···
}
let to_html button =
-
let button_classes = Tailwind.tw [
+
let button_classes = Tailwind.Css.tw [
base_button_classes;
variant_classes button.variant;
size_classes button.size;
···
let all_attrs = base_attrs @ state_attrs @ custom_attrs in
let loading_spinner = match button.state with
-
| `Loading -> [El.span ~at:[classes_attr (Tailwind.tw [
+
| `Loading -> [El.span ~at:[classes_attr (Tailwind.Css.tw [
Tailwind.Css.make "animate-spin";
Tailwind.Spacing.(to_class (mr (Tailwind.Size.rem 0.5)));
])] [El.txt "⟳"]]
+14 -14
lib/tailwind-html/card.ml
···
let classes_attr tailwind_classes =
At.class' (Tailwind.to_string tailwind_classes)
-
let base_card_classes = Tailwind.tw [
+
let base_card_classes = Tailwind.Css.tw [
Tailwind.Effects.rounded_lg;
Tailwind.Color.bg Tailwind.Color.white;
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V900 ());
]
let variant_classes = function
-
| Default -> Tailwind.tw [
+
| Default -> Tailwind.Css.tw [
Tailwind.Effects.border;
Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V200 ());
Tailwind.Effects.shadow_sm;
]
-
| Outlined -> Tailwind.tw [
+
| Outlined -> Tailwind.Css.tw [
Tailwind.Effects.border_2;
Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V300 ());
]
-
| Elevated -> Tailwind.tw [
+
| Elevated -> Tailwind.Css.tw [
Tailwind.Effects.shadow_lg;
Tailwind.Effects.border;
Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V200 ());
]
-
| Flat -> Tailwind.tw [
+
| Flat -> Tailwind.Css.tw [
Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V50 ());
]
···
}
let to_html card =
-
let card_classes = Tailwind.tw [
+
let card_classes = Tailwind.Css.tw [
base_card_classes;
variant_classes card.variant;
(if card.padding then Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5))) else Tailwind.Css.empty);
(if card.hoverable then Tailwind.Variants.hover (Tailwind.Effects.shadow_md) else Tailwind.Css.empty);
-
(if card.clickable then Tailwind.tw [
+
(if card.clickable then Tailwind.Css.tw [
Tailwind.Css.make "cursor-pointer";
Tailwind.Variants.hover (Tailwind.Effects.shadow_md);
] else Tailwind.Css.empty);
···
(** Card header section *)
let header ?classes ?title ?subtitle ?actions ~children () =
-
let header_classes = Tailwind.tw [
+
let header_classes = Tailwind.Css.tw [
Tailwind.Display.flex;
Tailwind.Flexbox.(to_class (direction `Col));
Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5)));
···
] in
let title_element = match title with
-
| Some t -> Some (El.h3 ~at:[classes_attr (Tailwind.tw [
+
| Some t -> Some (El.h3 ~at:[classes_attr (Tailwind.Css.tw [
Tailwind.Typography.(to_class (font_size `Lg));
Tailwind.Typography.(to_class (font_weight `Semibold));
Tailwind.Spacing.(to_class (mb (Tailwind.Size.rem 0.5)));
···
in
let subtitle_element = match subtitle with
-
| Some s -> Some (El.p ~at:[classes_attr (Tailwind.tw [
+
| Some s -> Some (El.p ~at:[classes_attr (Tailwind.Css.tw [
Tailwind.Typography.(to_class (font_size `Sm));
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V600 ());
])] [El.txt s])
···
(** Card body section *)
let body ?classes ~children () =
-
let body_classes = Tailwind.tw [
+
let body_classes = Tailwind.Css.tw [
Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5)));
Tailwind.Spacing.(to_class (pt (Tailwind.Size.zero)));
(match classes with Some c -> c | None -> Tailwind.Css.empty);
···
(** Card footer section *)
let footer ?classes ?actions ~children () =
-
let footer_classes = Tailwind.tw [
+
let footer_classes = Tailwind.Css.tw [
Tailwind.Display.flex;
Tailwind.Flexbox.(to_class (align_items `Center));
Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5)));
···
(** Card image section *)
let image ?classes ?alt ?(cover=true) ~src () =
-
let img_classes = Tailwind.tw [
+
let img_classes = Tailwind.Css.tw [
Tailwind.Layout.w_full;
Tailwind.Layout.(to_class (height (Tailwind.Size.rem 12.0)));
(if cover then Tailwind.Layout.(to_class (object_fit `Cover)) else Tailwind.Css.empty);
···
| None -> []
in
-
let grid_classes = Tailwind.tw (base_classes @ col_classes @ gap_classes @
+
let grid_classes = Tailwind.Css.tw (base_classes @ col_classes @ gap_classes @
(match classes with Some c -> [c] | None -> [])) in
let card_elements = List.map to_html cards in
+1 -1
lib/tailwind-html/component.ml
···
(* Add classes to a component *)
let add_classes new_classes comp = {
comp with classes = match comp.classes with
-
| Some existing -> Some (Tailwind.tw [existing; new_classes])
+
| Some existing -> Some (Tailwind.Css.tw [existing; new_classes])
| None -> Some new_classes
}
+7 -7
lib/tailwind-html/form.ml
···
let classes_attr tailwind_classes =
At.class' (Tailwind.to_string tailwind_classes)
-
let base_input_classes = Tailwind.tw [
+
let base_input_classes = Tailwind.Css.tw [
Tailwind.Display.flex;
Tailwind.Layout.(to_class (height (Tailwind.Size.rem 2.5)));
Tailwind.Layout.w_full;
···
]
let validation_classes = function
-
| Some Valid -> Tailwind.tw [
+
| Some Valid -> Tailwind.Css.tw [
Tailwind.Color.border (Tailwind.Color.make `Green ~variant:`V500 ());
Tailwind.Variants.focus (Tailwind.Color.border (Tailwind.Color.make `Green ~variant:`V600 ()));
]
-
| Some Invalid -> Tailwind.tw [
+
| Some Invalid -> Tailwind.Css.tw [
Tailwind.Color.border (Tailwind.Color.make `Red ~variant:`V500 ());
Tailwind.Variants.focus (Tailwind.Color.border (Tailwind.Color.make `Red ~variant:`V600 ()));
]
-
| Some Warning -> Tailwind.tw [
+
| Some Warning -> Tailwind.Css.tw [
Tailwind.Color.border (Tailwind.Color.make `Yellow ~variant:`V500 ());
Tailwind.Variants.focus (Tailwind.Color.border (Tailwind.Color.make `Yellow ~variant:`V600 ()));
]
···
| Datetime_local -> "datetime-local"
let to_html field =
-
let field_classes = Tailwind.tw [
+
let field_classes = Tailwind.Css.tw [
base_input_classes;
validation_classes field.validation;
(match field.classes with Some c -> c | None -> Tailwind.Css.empty);
···
| None -> input_element
let group ?classes ~fields () =
-
let group_classes = Tailwind.tw [
+
let group_classes = Tailwind.Css.tw [
Tailwind.Display.grid;
Tailwind.Layout.w_full;
Tailwind.Spacing.(to_class (gap `All (Tailwind.Size.rem 1.0)));
···
El.div ~at:[classes_attr group_classes] field_elements
let form ?action ?method_ ?classes ?attributes ~fields ?submit () =
-
let form_classes = Tailwind.tw [
+
let form_classes = Tailwind.Css.tw [
Tailwind.Display.grid;
Tailwind.Layout.w_full;
Tailwind.Spacing.(to_class (gap `All (Tailwind.Size.rem 1.5)));
+12 -12
lib/tailwind-html/layout.ml
···
let size_class = container_size_to_class size in
let center_class = if center then Tailwind.Css.make "mx-auto" else Tailwind.Css.empty in
let padding_class = if padding then Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 1.0))) else Tailwind.Css.empty in
-
Tailwind.tw [size_class; center_class; padding_class]
+
Tailwind.Css.tw [size_class; center_class; padding_class]
| Flex (direction, justify, align, wrap, gap) ->
let dir_classes = match direction with Some d -> [Tailwind.Flexbox.(to_class (direction d))] | None -> [] in
···
let align_classes = match align with Some a -> [Tailwind.Flexbox.(to_class (align_items a))] | None -> [] in
let wrap_classes = match wrap with Some w -> [Tailwind.Flexbox.(to_class (wrap w))] | None -> [] in
let gap_classes = match gap with Some g -> [Tailwind.Spacing.(to_class (gap `All g))] | None -> [] in
-
Tailwind.tw ([Tailwind.Display.flex] @ dir_classes @ justify_classes @ align_classes @ wrap_classes @ gap_classes)
+
Tailwind.Css.tw ([Tailwind.Display.flex] @ dir_classes @ justify_classes @ align_classes @ wrap_classes @ gap_classes)
| Grid (cols, rows, gap, gap_x, gap_y, _flow) ->
let col_classes = match cols with Some c -> [Tailwind.Grid.(to_class (template_cols c))] | None -> [] in
···
let gap_x_classes = match gap_x with Some g -> [Tailwind.Spacing.(to_class (gap `X g))] | None -> [] in
let gap_y_classes = match gap_y with Some g -> [Tailwind.Spacing.(to_class (gap `Y g))] | None -> [] in
let flow_classes = [] in
-
Tailwind.tw ([Tailwind.Display.grid] @ col_classes @ row_classes @ gap_classes @ gap_x_classes @ gap_y_classes @ flow_classes)
+
Tailwind.Css.tw ([Tailwind.Display.grid] @ col_classes @ row_classes @ gap_classes @ gap_x_classes @ gap_y_classes @ flow_classes)
| Stack (gap, align) ->
let gap_classes = match gap with Some g -> [Tailwind.Spacing.(to_class (gap `All g))] | None -> [] in
let align_classes = match align with Some a -> [Tailwind.Flexbox.(to_class (align_items a))] | None -> [] in
-
Tailwind.tw ([Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Col))] @ gap_classes @ align_classes)
+
Tailwind.Css.tw ([Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Col))] @ gap_classes @ align_classes)
| Row (gap, justify, align, wrap) ->
let gap_classes = match gap with Some g -> [Tailwind.Spacing.(to_class (gap `All g))] | None -> [] in
let justify_classes = match justify with Some j -> [Tailwind.Flexbox.(to_class (justify j))] | None -> [] in
let align_classes = match align with Some a -> [Tailwind.Flexbox.(to_class (align_items a))] | None -> [] in
let wrap_classes = match wrap with Some true -> [Tailwind.Flexbox.(to_class (wrap `Wrap))] | Some false -> [Tailwind.Flexbox.(to_class (wrap `Nowrap))] | None -> [] in
-
Tailwind.tw ([Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Row))] @ gap_classes @ justify_classes @ align_classes @ wrap_classes)
+
Tailwind.Css.tw ([Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Row))] @ gap_classes @ justify_classes @ align_classes @ wrap_classes)
| Sidebar (_side, _width, _collapsible, _sidebar_content, _main_content) ->
-
Tailwind.tw [Tailwind.Display.flex]
+
Tailwind.Css.tw [Tailwind.Display.flex]
| Page (_header, _footer, _sidebar, _main) ->
-
Tailwind.tw [Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Col)); Tailwind.Layout.h_screen]
+
Tailwind.Css.tw [Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Col)); Tailwind.Layout.h_screen]
in
-
let final_classes = Tailwind.tw [
+
let final_classes = Tailwind.Css.tw [
base_classes;
(match layout.classes with Some c -> c | None -> Tailwind.Css.empty);
] in
···
match layout.layout_type with
| Sidebar (_side, width, _collapsible, sidebar_content, main_content) ->
let sidebar_width = match width with Some w -> w | None -> Tailwind.Size.rem 16.0 in
-
let sidebar_classes = Tailwind.tw [
+
let sidebar_classes = Tailwind.Css.tw [
Tailwind.Layout.(to_class (width sidebar_width));
Tailwind.Flexbox.(to_class (shrink (Some 0)));
Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V50 ());
] in
-
let main_classes = Tailwind.tw [
+
let main_classes = Tailwind.Css.tw [
Tailwind.Flexbox.(to_class (grow (Some 1)));
Tailwind.Layout.(to_class (overflow `All `Auto));
] in
···
| Some s -> Tailwind.Layout.(to_class (height s))
| None -> Tailwind.Layout.(to_class (height (Tailwind.Size.rem 1.0)))
in
-
El.div ~at:[classes_attr (Tailwind.tw [size_class])] []
+
El.div ~at:[classes_attr (Tailwind.Css.tw [size_class])] []
let divider ?orientation ?classes () =
let base_classes = match orientation with
···
Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V300 ());
]
in
-
let divider_classes = Tailwind.tw (base_classes @
+
let divider_classes = Tailwind.Css.tw (base_classes @
(match classes with Some c -> [c] | None -> [])) in
El.div ~at:[classes_attr divider_classes] []
+2 -2
lib/tailwind-html/tailwind_html.ml
···
let weight_styles = match weight with Some w -> [Tailwind.Typography.(to_class (font_weight w))] | None -> [] in
let color_styles = match color with Some c -> [Tailwind.Color.text c] | None -> [] in
let align_styles = match align with Some a -> [Tailwind.Typography.(to_class (text_align a))] | None -> [] in
-
let text_classes = Tailwind.tw (base_styles @ size_styles @ weight_styles @ color_styles @ align_styles) in
+
let text_classes = Tailwind.Css.tw (base_styles @ size_styles @ weight_styles @ color_styles @ align_styles) in
let final_classes = match classes with
-
| Some c -> Tailwind.tw [text_classes; c]
+
| Some c -> Tailwind.Css.tw [text_classes; c]
| None -> text_classes
in
span ~classes:final_classes [Htmlit.El.txt text_content]
+3 -1
lib/tailwind/css.ml
···
| [] -> true
| _ -> false
-
let of_strings ss = ss
+
let of_strings ss = ss
+
+
let tw = concat
+4 -1
lib/tailwind/css.mli
···
val is_empty : t -> bool
(** Create CSS classes from a list of strings *)
-
val of_strings : string list -> t
+
val of_strings : string list -> t
+
+
(** Combine multiple CSS classes (alias for concat) *)
+
val tw : t list -> t
+30
lib/tailwind/effects.ml
···
| `Out -> "ease-out"
| `In_out -> "ease-in-out"
in
+
Css.make class_name
+
+
(* Text shadow utilities *)
+
let text_shadow shadow_size =
+
let class_name = match shadow_size with
+
| `None -> "text-shadow-none"
+
| `Sm -> "text-shadow-sm"
+
| `Base -> "text-shadow"
+
| `Lg -> "text-shadow-lg"
+
| `Xl -> "text-shadow-xl"
+
in
+
Css.make class_name
+
+
(* Mask utilities *)
+
let mask mask_type =
+
let class_name = match mask_type with
+
| `Auto -> "mask-auto"
+
| `Cover -> "mask-cover"
+
| `Contain -> "mask-contain"
+
in
+
Css.make class_name
+
+
(* 3D perspective *)
+
let perspective perspective_type =
+
let class_name = match perspective_type with
+
| `None -> "perspective-none"
+
| `Distant -> "perspective-distant"
+
| `Normal -> "perspective-normal"
+
| `Near -> "perspective-near"
+
in
Css.make class_name
+10 -1
lib/tailwind/effects.mli
···
val duration : int -> Css.t
(** Ease timing functions *)
-
val ease : timing_function -> Css.t
+
val ease : timing_function -> Css.t
+
+
(** Text shadow utilities *)
+
val text_shadow : [`None | `Sm | `Base | `Lg | `Xl] -> Css.t
+
+
(** Mask utilities *)
+
val mask : [`Auto | `Cover | `Contain] -> Css.t
+
+
(** 3D perspective *)
+
val perspective : [`None | `Distant | `Normal | `Near] -> Css.t
+20 -1
lib/tailwind/layout.ml
···
let h_full = Css.make "h-full"
let h_screen = Css.make "h-screen"
let h_auto = Css.make "h-auto"
-
let h_fit = Css.make "h-fit"
+
let h_fit = Css.make "h-fit"
+
+
(* Accessibility utilities *)
+
let sr_only = Css.make "sr-only"
+
+
let focus_ring ?color ?width () =
+
let base_classes = [
+
Css.make "focus:outline-none";
+
Css.make "focus:ring-2";
+
Css.make "focus:ring-offset-2";
+
] in
+
let color_class = match color with
+
| Some c -> [Color.ring c]
+
| None -> [Css.make "focus:ring-blue-500"]
+
in
+
let width_class = match width with
+
| Some _ -> [] (* Could implement width variations *)
+
| None -> []
+
in
+
Css.concat (base_classes @ color_class @ width_class)
+8
lib/tailwind/layout.mli
···
(** Convert to CSS class *)
val to_class : t -> Css.t
+
(** Accessibility utilities *)
+
+
(** Screen reader only (visually hidden but accessible) *)
+
val sr_only : Css.t
+
+
(** Focus ring utility *)
+
val focus_ring : ?color:Color.t -> ?width:Effects.border_width -> unit -> Css.t
+
(** Common width utilities *)
val w_full : Css.t
val w_screen : Css.t
-90
lib/tailwind/tailwind.ml
···
type t = Css.t
-
(* Module aliases *)
module Css = Css
module Color = Color
module Size = Size
···
module Reset = Reset
module Patterns = Patterns
-
(* Convenience aliases *)
-
module C = Color
-
module S = Spacing
-
module E = Effects
-
module T = Typography
-
module F = Flexbox
-
module G = Grid
-
module P = Patterns
-
module R = Reset
-
-
let tw classes = Css.concat classes
-
-
let class_list pairs =
-
List.fold_left (fun acc (classes, condition) ->
-
if condition then Css.combine acc classes else acc
-
) Css.empty pairs
-
let to_string = Css.to_string
-
-
(* Core utility functions *)
-
-
let sr_only =
-
tw [
-
Css.make "sr-only";
-
]
-
-
let focus_ring ?color ?width () =
-
let base_classes = [
-
Css.make "focus:outline-none";
-
Css.make "focus:ring-2";
-
Css.make "focus:ring-offset-2";
-
] in
-
let color_class = match color with
-
| Some c -> [Color.ring c]
-
| None -> [Css.make "focus:ring-blue-500"]
-
in
-
let width_class = match width with
-
| Some _ -> [] (* Could implement width variations *)
-
| None -> []
-
in
-
tw (base_classes @ color_class @ width_class)
-
-
-
module V4 = struct
-
let container_query size classes =
-
let container_class = match size with
-
| `Xs -> "@xs:"
-
| `Sm -> "@sm:"
-
| `Md -> "@md:"
-
| `Lg -> "@lg:"
-
| `Xl -> "@xl:"
-
| `Xl2 -> "@2xl:"
-
| `Xl3 -> "@3xl:"
-
| `Xl4 -> "@4xl:"
-
| `Xl5 -> "@5xl:"
-
| `Xl6 -> "@6xl:"
-
| `Xl7 -> "@7xl:"
-
in
-
Css.make (container_class ^ Css.to_string classes)
-
-
let starting_style classes =
-
Css.make ("@starting-style " ^ Css.to_string classes)
-
-
let text_shadow shadow_size =
-
let class_name = match shadow_size with
-
| `None -> "text-shadow-none"
-
| `Sm -> "text-shadow-sm"
-
| `Base -> "text-shadow"
-
| `Lg -> "text-shadow-lg"
-
| `Xl -> "text-shadow-xl"
-
in
-
Css.make class_name
-
-
let mask mask_type =
-
let class_name = match mask_type with
-
| `Auto -> "mask-auto"
-
| `Cover -> "mask-cover"
-
| `Contain -> "mask-contain"
-
in
-
Css.make class_name
-
-
let perspective perspective_type =
-
let class_name = match perspective_type with
-
| `None -> "perspective-none"
-
| `Distant -> "perspective-distant"
-
| `Normal -> "perspective-normal"
-
| `Near -> "perspective-near"
-
in
-
Css.make class_name
-
end
-41
lib/tailwind/tailwind.mli
···
module Reset = Reset
module Patterns = Patterns
-
(** Convenience aliases for shorter imports *)
-
module C = Color
-
module S = Spacing
-
module E = Effects
-
module T = Typography
-
module F = Flexbox
-
module G = Grid
-
module P = Patterns
-
module R = Reset
-
-
(** Combine multiple CSS classes *)
-
val tw : Css.t list -> Css.t
-
-
(** Conditionally include classes *)
-
val class_list : (Css.t * bool) list -> Css.t
-
(** Convert CSS classes to string *)
val to_string : t -> string
-
(** Core utility functions *)
-
-
(** Screen reader only (visually hidden but accessible) *)
-
val sr_only : t
-
-
(** Focus ring utility *)
-
val focus_ring : ?color:Color.t -> ?width:Effects.border_width -> unit -> t
-
-
(** V4 specific features *)
-
module V4 : sig
-
(** Container query support *)
-
val container_query : Responsive.container_size -> t -> t
-
-
(** Starting style animation *)
-
val starting_style : t -> t
-
-
(** Text shadow utilities *)
-
val text_shadow : [`None | `Sm | `Base | `Lg | `Xl] -> t
-
-
(** Mask utilities *)
-
val mask : [`Auto | `Cover | `Contain] -> t
-
-
(** 3D perspective *)
-
val perspective : [`None | `Distant | `Normal | `Near] -> t
-
end
+2 -1
lib/tailwind/variants.ml
···
let first classes = Css.make ("first:" ^ Css.to_string classes)
let last classes = Css.make ("last:" ^ Css.to_string classes)
let odd classes = Css.make ("odd:" ^ Css.to_string classes)
-
let even classes = Css.make ("even:" ^ Css.to_string classes)
+
let even classes = Css.make ("even:" ^ Css.to_string classes)
+
let starting_style classes = Css.make ("@starting-style:" ^ Css.to_string classes)
+2 -1
lib/tailwind/variants.mli
···
val first : Css.t -> Css.t
val last : Css.t -> Css.t
val odd : Css.t -> Css.t
-
val even : Css.t -> Css.t
+
val even : Css.t -> Css.t
+
val starting_style : Css.t -> Css.t
+1 -6
test/dune
···
-
(executable
-
(public_name test_tailwind)
+
(test
(name test_runner)
(package tailwind)
(modules test_runner test_simple)
(libraries tailwind tailwind-html alcotest))
-
-
(rule
-
(alias runtest)
-
(action (run ./test_runner.exe)))
+1 -1
test/test_simple.ml
···
Alcotest.(check string) "basic combination" "p-4 m-2" (Css.to_string combined);
(* Test tw function *)
-
let classes = tw [css1; css2] in
+
let classes = Css.tw [css1; css2] in
Alcotest.(check string) "tw function" "p-4 m-2" (Css.to_string classes);
(* Test patterns *)
+2 -2
test/test_tailwind.ml
···
open Tailwind
let test_tw_combinator () =
-
let classes = tw [
+
let classes = Css.tw [
Color.bg (Color.make `Blue ~variant:`V500 ());
Effects.rounded_md;
Spacing.(to_class (p (Size.rem 1.0)));
···
Alcotest.(check string) "screen reader only" "sr-only" result
let test_module_integration () =
-
let complex_button = tw [
+
let complex_button = Css.tw [
Color.bg (Color.make `Blue ~variant:`V500 ());
Color.text (Color.make `White ());
Spacing.(to_class (px (Size.rem 1.0)));