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>

+316 -379
examples/.hello_tailwind_01.ml.swp

This is a binary file and will not be displayed.

+24 -24
examples/colors_and_typography_02.ml
··· 36 36 ]; 37 37 El.body ~at:[At.class' "min-h-screen bg-gray-50 p-8"] [ 38 38 El.div ~at:[At.class' "max-w-4xl mx-auto"] [ 39 - El.h1 ~at:[classes_attr (tw [ 39 + El.h1 ~at:[classes_attr (Css.tw [ 40 40 Typography.(to_class (font_size `Xl2)); 41 41 Typography.(to_class (font_weight `Bold)); 42 42 Color.text (Color.make `Gray ~variant:`V800 ()); 43 43 ]); At.class' "mb-8 text-center"] [El.txt "Colors and Typography Demo"]; 44 44 45 - El.p ~at:[classes_attr (tw [ 45 + El.p ~at:[classes_attr (Css.tw [ 46 46 Typography.(to_class (font_size `Lg)); 47 47 Color.text (Color.make `Gray ~variant:`V600 ()); 48 48 ]); At.class' "text-center mb-12"] [ ··· 51 51 52 52 (* Color Palette Section *) 53 53 El.section ~at:[At.class' "mb-12"] [ 54 - El.h2 ~at:[classes_attr (tw [ 54 + El.h2 ~at:[classes_attr (Css.tw [ 55 55 Typography.(to_class (font_size `Xl)); 56 56 Typography.(to_class (font_weight `Semibold)); 57 57 Color.text (Color.make `Gray ~variant:`V700 ()); 58 58 ]); At.class' "mb-8"] [El.txt "Color Palette"]; 59 59 60 - El.div ~at:[classes_attr (tw [ 60 + El.div ~at:[classes_attr (Css.tw [ 61 61 Display.grid; 62 62 Grid.(to_class (template_cols (`Cols 1))); 63 63 Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2)))))); 64 64 Responsive.(to_class (at_breakpoint `Lg (Grid.(to_class (template_cols (`Cols 3)))))); 65 65 Spacing.(to_class (gap `All (Size.rem 1.5))); 66 66 ])] (List.map (fun (name, color) -> 67 - El.div ~at:[classes_attr (tw [ 67 + El.div ~at:[classes_attr (Css.tw [ 68 68 Color.bg Color.white; 69 69 Spacing.(to_class (p (Size.rem 1.5))); 70 70 Effects.rounded_lg; 71 71 Effects.shadow_sm; 72 72 ]); At.class' "text-center"] [ 73 - El.div ~at:[classes_attr (tw [ 73 + El.div ~at:[classes_attr (Css.tw [ 74 74 Color.text color; 75 75 Typography.(to_class (font_size `Xl2)); 76 76 Typography.(to_class (font_weight `Bold)); 77 77 ]); At.class' "mb-4"] [El.txt "Aa"]; 78 - El.h3 ~at:[classes_attr (tw [ 78 + El.h3 ~at:[classes_attr (Css.tw [ 79 79 Typography.(to_class (font_size `Lg)); 80 80 Typography.(to_class (font_weight `Semibold)); 81 81 Color.text (Color.make `Gray ~variant:`V800 ()); 82 82 ]); At.class' "mb-2"] [El.txt name]; 83 - El.p ~at:[classes_attr (tw [ 83 + El.p ~at:[classes_attr (Css.tw [ 84 84 Typography.(to_class (font_size `Sm)); 85 85 Color.text (Color.make `Gray ~variant:`V500 ()); 86 - ]); At.class' "mb-3"] [El.txt (to_string (tw [Color.text color]))]; 87 - El.p ~at:[classes_attr (tw [Color.text color])] [ 86 + ]); At.class' "mb-3"] [El.txt (to_string (Css.tw [Color.text color]))]; 87 + El.p ~at:[classes_attr (Css.tw [Color.text color])] [ 88 88 El.txt "The quick brown fox jumps over the lazy dog" 89 89 ]; 90 90 ] ··· 93 93 94 94 (* Typography Scale Section *) 95 95 El.section ~at:[At.class' "mb-12"] [ 96 - El.h2 ~at:[classes_attr (tw [ 96 + El.h2 ~at:[classes_attr (Css.tw [ 97 97 Typography.(to_class (font_size `Xl)); 98 98 Typography.(to_class (font_weight `Semibold)); 99 99 Color.text (Color.make `Gray ~variant:`V700 ()); 100 100 ]); At.class' "mb-8"] [El.txt "Typography Scale"]; 101 101 102 - El.div ~at:[classes_attr (tw [ 102 + El.div ~at:[classes_attr (Css.tw [ 103 103 Color.bg Color.white; 104 104 Spacing.(to_class (p (Size.rem 2.0))); 105 105 Effects.rounded_lg; 106 106 Effects.shadow_sm; 107 107 ]); At.class' "mb-8"] (List.map (fun (name, typ_class) -> 108 108 El.div ~at:[At.class' "mb-6 last:mb-0"] [ 109 - El.div ~at:[classes_attr (tw [ 109 + El.div ~at:[classes_attr (Css.tw [ 110 110 Display.flex; 111 111 Flexbox.(to_class (align_items `Center)); 112 112 Flexbox.(to_class (justify `Between)); 113 113 Spacing.(to_class (gap `All (Size.rem 1.0))); 114 114 ]); At.class' "mb-2"] [ 115 - El.span ~at:[classes_attr (tw [ 115 + El.span ~at:[classes_attr (Css.tw [ 116 116 Typography.(to_class (font_size `Sm)); 117 117 Typography.(to_class (font_weight `Medium)); 118 118 Color.text (Color.make `Gray ~variant:`V500 ()); 119 119 ])] [El.txt name]; 120 - El.code ~at:[classes_attr (tw [ 120 + El.code ~at:[classes_attr (Css.tw [ 121 121 Typography.(to_class (font_size `Xs)); 122 122 Color.bg (Color.make `Gray ~variant:`V100 ()); 123 123 Spacing.(to_class (px (Size.rem 0.5))); 124 124 Spacing.(to_class (py (Size.rem 0.25))); 125 125 Effects.rounded_sm; 126 - ])] [El.txt (to_string (tw [typ_class]))]; 126 + ])] [El.txt (to_string (Css.tw [typ_class]))]; 127 127 ]; 128 - El.p ~at:[classes_attr (tw [typ_class])] [ 128 + El.p ~at:[classes_attr (Css.tw [typ_class])] [ 129 129 El.txt "The quick brown fox jumps over the lazy dog" 130 130 ]; 131 131 ] ··· 134 134 135 135 (* Font Weights Section *) 136 136 El.section [ 137 - El.h2 ~at:[classes_attr (tw [ 137 + El.h2 ~at:[classes_attr (Css.tw [ 138 138 Typography.(to_class (font_size `Xl)); 139 139 Typography.(to_class (font_weight `Semibold)); 140 140 Color.text (Color.make `Gray ~variant:`V700 ()); ··· 149 149 ("Extrabold", Typography.(to_class (font_weight `Extrabold))); 150 150 ] in 151 151 152 - El.div ~at:[classes_attr (tw [ 152 + El.div ~at:[classes_attr (Css.tw [ 153 153 Color.bg Color.white; 154 154 Spacing.(to_class (p (Size.rem 2.0))); 155 155 Effects.rounded_lg; 156 156 Effects.shadow_sm; 157 157 ])] (List.map (fun (name, weight_class) -> 158 158 El.div ~at:[At.class' "mb-6 last:mb-0"] [ 159 - El.div ~at:[classes_attr (tw [ 159 + El.div ~at:[classes_attr (Css.tw [ 160 160 Display.flex; 161 161 Flexbox.(to_class (align_items `Center)); 162 162 Flexbox.(to_class (justify `Between)); 163 163 Spacing.(to_class (gap `All (Size.rem 1.0))); 164 164 ]); At.class' "mb-2"] [ 165 - El.span ~at:[classes_attr (tw [ 165 + El.span ~at:[classes_attr (Css.tw [ 166 166 Typography.(to_class (font_size `Sm)); 167 167 Typography.(to_class (font_weight `Medium)); 168 168 Color.text (Color.make `Gray ~variant:`V500 ()); 169 169 ])] [El.txt name]; 170 - El.code ~at:[classes_attr (tw [ 170 + El.code ~at:[classes_attr (Css.tw [ 171 171 Typography.(to_class (font_size `Xs)); 172 172 Color.bg (Color.make `Gray ~variant:`V100 ()); 173 173 Spacing.(to_class (px (Size.rem 0.5))); 174 174 Spacing.(to_class (py (Size.rem 0.25))); 175 175 Effects.rounded_sm; 176 - ])] [El.txt (to_string (tw [weight_class]))]; 176 + ])] [El.txt (to_string (Css.tw [weight_class]))]; 177 177 ]; 178 - El.p ~at:[classes_attr (tw [ 178 + El.p ~at:[classes_attr (Css.tw [ 179 179 weight_class; 180 180 Typography.(to_class (font_size `Lg)); 181 181 ])] [
+14 -14
examples/comprehensive_showcase_07.ml
··· 16 16 El.link ~at:[At.rel "stylesheet"; At.href "comprehensive_showcase_07.css"] (); 17 17 ]; 18 18 19 - El.body ~at:[classes_attr (Tailwind.tw [ 19 + El.body ~at:[classes_attr (Tailwind.Css.tw [ 20 20 Color.bg (Color.make `Gray ~variant:`V50 ()); 21 21 Typography.(to_class (font_size `Base)); 22 22 Typography.(to_class (line_height `Normal)); 23 23 ])] [ 24 24 (* Header with navigation *) 25 - El.header ~at:[classes_attr (Tailwind.tw [ 25 + El.header ~at:[classes_attr (Tailwind.Css.tw [ 26 26 Color.bg Color.white; 27 27 Effects.shadow_lg; 28 28 Effects.border; 29 29 Color.border (Color.make `Gray ~variant:`V200 ()); 30 30 Patterns.sticky_header; 31 31 ])] [ 32 - El.div ~at:[classes_attr (Tailwind.tw [ 32 + El.div ~at:[classes_attr (Tailwind.Css.tw [ 33 33 Patterns.container (); 34 34 Spacing.(to_class (px (Size.rem 1.0))); 35 35 ])] [ 36 - El.div ~at:[classes_attr (Tailwind.tw [ 36 + El.div ~at:[classes_attr (Tailwind.Css.tw [ 37 37 Display.flex; 38 38 Flexbox.(to_class (justify `Between)); 39 39 Flexbox.(to_class (align_items `Center)); 40 40 Layout.(to_class (height (Size.rem 4.0))); 41 41 ])] [ 42 42 (* Brand with gradient text *) 43 - El.h1 ~at:[classes_attr (Tailwind.tw [ 43 + El.h1 ~at:[classes_attr (Tailwind.Css.tw [ 44 44 Typography.(to_class (font_size `Xl2)); 45 45 Typography.(to_class (font_weight `Bold)); 46 46 Color.text (Color.make `Blue ~variant:`V600 ()); 47 47 ])] [El.txt "Tailwind OCaml"]; 48 48 49 49 (* Navigation items with hover effects *) 50 - El.nav ~at:[classes_attr (Tailwind.tw [ 50 + El.nav ~at:[classes_attr (Tailwind.Css.tw [ 51 51 Display.flex; 52 52 Spacing.(to_class (gap `All (Size.rem 2.0))); 53 53 Flexbox.(to_class (align_items `Center)); 54 54 ])] [ 55 - El.a ~at:[At.href "#typography"; classes_attr (Tailwind.tw [ 55 + El.a ~at:[At.href "#typography"; classes_attr (Tailwind.Css.tw [ 56 56 Color.text (Color.make `Gray ~variant:`V600 ()); 57 57 Variants.hover (Color.text (Color.make `Gray ~variant:`V900 ())); 58 58 Effects.transition `All; 59 59 ])] [El.txt "Typography"]; 60 - El.a ~at:[At.href "#layout"; classes_attr (Tailwind.tw [ 60 + El.a ~at:[At.href "#layout"; classes_attr (Tailwind.Css.tw [ 61 61 Color.text (Color.make `Gray ~variant:`V600 ()); 62 62 Variants.hover (Color.text (Color.make `Gray ~variant:`V900 ())); 63 63 Effects.transition `All; 64 64 ])] [El.txt "Layout"]; 65 - El.a ~at:[At.href "#components"; classes_attr (Tailwind.tw [ 65 + El.a ~at:[At.href "#components"; classes_attr (Tailwind.Css.tw [ 66 66 Color.text (Color.make `Gray ~variant:`V600 ()); 67 67 Variants.hover (Color.text (Color.make `Gray ~variant:`V900 ())); 68 68 Effects.transition `All; 69 69 ])] [El.txt "Components"]; 70 70 71 71 (* CTA Button *) 72 - El.button ~at:[classes_attr (Tailwind.tw [ 72 + El.button ~at:[classes_attr (Tailwind.Css.tw [ 73 73 Color.bg (Color.make `Blue ~variant:`V600 ()); 74 74 Color.text Color.white; 75 75 Spacing.(to_class (px (Size.rem 1.0))); ··· 88 88 (* Main Content *) 89 89 El.main [ 90 90 (* Hero Section *) 91 - El.section ~at:[At.id "hero"; classes_attr (Tailwind.tw [ 91 + El.section ~at:[At.id "hero"; classes_attr (Tailwind.Css.tw [ 92 92 Layout.(to_class (min_height Size.screen)); 93 93 Display.flex; 94 94 Flexbox.(to_class (align_items `Center)); ··· 97 97 Color.text Color.white; 98 98 ])] [ 99 99 El.div ~at:[At.class' "text-center container px-8"] [ 100 - El.h1 ~at:[classes_attr (Tailwind.tw [ 100 + El.h1 ~at:[classes_attr (Tailwind.Css.tw [ 101 101 Typography.(to_class (font_size `Xl5)); 102 102 Typography.(to_class (font_weight `Extrabold)); 103 103 Spacing.(to_class (mb (Size.rem 1.5))); 104 104 ])] [El.txt "Type-Safe Tailwind CSS"]; 105 105 106 - El.p ~at:[classes_attr (Tailwind.tw [ 106 + El.p ~at:[classes_attr (Tailwind.Css.tw [ 107 107 Typography.(to_class (font_size `Xl)); 108 108 Color.text (Color.make `Gray ~variant:`V100 ()); 109 109 Spacing.(to_class (mb (Size.rem 2.0))); ··· 197 197 El.pre ~at:[At.class' "text-sm overflow-x-auto"] [ 198 198 El.code [El.txt {|open Tailwind 199 199 200 - let button_classes = tw [ 200 + let button_classes = Css.tw [ 201 201 Color.bg (Color.make `Blue ~variant:`V600 ()); 202 202 Color.text Color.white; 203 203 Spacing.(to_class (px (Size.rem 1.0)));
+43 -43
examples/effects_and_variants_05.ml
··· 18 18 ]; 19 19 El.body ~at:[At.class' "min-h-screen bg-gray-50 p-8"] [ 20 20 El.div ~at:[At.class' "max-w-6xl mx-auto"] [ 21 - El.h1 ~at:[classes_attr (tw [ 21 + El.h1 ~at:[classes_attr (Css.tw [ 22 22 Typography.(to_class (font_size `Xl2)); 23 23 Typography.(to_class (font_weight `Bold)); 24 24 Color.text (Color.make `Gray ~variant:`V800 ()); ··· 26 26 27 27 (* Shadow Effects *) 28 28 El.section ~at:[At.class' "mb-8"] [ 29 - El.h2 ~at:[classes_attr (tw [ 29 + El.h2 ~at:[classes_attr (Css.tw [ 30 30 Typography.(to_class (font_size `Xl)); 31 31 Typography.(to_class (font_weight `Semibold)); 32 32 Color.text (Color.make `Gray ~variant:`V700 ()); 33 33 ]); At.class' "mb-6"] [El.txt "Shadow Effects"]; 34 34 35 - El.div ~at:[classes_attr (tw [ 35 + El.div ~at:[classes_attr (Css.tw [ 36 36 Display.grid; 37 37 Grid.(to_class (template_cols (`Cols 1))); 38 38 Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 3)))))); 39 39 Spacing.(to_class (gap `All (Size.rem 1.5))); 40 40 ])] [ 41 - El.div ~at:[classes_attr (tw [ 41 + El.div ~at:[classes_attr (Css.tw [ 42 42 Color.bg Color.white; 43 43 Spacing.(to_class (p (Size.rem 1.5))); 44 44 Effects.shadow_sm; 45 45 Effects.rounded_lg; 46 46 ]); At.class' "text-center"] [ 47 - El.h3 ~at:[classes_attr (tw [ 47 + El.h3 ~at:[classes_attr (Css.tw [ 48 48 Typography.(to_class (font_weight `Semibold)); 49 49 Color.text (Color.make `Gray ~variant:`V700 ()); 50 50 ]); At.class' "mb-2"] [El.txt "Small Shadow"]; 51 - El.p ~at:[classes_attr (tw [ 51 + El.p ~at:[classes_attr (Css.tw [ 52 52 Typography.(to_class (font_size `Sm)); 53 53 Color.text (Color.make `Gray ~variant:`V600 ()); 54 54 ])] [El.txt "shadow-sm"]; 55 55 ]; 56 56 57 - El.div ~at:[classes_attr (tw [ 57 + El.div ~at:[classes_attr (Css.tw [ 58 58 Color.bg Color.white; 59 59 Spacing.(to_class (p (Size.rem 1.5))); 60 60 Effects.shadow_md; 61 61 Effects.rounded_lg; 62 62 ]); At.class' "text-center"] [ 63 - El.h3 ~at:[classes_attr (tw [ 63 + El.h3 ~at:[classes_attr (Css.tw [ 64 64 Typography.(to_class (font_weight `Semibold)); 65 65 Color.text (Color.make `Gray ~variant:`V700 ()); 66 66 ]); At.class' "mb-2"] [El.txt "Medium Shadow"]; 67 - El.p ~at:[classes_attr (tw [ 67 + El.p ~at:[classes_attr (Css.tw [ 68 68 Typography.(to_class (font_size `Sm)); 69 69 Color.text (Color.make `Gray ~variant:`V600 ()); 70 70 ])] [El.txt "shadow-md"]; 71 71 ]; 72 72 73 - El.div ~at:[classes_attr (tw [ 73 + El.div ~at:[classes_attr (Css.tw [ 74 74 Color.bg Color.white; 75 75 Spacing.(to_class (p (Size.rem 1.5))); 76 76 Effects.shadow_lg; 77 77 Effects.rounded_lg; 78 78 ]); At.class' "text-center"] [ 79 - El.h3 ~at:[classes_attr (tw [ 79 + El.h3 ~at:[classes_attr (Css.tw [ 80 80 Typography.(to_class (font_weight `Semibold)); 81 81 Color.text (Color.make `Gray ~variant:`V700 ()); 82 82 ]); At.class' "mb-2"] [El.txt "Large Shadow"]; 83 - El.p ~at:[classes_attr (tw [ 83 + El.p ~at:[classes_attr (Css.tw [ 84 84 Typography.(to_class (font_size `Sm)); 85 85 Color.text (Color.make `Gray ~variant:`V600 ()); 86 86 ])] [El.txt "shadow-lg"]; ··· 90 90 91 91 (* Rounded Corners *) 92 92 El.section ~at:[At.class' "mb-8"] [ 93 - El.h2 ~at:[classes_attr (tw [ 93 + El.h2 ~at:[classes_attr (Css.tw [ 94 94 Typography.(to_class (font_size `Xl)); 95 95 Typography.(to_class (font_weight `Semibold)); 96 96 Color.text (Color.make `Gray ~variant:`V700 ()); 97 97 ]); At.class' "mb-6"] [El.txt "Border Radius"]; 98 98 99 - El.div ~at:[classes_attr (tw [ 99 + El.div ~at:[classes_attr (Css.tw [ 100 100 Display.flex; 101 101 Flexbox.(to_class (wrap `Wrap)); 102 102 Spacing.(to_class (gap `All (Size.rem 1.0))); 103 103 Flexbox.(to_class (justify `Center)); 104 104 ])] [ 105 - El.div ~at:[classes_attr (tw [ 105 + El.div ~at:[classes_attr (Css.tw [ 106 106 Color.bg (Color.make `Blue ~variant:`V100 ()); 107 107 Spacing.(to_class (p (Size.rem 1.0))); 108 108 (* No rounded corners *) 109 109 ]); At.class' "text-center"] [El.txt "No Radius"]; 110 110 111 - El.div ~at:[classes_attr (tw [ 111 + El.div ~at:[classes_attr (Css.tw [ 112 112 Color.bg (Color.make `Green ~variant:`V100 ()); 113 113 Spacing.(to_class (p (Size.rem 1.0))); 114 114 Effects.rounded_sm; 115 115 ]); At.class' "text-center"] [El.txt "Small"]; 116 116 117 - El.div ~at:[classes_attr (tw [ 117 + El.div ~at:[classes_attr (Css.tw [ 118 118 Color.bg (Color.make `Purple ~variant:`V100 ()); 119 119 Spacing.(to_class (p (Size.rem 1.0))); 120 120 Effects.rounded_md; 121 121 ]); At.class' "text-center"] [El.txt "Medium"]; 122 122 123 - El.div ~at:[classes_attr (tw [ 123 + El.div ~at:[classes_attr (Css.tw [ 124 124 Color.bg (Color.make `Red ~variant:`V100 ()); 125 125 Spacing.(to_class (p (Size.rem 1.0))); 126 126 Effects.rounded_lg; 127 127 ]); At.class' "text-center"] [El.txt "Large"]; 128 128 129 - El.div ~at:[classes_attr (tw [ 129 + El.div ~at:[classes_attr (Css.tw [ 130 130 Color.bg (Color.make `Yellow ~variant:`V100 ()); 131 131 Spacing.(to_class (p (Size.rem 1.0))); 132 132 Effects.rounded_full; ··· 136 136 137 137 (* Interactive Buttons *) 138 138 El.section ~at:[At.class' "mb-8"] [ 139 - El.h2 ~at:[classes_attr (tw [ 139 + El.h2 ~at:[classes_attr (Css.tw [ 140 140 Typography.(to_class (font_size `Xl)); 141 141 Typography.(to_class (font_weight `Semibold)); 142 142 Color.text (Color.make `Gray ~variant:`V700 ()); 143 143 ]); At.class' "mb-6"] [El.txt "Interactive Buttons"]; 144 144 145 - El.div ~at:[classes_attr (tw [ 145 + El.div ~at:[classes_attr (Css.tw [ 146 146 Display.flex; 147 147 Flexbox.(to_class (wrap `Wrap)); 148 148 Spacing.(to_class (gap `All (Size.rem 1.0))); 149 149 Flexbox.(to_class (justify `Center)); 150 150 ])] [ 151 151 (* Hover color change *) 152 - El.button ~at:[classes_attr (tw [ 152 + El.button ~at:[classes_attr (Css.tw [ 153 153 Color.bg (Color.make `Blue ~variant:`V500 ()); 154 154 Color.text Color.white; 155 155 Spacing.(to_class (px (Size.rem 1.5))); ··· 161 161 ])] [El.txt "Hover Color"]; 162 162 163 163 (* Hover shadow *) 164 - El.button ~at:[classes_attr (tw [ 164 + El.button ~at:[classes_attr (Css.tw [ 165 165 Color.bg (Color.make `Green ~variant:`V500 ()); 166 166 Color.text Color.white; 167 167 Spacing.(to_class (px (Size.rem 1.5))); ··· 174 174 ])] [El.txt "Hover Shadow"]; 175 175 176 176 (* Scale effect *) 177 - El.button ~at:[classes_attr (tw [ 177 + El.button ~at:[classes_attr (Css.tw [ 178 178 Color.bg (Color.make `Purple ~variant:`V500 ()); 179 179 Color.text Color.white; 180 180 Spacing.(to_class (px (Size.rem 1.5))); ··· 185 185 ]); At.class' "hover:scale-105 active:scale-95"] [El.txt "Scale Effect"]; 186 186 187 187 (* Focus ring *) 188 - El.button ~at:[classes_attr (tw [ 188 + El.button ~at:[classes_attr (Css.tw [ 189 189 Color.bg (Color.make `Red ~variant:`V500 ()); 190 190 Color.text Color.white; 191 191 Spacing.(to_class (px (Size.rem 1.5))); ··· 200 200 201 201 (* Card Hover Effects *) 202 202 El.section ~at:[At.class' "mb-8"] [ 203 - El.h2 ~at:[classes_attr (tw [ 203 + El.h2 ~at:[classes_attr (Css.tw [ 204 204 Typography.(to_class (font_size `Xl)); 205 205 Typography.(to_class (font_weight `Semibold)); 206 206 Color.text (Color.make `Gray ~variant:`V700 ()); 207 207 ]); At.class' "mb-6"] [El.txt "Card Hover Effects"]; 208 208 209 - El.div ~at:[classes_attr (tw [ 209 + El.div ~at:[classes_attr (Css.tw [ 210 210 Display.grid; 211 211 Grid.(to_class (template_cols (`Cols 1))); 212 212 Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2)))))); 213 213 Spacing.(to_class (gap `All (Size.rem 1.5))); 214 214 ])] [ 215 215 (* Hover shadow card *) 216 - El.div ~at:[classes_attr (tw [ 216 + El.div ~at:[classes_attr (Css.tw [ 217 217 Color.bg Color.white; 218 218 Spacing.(to_class (p (Size.rem 1.5))); 219 219 Effects.rounded_lg; ··· 221 221 Effects.transition `All; 222 222 Variants.hover Effects.shadow_lg; 223 223 ]); At.class' "cursor-pointer"] [ 224 - El.h3 ~at:[classes_attr (tw [ 224 + El.h3 ~at:[classes_attr (Css.tw [ 225 225 Typography.(to_class (font_size `Lg)); 226 226 Typography.(to_class (font_weight `Semibold)); 227 227 Color.text (Color.make `Gray ~variant:`V800 ()); 228 228 ]); At.class' "mb-2"] [El.txt "Shadow Lift"]; 229 - El.p ~at:[classes_attr (tw [ 229 + El.p ~at:[classes_attr (Css.tw [ 230 230 Color.text (Color.make `Gray ~variant:`V600 ()); 231 231 ])] [El.txt "Hover to see the shadow increase. This creates a lifting effect."]; 232 232 ]; 233 233 234 234 (* Scale and shadow card *) 235 - El.div ~at:[classes_attr (tw [ 235 + El.div ~at:[classes_attr (Css.tw [ 236 236 Color.bg Color.white; 237 237 Spacing.(to_class (p (Size.rem 1.5))); 238 238 Effects.rounded_lg; 239 239 Effects.shadow_md; 240 240 Effects.transition `All; 241 241 ]); At.class' "cursor-pointer hover:scale-105 hover:shadow-xl"] [ 242 - El.h3 ~at:[classes_attr (tw [ 242 + El.h3 ~at:[classes_attr (Css.tw [ 243 243 Typography.(to_class (font_size `Lg)); 244 244 Typography.(to_class (font_weight `Semibold)); 245 245 Color.text (Color.make `Gray ~variant:`V800 ()); 246 246 ]); At.class' "mb-2"] [El.txt "Scale + Shadow"]; 247 - El.p ~at:[classes_attr (tw [ 247 + El.p ~at:[classes_attr (Css.tw [ 248 248 Color.text (Color.make `Gray ~variant:`V600 ()); 249 249 ])] [El.txt "This card both scales up and increases shadow on hover."]; 250 250 ]; ··· 253 253 254 254 (* Border Effects *) 255 255 El.section [ 256 - El.h2 ~at:[classes_attr (tw [ 256 + El.h2 ~at:[classes_attr (Css.tw [ 257 257 Typography.(to_class (font_size `Xl)); 258 258 Typography.(to_class (font_weight `Semibold)); 259 259 Color.text (Color.make `Gray ~variant:`V700 ()); 260 260 ]); At.class' "mb-6"] [El.txt "Border Effects"]; 261 261 262 - El.div ~at:[classes_attr (tw [ 262 + El.div ~at:[classes_attr (Css.tw [ 263 263 Display.grid; 264 264 Grid.(to_class (template_cols (`Cols 1))); 265 265 Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 3)))))); 266 266 Spacing.(to_class (gap `All (Size.rem 1.5))); 267 267 ])] [ 268 268 (* Regular border *) 269 - El.div ~at:[classes_attr (tw [ 269 + El.div ~at:[classes_attr (Css.tw [ 270 270 Color.bg Color.white; 271 271 Spacing.(to_class (p (Size.rem 1.5))); 272 272 Effects.border; 273 273 Color.border (Color.make `Gray ~variant:`V200 ()); 274 274 Effects.rounded_lg; 275 275 ]); At.class' "text-center"] [ 276 - El.h3 ~at:[classes_attr (tw [ 276 + El.h3 ~at:[classes_attr (Css.tw [ 277 277 Typography.(to_class (font_weight `Semibold)); 278 278 Color.text (Color.make `Gray ~variant:`V700 ()); 279 279 ]); At.class' "mb-2"] [El.txt "Regular Border"]; 280 - El.p ~at:[classes_attr (tw [ 280 + El.p ~at:[classes_attr (Css.tw [ 281 281 Typography.(to_class (font_size `Sm)); 282 282 Color.text (Color.make `Gray ~variant:`V600 ()); 283 283 ])] [El.txt "border border-gray-200"]; 284 284 ]; 285 285 286 286 (* Colored border *) 287 - El.div ~at:[classes_attr (tw [ 287 + El.div ~at:[classes_attr (Css.tw [ 288 288 Color.bg Color.white; 289 289 Spacing.(to_class (p (Size.rem 1.5))); 290 290 Effects.border; 291 291 Color.border (Color.make `Blue ~variant:`V300 ()); 292 292 Effects.rounded_lg; 293 293 ]); At.class' "text-center"] [ 294 - El.h3 ~at:[classes_attr (tw [ 294 + El.h3 ~at:[classes_attr (Css.tw [ 295 295 Typography.(to_class (font_weight `Semibold)); 296 296 Color.text (Color.make `Blue ~variant:`V600 ()); 297 297 ]); At.class' "mb-2"] [El.txt "Colored Border"]; 298 - El.p ~at:[classes_attr (tw [ 298 + El.p ~at:[classes_attr (Css.tw [ 299 299 Typography.(to_class (font_size `Sm)); 300 300 Color.text (Color.make `Gray ~variant:`V600 ()); 301 301 ])] [El.txt "border border-blue-300"]; ··· 303 303 304 304 (* Thick border *) 305 305 El.div ~at:[At.class' "bg-white p-6 border-2 border-purple-300 rounded-lg text-center"] [ 306 - El.h3 ~at:[classes_attr (tw [ 306 + El.h3 ~at:[classes_attr (Css.tw [ 307 307 Typography.(to_class (font_weight `Semibold)); 308 308 Color.text (Color.make `Purple ~variant:`V600 ()); 309 309 ]); At.class' "mb-2"] [El.txt "Thick Border"]; 310 - El.p ~at:[classes_attr (tw [ 310 + El.p ~at:[classes_attr (Css.tw [ 311 311 Typography.(to_class (font_size `Sm)); 312 312 Color.text (Color.make `Gray ~variant:`V600 ()); 313 313 ])] [El.txt "border-2 border-purple-300"];
+14 -14
examples/hello_tailwind_01.ml
··· 4 4 open Tailwind 5 5 6 6 let classes_attr tailwind_classes = 7 - At.class' (Tailwind.to_string tailwind_classes) 7 + At.class' @@ Tailwind.to_string tailwind_classes 8 8 9 9 let create_page () = 10 - let hello_classes = tw [ 10 + let hello_classes = Css.tw [ 11 11 Color.text (Color.make `Blue ~variant:`V600 ()); 12 12 Typography.(to_class (font_size `Xl2)); 13 13 Typography.(to_class (font_weight `Bold)); 14 14 Spacing.(to_class (mb (Size.rem 1.0))); 15 15 ] in 16 16 17 - let body_classes = tw [ 17 + let body_classes = Css.tw [ 18 18 Layout.(to_class (min_height Size.screen)); 19 19 Color.bg (Color.make `Gray ~variant:`V50 ()); 20 20 Display.flex; ··· 23 23 Spacing.(to_class (p (Size.rem 2.0))); 24 24 ] in 25 25 26 - let container_classes = tw [ 26 + let container_classes = Css.tw [ 27 27 Spacing.(to_class (mx `Auto)); 28 28 Typography.(to_class (text_align `Center)); 29 29 Spacing.(to_class (px (Size.rem 1.0))); 30 30 ] in 31 31 32 - let paragraph_classes = tw [ 32 + let paragraph_classes = Css.tw [ 33 33 Color.text (Color.make `Gray ~variant:`V600 ()); 34 34 Spacing.(to_class (mb (Size.rem 1.5))); 35 35 ] in 36 36 37 - let card_classes = tw [ 37 + let card_classes = Css.tw [ 38 38 Color.bg Color.white; 39 39 Effects.rounded_lg; 40 40 Effects.shadow_sm; ··· 42 42 Typography.(to_class (text_align `Left)); 43 43 ] in 44 44 45 - let subheading_classes = tw [ 45 + let subheading_classes = Css.tw [ 46 46 Typography.(to_class (font_size `Lg)); 47 47 Typography.(to_class (font_weight `Semibold)); 48 48 Color.text (Color.make `Gray ~variant:`V800 ()); 49 49 Spacing.(to_class (mb (Size.rem 0.75))); 50 50 ] in 51 51 52 - let code_block_classes = tw [ 52 + let code_block_classes = Css.tw [ 53 53 Color.bg (Color.make `Gray ~variant:`V100 ()); 54 54 Spacing.(to_class (p (Size.rem 0.75))); 55 55 Effects.rounded_sm; ··· 57 57 Layout.(to_class (overflow `X `Auto)); 58 58 ] in 59 59 60 - let code_classes = tw [ 60 + let code_classes = Css.tw [ 61 61 Color.text (Color.make `Blue ~variant:`V600 ()); 62 62 ] in 63 63 64 - let section_classes = tw [ 64 + let section_classes = Css.tw [ 65 65 Spacing.(to_class (mt (Size.rem 2.0))); 66 66 Spacing.(to_class (gap `Y (Size.rem 1.0))); 67 67 ] in 68 68 69 - let list_classes = tw [ 69 + let list_classes = Css.tw [ 70 70 Typography.(to_class (text_align `Left)); 71 71 Spacing.(to_class (gap `Y (Size.rem 0.5))); 72 72 Color.text (Color.make `Gray ~variant:`V600 ()); 73 73 ] in 74 74 75 - let list_item_classes = tw [ 75 + let list_item_classes = Css.tw [ 76 76 Display.flex; 77 77 Flexbox.(to_class (align_items `Start)); 78 78 ] in 79 79 80 - let checkmark_classes = tw [ 80 + let checkmark_classes = Css.tw [ 81 81 Color.text (Color.make `Green ~variant:`V500 ()); 82 82 Spacing.(to_class (mr (Size.rem 0.5))); 83 83 ] in ··· 139 139 let () = 140 140 (* Output HTML to stdout *) 141 141 let html = create_page () in 142 - print_string (El.to_string ~doctype:true html) 142 + print_string (El.to_string ~doctype:true html)
+12 -12
examples/index_html_generator.ml
··· 37 37 ] 38 38 39 39 let create_index_page () = 40 - let page_classes = tw [ 40 + let page_classes = Css.tw [ 41 41 Layout.(to_class (min_height Size.screen)); 42 42 Color.bg (Color.make `Gray ~variant:`V50 ()); 43 43 ] in 44 44 45 - let container_classes = tw [ 45 + let container_classes = Css.tw [ 46 46 Spacing.(to_class (mx `Auto)); 47 47 Spacing.(to_class (p (Size.rem 2.0))); 48 48 ] in 49 49 50 - let header_classes = tw [ 50 + let header_classes = Css.tw [ 51 51 Typography.(to_class (font_size `Xl4)); 52 52 Typography.(to_class (font_weight `Bold)); 53 53 Color.text (Color.make `Gray ~variant:`V900 ()); ··· 55 55 Typography.(to_class (text_align `Center)); 56 56 ] in 57 57 58 - let subtitle_classes = tw [ 58 + let subtitle_classes = Css.tw [ 59 59 Typography.(to_class (font_size `Xl)); 60 60 Color.text (Color.make `Gray ~variant:`V600 ()); 61 61 Typography.(to_class (text_align `Center)); 62 62 Spacing.(to_class (mb (Size.rem 3.0))); 63 63 ] in 64 64 65 - let grid_classes = tw [ 65 + let grid_classes = Css.tw [ 66 66 Display.grid; 67 67 Grid.(to_class (template_cols (`Cols 1))); 68 68 Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2)))))); ··· 70 70 Spacing.(to_class (mb (Size.rem 3.0))); 71 71 ] in 72 72 73 - let card_classes = tw [ 73 + let card_classes = Css.tw [ 74 74 Color.bg Color.white; 75 75 Effects.rounded_lg; 76 76 Effects.shadow_sm; ··· 82 82 Variants.hover (Color.border (Color.make `Blue ~variant:`V300 ())); 83 83 ] in 84 84 85 - let card_title_classes = tw [ 85 + let card_title_classes = Css.tw [ 86 86 Typography.(to_class (font_size `Lg)); 87 87 Typography.(to_class (font_weight `Semibold)); 88 88 Color.text (Color.make `Gray ~variant:`V900 ()); 89 89 Spacing.(to_class (mb (Size.rem 0.75))); 90 90 ] in 91 91 92 - let card_description_classes = tw [ 92 + let card_description_classes = Css.tw [ 93 93 Color.text (Color.make `Gray ~variant:`V600 ()); 94 94 Spacing.(to_class (mb (Size.rem 1.0))); 95 95 Typography.(to_class (line_height `Relaxed)); 96 96 ] in 97 97 98 - let features_classes = tw [ 98 + let features_classes = Css.tw [ 99 99 Display.flex; 100 100 Flexbox.(to_class (wrap `Wrap)); 101 101 Spacing.(to_class (gap `All (Size.rem 0.5))); 102 102 Spacing.(to_class (mb (Size.rem 1.0))); 103 103 ] in 104 104 105 - let feature_tag_classes = tw [ 105 + let feature_tag_classes = Css.tw [ 106 106 Color.bg (Color.make `Blue ~variant:`V50 ()); 107 107 Color.text (Color.make `Blue ~variant:`V700 ()); 108 108 Typography.(to_class (font_size `Xs)); ··· 111 111 Effects.rounded_full; 112 112 ] in 113 113 114 - let link_classes = tw [ 114 + let link_classes = Css.tw [ 115 115 Color.text (Color.make `Blue ~variant:`V600 ()); 116 116 Typography.(to_class (font_weight `Medium)); 117 117 Variants.hover (Color.text (Color.make `Blue ~variant:`V800 ())); 118 118 Effects.transition `Colors; 119 119 ] in 120 120 121 - let footer_classes = tw [ 121 + let footer_classes = Css.tw [ 122 122 Typography.(to_class (text_align `Center)); 123 123 Spacing.(to_class (mt (Size.rem 3.0))); 124 124 Color.text (Color.make `Gray ~variant:`V500 ());
+31 -31
examples/layout_and_spacing_03.ml
··· 17 17 ]; 18 18 El.body ~at:[At.class' "min-h-screen bg-gray-50 p-8"] [ 19 19 El.div ~at:[At.class' "max-w-6xl mx-auto"] [ 20 - El.h1 ~at:[classes_attr (tw [ 20 + El.h1 ~at:[classes_attr (Css.tw [ 21 21 Typography.(to_class (font_size `Xl2)); 22 22 Typography.(to_class (font_weight `Bold)); 23 23 Color.text (Color.make `Gray ~variant:`V800 ()); 24 24 ]); At.class' "mb-8 text-center"] [El.txt "Layout and Spacing Demo"]; 25 25 26 - El.p ~at:[classes_attr (tw [ 26 + El.p ~at:[classes_attr (Css.tw [ 27 27 Typography.(to_class (font_size `Lg)); 28 28 Color.text (Color.make `Gray ~variant:`V600 ()); 29 29 ]); At.class' "text-center mb-12"] [ ··· 32 32 33 33 (* Flexbox Examples *) 34 34 El.section ~at:[At.class' "mb-12"] [ 35 - El.h2 ~at:[classes_attr (tw [ 35 + El.h2 ~at:[classes_attr (Css.tw [ 36 36 Typography.(to_class (font_size `Xl)); 37 37 Typography.(to_class (font_weight `Semibold)); 38 38 Color.text (Color.make `Gray ~variant:`V700 ()); ··· 40 40 41 41 (* Centered content *) 42 42 El.div ~at:[At.class' "mb-8"] [ 43 - El.h3 ~at:[classes_attr (tw [ 43 + El.h3 ~at:[classes_attr (Css.tw [ 44 44 Typography.(to_class (font_size `Lg)); 45 45 Typography.(to_class (font_weight `Semibold)); 46 46 Color.text (Color.make `Gray ~variant:`V700 ()); 47 47 ]); At.class' "mb-4"] [El.txt "Centered Content"]; 48 48 49 - El.div ~at:[classes_attr (tw [ 49 + El.div ~at:[classes_attr (Css.tw [ 50 50 Display.flex; 51 51 Flexbox.(to_class (justify `Center)); 52 52 Flexbox.(to_class (align_items `Center)); ··· 54 54 Layout.(to_class (height (Size.rem 8.0))); 55 55 Effects.rounded_lg; 56 56 ])] [ 57 - El.div ~at:[classes_attr (tw [ 57 + El.div ~at:[classes_attr (Css.tw [ 58 58 Color.bg Color.white; 59 59 Spacing.(to_class (p (Size.rem 1.5))); 60 60 Effects.rounded_md; ··· 67 67 68 68 (* Space between items *) 69 69 El.div ~at:[At.class' "mb-8"] [ 70 - El.h3 ~at:[classes_attr (tw [ 70 + El.h3 ~at:[classes_attr (Css.tw [ 71 71 Typography.(to_class (font_size `Lg)); 72 72 Typography.(to_class (font_weight `Semibold)); 73 73 Color.text (Color.make `Gray ~variant:`V700 ()); 74 74 ]); At.class' "mb-4"] [El.txt "Space Between"]; 75 75 76 - El.div ~at:[classes_attr (tw [ 76 + El.div ~at:[classes_attr (Css.tw [ 77 77 Display.flex; 78 78 Flexbox.(to_class (justify `Between)); 79 79 Flexbox.(to_class (align_items `Center)); ··· 81 81 Spacing.(to_class (p (Size.rem 1.5))); 82 82 Effects.rounded_lg; 83 83 ])] [ 84 - El.div ~at:[classes_attr (tw [ 84 + El.div ~at:[classes_attr (Css.tw [ 85 85 Color.bg Color.white; 86 86 Spacing.(to_class (p (Size.rem 1.0))); 87 87 Effects.rounded_md; 88 88 ])] [El.txt "Left"]; 89 - El.div ~at:[classes_attr (tw [ 89 + El.div ~at:[classes_attr (Css.tw [ 90 90 Color.bg Color.white; 91 91 Spacing.(to_class (p (Size.rem 1.0))); 92 92 Effects.rounded_md; 93 93 ])] [El.txt "Center"]; 94 - El.div ~at:[classes_attr (tw [ 94 + El.div ~at:[classes_attr (Css.tw [ 95 95 Color.bg Color.white; 96 96 Spacing.(to_class (p (Size.rem 1.0))); 97 97 Effects.rounded_md; ··· 101 101 102 102 (* Flex direction example *) 103 103 El.div [ 104 - El.h3 ~at:[classes_attr (tw [ 104 + El.h3 ~at:[classes_attr (Css.tw [ 105 105 Typography.(to_class (font_size `Lg)); 106 106 Typography.(to_class (font_weight `Semibold)); 107 107 Color.text (Color.make `Gray ~variant:`V700 ()); 108 108 ]); At.class' "mb-4"] [El.txt "Flex Direction Column"]; 109 109 110 - El.div ~at:[classes_attr (tw [ 110 + El.div ~at:[classes_attr (Css.tw [ 111 111 Display.flex; 112 112 Flexbox.(to_class (direction `Col)); 113 113 Spacing.(to_class (gap `All (Size.rem 1.0))); ··· 115 115 Spacing.(to_class (p (Size.rem 1.5))); 116 116 Effects.rounded_lg; 117 117 ])] [ 118 - El.div ~at:[classes_attr (tw [ 118 + El.div ~at:[classes_attr (Css.tw [ 119 119 Color.bg Color.white; 120 120 Spacing.(to_class (p (Size.rem 1.0))); 121 121 Effects.rounded_md; 122 122 ]); At.class' "text-center"] [El.txt "Item 1"]; 123 - El.div ~at:[classes_attr (tw [ 123 + El.div ~at:[classes_attr (Css.tw [ 124 124 Color.bg Color.white; 125 125 Spacing.(to_class (p (Size.rem 1.0))); 126 126 Effects.rounded_md; 127 127 ]); At.class' "text-center"] [El.txt "Item 2"]; 128 - El.div ~at:[classes_attr (tw [ 128 + El.div ~at:[classes_attr (Css.tw [ 129 129 Color.bg Color.white; 130 130 Spacing.(to_class (p (Size.rem 1.0))); 131 131 Effects.rounded_md; ··· 136 136 137 137 (* Grid Examples *) 138 138 El.section ~at:[At.class' "mb-12"] [ 139 - El.h2 ~at:[classes_attr (tw [ 139 + El.h2 ~at:[classes_attr (Css.tw [ 140 140 Typography.(to_class (font_size `Xl)); 141 141 Typography.(to_class (font_weight `Semibold)); 142 142 Color.text (Color.make `Gray ~variant:`V700 ()); ··· 144 144 145 145 (* 2-column grid *) 146 146 El.div ~at:[At.class' "mb-8"] [ 147 - El.h3 ~at:[classes_attr (tw [ 147 + El.h3 ~at:[classes_attr (Css.tw [ 148 148 Typography.(to_class (font_size `Lg)); 149 149 Typography.(to_class (font_weight `Semibold)); 150 150 Color.text (Color.make `Gray ~variant:`V700 ()); 151 151 ]); At.class' "mb-4"] [El.txt "Two Column Grid"]; 152 152 153 - El.div ~at:[classes_attr (tw [ 153 + El.div ~at:[classes_attr (Css.tw [ 154 154 Display.grid; 155 155 Grid.(to_class (template_cols (`Cols 2))); 156 156 Spacing.(to_class (gap `All (Size.rem 1.5))); 157 157 ])] (List.init 4 (fun i -> 158 - El.div ~at:[classes_attr (tw [ 158 + El.div ~at:[classes_attr (Css.tw [ 159 159 Color.bg (Color.make `Red ~variant:`V100 ()); 160 160 Spacing.(to_class (p (Size.rem 1.5))); 161 161 Effects.rounded_lg; ··· 167 167 168 168 (* 3-column grid *) 169 169 El.div ~at:[At.class' "mb-8"] [ 170 - El.h3 ~at:[classes_attr (tw [ 170 + El.h3 ~at:[classes_attr (Css.tw [ 171 171 Typography.(to_class (font_size `Lg)); 172 172 Typography.(to_class (font_weight `Semibold)); 173 173 Color.text (Color.make `Gray ~variant:`V700 ()); 174 174 ]); At.class' "mb-4"] [El.txt "Three Column Grid"]; 175 175 176 - El.div ~at:[classes_attr (tw [ 176 + El.div ~at:[classes_attr (Css.tw [ 177 177 Display.grid; 178 178 Grid.(to_class (template_cols (`Cols 3))); 179 179 Spacing.(to_class (gap `All (Size.rem 1.5))); 180 180 ])] (List.init 6 (fun i -> 181 - El.div ~at:[classes_attr (tw [ 181 + El.div ~at:[classes_attr (Css.tw [ 182 182 Color.bg (Color.make `Yellow ~variant:`V100 ()); 183 183 Spacing.(to_class (p (Size.rem 1.5))); 184 184 Effects.rounded_lg; ··· 191 191 192 192 (* Spacing Examples *) 193 193 El.section [ 194 - El.h2 ~at:[classes_attr (tw [ 194 + El.h2 ~at:[classes_attr (Css.tw [ 195 195 Typography.(to_class (font_size `Xl)); 196 196 Typography.(to_class (font_weight `Semibold)); 197 197 Color.text (Color.make `Gray ~variant:`V700 ()); 198 198 ]); At.class' "mb-8"] [El.txt "Spacing System"]; 199 199 200 - El.div ~at:[classes_attr (tw [ 200 + El.div ~at:[classes_attr (Css.tw [ 201 201 Display.grid; 202 202 Grid.(to_class (template_cols (`Cols 1))); 203 203 Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2)))))); 204 204 Spacing.(to_class (gap `All (Size.rem 2.0))); 205 205 ])] [ 206 206 (* Padding example *) 207 - El.div ~at:[classes_attr (tw [ 207 + El.div ~at:[classes_attr (Css.tw [ 208 208 Color.bg (Color.make `Indigo ~variant:`V100 ()); 209 209 Spacing.(to_class (p (Size.rem 1.5))); 210 210 Effects.rounded_lg; 211 211 ])] [ 212 - El.h4 ~at:[classes_attr (tw [ 212 + El.h4 ~at:[classes_attr (Css.tw [ 213 213 Typography.(to_class (font_size `Base)); 214 214 Typography.(to_class (font_weight `Semibold)); 215 215 Color.text (Color.make `Gray ~variant:`V700 ()); 216 216 ]); At.class' "mb-3"] [El.txt "Padding Example"]; 217 - El.div ~at:[classes_attr (tw [ 217 + El.div ~at:[classes_attr (Css.tw [ 218 218 Color.bg Color.white; 219 219 Spacing.(to_class (p (Size.rem 2.0))); 220 220 Effects.rounded_md; ··· 226 226 ]; 227 227 228 228 (* Margin example *) 229 - El.div ~at:[classes_attr (tw [ 229 + El.div ~at:[classes_attr (Css.tw [ 230 230 Color.bg (Color.make `Cyan ~variant:`V100 ()); 231 231 Spacing.(to_class (p (Size.rem 1.5))); 232 232 Effects.rounded_lg; 233 233 ])] [ 234 - El.h4 ~at:[classes_attr (tw [ 234 + El.h4 ~at:[classes_attr (Css.tw [ 235 235 Typography.(to_class (font_size `Base)); 236 236 Typography.(to_class (font_weight `Semibold)); 237 237 Color.text (Color.make `Gray ~variant:`V700 ()); 238 238 ]); At.class' "mb-3"] [El.txt "Margin Example"]; 239 - El.div ~at:[classes_attr (tw [ 239 + El.div ~at:[classes_attr (Css.tw [ 240 240 Color.bg Color.white; 241 241 Spacing.(to_class (p (Size.rem 1.0))); 242 242 Spacing.(to_class (m (Size.rem 1.5)));
+27 -27
examples/patterns_and_components_06.ml
··· 17 17 ]; 18 18 El.body ~at:[At.class' "min-h-screen bg-gray-50 p-8"] [ 19 19 El.div ~at:[At.class' "max-w-6xl mx-auto"] [ 20 - El.h1 ~at:[classes_attr (tw [ 20 + El.h1 ~at:[classes_attr (Css.tw [ 21 21 Typography.(to_class (font_size `Xl2)); 22 22 Typography.(to_class (font_weight `Bold)); 23 23 Color.text (Color.make `Gray ~variant:`V800 ()); ··· 25 25 26 26 (* Container Pattern *) 27 27 El.section ~at:[At.class' "mb-12"] [ 28 - El.h2 ~at:[classes_attr (tw [ 28 + El.h2 ~at:[classes_attr (Css.tw [ 29 29 Typography.(to_class (font_size `Xl)); 30 30 Typography.(to_class (font_weight `Semibold)); 31 31 Color.text (Color.make `Gray ~variant:`V700 ()); 32 32 ]); At.class' "mb-6"] [El.txt "Container Pattern"]; 33 33 34 - El.div ~at:[classes_attr (tw [Patterns.container ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [ 35 - El.p ~at:[classes_attr (tw [ 34 + El.div ~at:[classes_attr (Css.tw [Patterns.container ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [ 35 + El.p ~at:[classes_attr (Css.tw [ 36 36 Color.text (Color.make `Gray ~variant:`V600 ()); 37 37 ])] [El.txt "This content is inside a container pattern that centers content and provides responsive padding."]; 38 38 ]; ··· 40 40 41 41 (* Card Pattern *) 42 42 El.section ~at:[At.class' "mb-12"] [ 43 - El.h2 ~at:[classes_attr (tw [ 43 + El.h2 ~at:[classes_attr (Css.tw [ 44 44 Typography.(to_class (font_size `Xl)); 45 45 Typography.(to_class (font_weight `Semibold)); 46 46 Color.text (Color.make `Gray ~variant:`V700 ()); 47 47 ]); At.class' "mb-6"] [El.txt "Card Pattern"]; 48 48 49 49 El.div ~at:[At.class' "grid grid-cols-1 md:grid-cols-3 gap-6"] [ 50 - El.div ~at:[classes_attr (tw [Patterns.card]); At.class' "p-6"] [ 51 - El.h3 ~at:[classes_attr (tw [ 50 + El.div ~at:[classes_attr (Css.tw [Patterns.card]); At.class' "p-6"] [ 51 + El.h3 ~at:[classes_attr (Css.tw [ 52 52 Typography.(to_class (font_size `Lg)); 53 53 Typography.(to_class (font_weight `Semibold)); 54 54 Color.text (Color.make `Gray ~variant:`V800 ()); 55 55 ]); At.class' "mb-2"] [El.txt "Card One"]; 56 - El.p ~at:[classes_attr (tw [ 56 + El.p ~at:[classes_attr (Css.tw [ 57 57 Color.text (Color.make `Gray ~variant:`V600 ()); 58 58 ])] [El.txt "This is a card using the built-in card pattern."]; 59 59 ]; 60 60 61 - El.div ~at:[classes_attr (tw [Patterns.card]); At.class' "p-6"] [ 62 - El.h3 ~at:[classes_attr (tw [ 61 + El.div ~at:[classes_attr (Css.tw [Patterns.card]); At.class' "p-6"] [ 62 + El.h3 ~at:[classes_attr (Css.tw [ 63 63 Typography.(to_class (font_size `Lg)); 64 64 Typography.(to_class (font_weight `Semibold)); 65 65 Color.text (Color.make `Gray ~variant:`V800 ()); 66 66 ]); At.class' "mb-2"] [El.txt "Card Two"]; 67 - El.p ~at:[classes_attr (tw [ 67 + El.p ~at:[classes_attr (Css.tw [ 68 68 Color.text (Color.make `Gray ~variant:`V600 ()); 69 69 ])] [El.txt "Another card with the same styling pattern applied."]; 70 70 ]; 71 71 72 - El.div ~at:[classes_attr (tw [Patterns.card]); At.class' "p-6"] [ 73 - El.h3 ~at:[classes_attr (tw [ 72 + El.div ~at:[classes_attr (Css.tw [Patterns.card]); At.class' "p-6"] [ 73 + El.h3 ~at:[classes_attr (Css.tw [ 74 74 Typography.(to_class (font_size `Lg)); 75 75 Typography.(to_class (font_weight `Semibold)); 76 76 Color.text (Color.make `Gray ~variant:`V800 ()); 77 77 ]); At.class' "mb-2"] [El.txt "Card Three"]; 78 - El.p ~at:[classes_attr (tw [ 78 + El.p ~at:[classes_attr (Css.tw [ 79 79 Color.text (Color.make `Gray ~variant:`V600 ()); 80 80 ])] [El.txt "A third card demonstrating consistent styling."]; 81 81 ]; ··· 84 84 85 85 (* Flex Center Pattern *) 86 86 El.section ~at:[At.class' "mb-12"] [ 87 - El.h2 ~at:[classes_attr (tw [ 87 + El.h2 ~at:[classes_attr (Css.tw [ 88 88 Typography.(to_class (font_size `Xl)); 89 89 Typography.(to_class (font_weight `Semibold)); 90 90 Color.text (Color.make `Gray ~variant:`V700 ()); 91 91 ]); At.class' "mb-6"] [El.txt "Flex Center Pattern"]; 92 92 93 - El.div ~at:[classes_attr (tw [Patterns.flex_center]); At.class' "bg-blue-50 rounded-lg h-32"] [ 94 - El.p ~at:[classes_attr (tw [ 93 + El.div ~at:[classes_attr (Css.tw [Patterns.flex_center]); At.class' "bg-blue-50 rounded-lg h-32"] [ 94 + El.p ~at:[classes_attr (Css.tw [ 95 95 Color.text (Color.make `Blue ~variant:`V600 ()); 96 96 Typography.(to_class (font_weight `Medium)); 97 97 ])] [El.txt "This content is perfectly centered using flex_center pattern"]; ··· 100 100 101 101 (* Stack Pattern *) 102 102 El.section ~at:[At.class' "mb-12"] [ 103 - El.h2 ~at:[classes_attr (tw [ 103 + El.h2 ~at:[classes_attr (Css.tw [ 104 104 Typography.(to_class (font_size `Xl)); 105 105 Typography.(to_class (font_weight `Semibold)); 106 106 Color.text (Color.make `Gray ~variant:`V700 ()); 107 107 ]); At.class' "mb-6"] [El.txt "Stack Pattern"]; 108 108 109 - El.div ~at:[classes_attr (tw [Patterns.stack ~gap:(Size.rem 1.0) ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [ 110 - El.div ~at:[classes_attr (tw [ 109 + El.div ~at:[classes_attr (Css.tw [Patterns.stack ~gap:(Size.rem 1.0) ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [ 110 + El.div ~at:[classes_attr (Css.tw [ 111 111 Color.bg (Color.make `Green ~variant:`V50 ()); 112 112 Spacing.(to_class (p (Size.rem 1.0))); 113 113 Effects.rounded_md; 114 114 ])] [El.txt "Stack Item 1"]; 115 115 116 - El.div ~at:[classes_attr (tw [ 116 + El.div ~at:[classes_attr (Css.tw [ 117 117 Color.bg (Color.make `Blue ~variant:`V50 ()); 118 118 Spacing.(to_class (p (Size.rem 1.0))); 119 119 Effects.rounded_md; 120 120 ])] [El.txt "Stack Item 2"]; 121 121 122 - El.div ~at:[classes_attr (tw [ 122 + El.div ~at:[classes_attr (Css.tw [ 123 123 Color.bg (Color.make `Purple ~variant:`V50 ()); 124 124 Spacing.(to_class (p (Size.rem 1.0))); 125 125 Effects.rounded_md; ··· 129 129 130 130 (* Inline Stack Pattern *) 131 131 El.section [ 132 - El.h2 ~at:[classes_attr (tw [ 132 + El.h2 ~at:[classes_attr (Css.tw [ 133 133 Typography.(to_class (font_size `Xl)); 134 134 Typography.(to_class (font_weight `Semibold)); 135 135 Color.text (Color.make `Gray ~variant:`V700 ()); 136 136 ]); At.class' "mb-6"] [El.txt "Inline Stack Pattern"]; 137 137 138 - El.div ~at:[classes_attr (tw [Patterns.inline_stack ~gap:(Size.rem 1.0) ()]); At.class' "bg-white rounded-lg shadow-sm p-6"] [ 139 - El.span ~at:[classes_attr (tw [ 138 + 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"] [ 139 + El.span ~at:[classes_attr (Css.tw [ 140 140 Color.bg (Color.make `Red ~variant:`V50 ()); 141 141 Color.text (Color.make `Red ~variant:`V600 ()); 142 142 Spacing.(to_class (px (Size.rem 0.75))); ··· 145 145 Typography.(to_class (font_size `Sm)); 146 146 ])] [El.txt "Tag 1"]; 147 147 148 - El.span ~at:[classes_attr (tw [ 148 + El.span ~at:[classes_attr (Css.tw [ 149 149 Color.bg (Color.make `Yellow ~variant:`V50 ()); 150 150 Color.text (Color.make `Yellow ~variant:`V600 ()); 151 151 Spacing.(to_class (px (Size.rem 0.75))); ··· 154 154 Typography.(to_class (font_size `Sm)); 155 155 ])] [El.txt "Tag 2"]; 156 156 157 - El.span ~at:[classes_attr (tw [ 157 + El.span ~at:[classes_attr (Css.tw [ 158 158 Color.bg (Color.make `Indigo ~variant:`V50 ()); 159 159 Color.text (Color.make `Indigo ~variant:`V600 ()); 160 160 Spacing.(to_class (px (Size.rem 0.75)));
+18 -18
examples/responsive_design_04.ml
··· 17 17 ]; 18 18 El.body ~at:[At.class' "min-h-screen bg-gray-50 p-8"] [ 19 19 El.div ~at:[At.class' "max-w-6xl mx-auto"] [ 20 - El.h1 ~at:[classes_attr (tw [ 20 + El.h1 ~at:[classes_attr (Css.tw [ 21 21 Typography.(to_class (font_size `Xl2)); 22 22 Responsive.(to_class (at_breakpoint `Md (Typography.(to_class (font_size `Xl3))))); 23 23 Typography.(to_class (font_weight `Bold)); 24 24 Color.text (Color.make `Gray ~variant:`V700 ()); 25 25 ]); At.class' "mb-8 text-center"] [El.txt "Responsive Design Demo"]; 26 26 27 - El.p ~at:[classes_attr (tw [ 27 + El.p ~at:[classes_attr (Css.tw [ 28 28 Typography.(to_class (font_size `Lg)); 29 29 Color.text (Color.make `Gray ~variant:`V600 ()); 30 30 ]); At.class' "text-center mb-8"] [ ··· 33 33 34 34 (* Responsive Grid *) 35 35 El.section ~at:[At.class' "mb-8"] [ 36 - El.h2 ~at:[classes_attr (tw [ 36 + El.h2 ~at:[classes_attr (Css.tw [ 37 37 Typography.(to_class (font_size `Xl)); 38 38 Typography.(to_class (font_weight `Semibold)); 39 39 Color.text (Color.make `Gray ~variant:`V700 ()); 40 40 ]); At.class' "mb-6"] [El.txt "Responsive Grid"]; 41 41 42 - El.p ~at:[classes_attr (tw [ 42 + El.p ~at:[classes_attr (Css.tw [ 43 43 Color.text (Color.make `Gray ~variant:`V600 ()); 44 44 ]); At.class' "mb-4"] [ 45 45 El.txt "1 column → 2 columns (md) → 3 columns (lg) → 4 columns (xl)" 46 46 ]; 47 47 48 - El.div ~at:[classes_attr (tw [ 48 + El.div ~at:[classes_attr (Css.tw [ 49 49 Display.grid; 50 50 Grid.(to_class (template_cols (`Cols 1))); 51 51 Responsive.(to_class (at_breakpoint `Md (Grid.(to_class (template_cols (`Cols 2)))))); ··· 60 60 Color.make `Red ~variant:`V100 (); 61 61 Color.make `Yellow ~variant:`V100 (); 62 62 |] in 63 - El.div ~at:[classes_attr (tw [ 63 + El.div ~at:[classes_attr (Css.tw [ 64 64 Color.bg colors.(i mod (Array.length colors)); 65 65 Spacing.(to_class (p (Size.rem 1.5))); 66 66 ]); At.class' "rounded-lg text-center"] [ ··· 71 71 72 72 (* Responsive Typography *) 73 73 El.section ~at:[At.class' "mb-8"] [ 74 - El.h2 ~at:[classes_attr (tw [ 74 + El.h2 ~at:[classes_attr (Css.tw [ 75 75 Typography.(to_class (font_size `Xl)); 76 76 Typography.(to_class (font_weight `Semibold)); 77 77 Color.text (Color.make `Gray ~variant:`V700 ()); 78 78 ]); At.class' "mb-6"] [El.txt "Responsive Typography"]; 79 79 80 - El.div ~at:[classes_attr (tw [ 80 + El.div ~at:[classes_attr (Css.tw [ 81 81 Color.bg (Color.make `Gray ~variant:`V100 ()); 82 82 Spacing.(to_class (p (Size.rem 1.5))); 83 83 ]); At.class' "rounded-lg text-center"] [ 84 - El.h3 ~at:[classes_attr (tw [ 84 + El.h3 ~at:[classes_attr (Css.tw [ 85 85 Typography.(to_class (font_size `Base)); 86 86 Responsive.(to_class (at_breakpoint `Md (Typography.(to_class (font_size `Lg))))); 87 87 Responsive.(to_class (at_breakpoint `Lg (Typography.(to_class (font_size `Xl2))))); ··· 89 89 Color.text (Color.make `Blue ~variant:`V600 ()); 90 90 ]); At.class' "mb-4"] [El.txt "Responsive Heading"]; 91 91 92 - El.p ~at:[classes_attr (tw [ 92 + El.p ~at:[classes_attr (Css.tw [ 93 93 Typography.(to_class (font_size `Sm)); 94 94 Responsive.(to_class (at_breakpoint `Md (Typography.(to_class (font_size `Base))))); 95 95 Color.text (Color.make `Gray ~variant:`V600 ()); ··· 101 101 102 102 (* Show/Hide Elements *) 103 103 El.section ~at:[At.class' "mb-8"] [ 104 - El.h2 ~at:[classes_attr (tw [ 104 + El.h2 ~at:[classes_attr (Css.tw [ 105 105 Typography.(to_class (font_size `Xl)); 106 106 Typography.(to_class (font_weight `Semibold)); 107 107 Color.text (Color.make `Gray ~variant:`V700 ()); 108 108 ]); At.class' "mb-6"] [El.txt "Responsive Visibility"]; 109 109 110 - El.div ~at:[classes_attr (tw [ 110 + El.div ~at:[classes_attr (Css.tw [ 111 111 Display.flex; 112 112 Flexbox.(to_class (direction `Col)); 113 113 Responsive.(to_class (at_breakpoint `Md (Flexbox.(to_class (direction `Row))))); 114 114 Spacing.(to_class (gap `All (Size.rem 1.0))); 115 115 ])] [ 116 - El.div ~at:[classes_attr (tw [ 116 + El.div ~at:[classes_attr (Css.tw [ 117 117 Color.bg (Color.make `Blue ~variant:`V100 ()); 118 118 Spacing.(to_class (p (Size.rem 1.5))); 119 119 ]); At.class' "rounded-lg text-center"] [ 120 120 El.txt "Always visible" 121 121 ]; 122 122 123 - El.div ~at:[classes_attr (tw [ 123 + El.div ~at:[classes_attr (Css.tw [ 124 124 Color.bg (Color.make `Green ~variant:`V100 ()); 125 125 Spacing.(to_class (p (Size.rem 1.5))); 126 126 Display.hidden; ··· 129 129 El.txt "Hidden on mobile, visible on md+" 130 130 ]; 131 131 132 - El.div ~at:[classes_attr (tw [ 132 + El.div ~at:[classes_attr (Css.tw [ 133 133 Color.bg (Color.make `Purple ~variant:`V100 ()); 134 134 Spacing.(to_class (p (Size.rem 1.5))); 135 135 Display.hidden; ··· 142 142 143 143 (* Responsive Spacing *) 144 144 El.section [ 145 - El.h2 ~at:[classes_attr (tw [ 145 + El.h2 ~at:[classes_attr (Css.tw [ 146 146 Typography.(to_class (font_size `Xl)); 147 147 Typography.(to_class (font_weight `Semibold)); 148 148 Color.text (Color.make `Gray ~variant:`V700 ()); 149 149 ]); At.class' "mb-6"] [El.txt "Responsive Spacing"]; 150 150 151 - El.div ~at:[classes_attr (tw [ 151 + El.div ~at:[classes_attr (Css.tw [ 152 152 Color.bg (Color.make `Gray ~variant:`V100 ()); 153 153 Spacing.(to_class (p (Size.rem 1.0))); 154 154 Responsive.(to_class (at_breakpoint `Md (Spacing.(to_class (p (Size.rem 1.5)))))); 155 155 Responsive.(to_class (at_breakpoint `Lg (Spacing.(to_class (p (Size.rem 2.0)))))); 156 156 ]); At.class' "rounded-lg"] [ 157 - El.div ~at:[classes_attr (tw [ 157 + El.div ~at:[classes_attr (Css.tw [ 158 158 Color.bg Color.white; 159 159 Spacing.(to_class (p (Size.rem 1.0))); 160 160 ]); At.class' "rounded"] [
+14 -14
lib/tailwind-html/button.ml
··· 18 18 let classes_attr tailwind_classes = 19 19 At.class' (Tailwind.to_string tailwind_classes) 20 20 21 - let base_button_classes = Tailwind.tw [ 21 + let base_button_classes = Tailwind.Css.tw [ 22 22 Tailwind.Display.inline_flex; 23 23 Tailwind.Flexbox.(to_class (align_items `Center)); 24 24 Tailwind.Flexbox.(to_class (justify `Center)); ··· 36 36 ] 37 37 38 38 let variant_classes = function 39 - | `Primary -> Tailwind.tw [ 39 + | `Primary -> Tailwind.Css.tw [ 40 40 Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V600 ()); 41 41 Tailwind.Color.text Tailwind.Color.white; 42 42 Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V700 ())); 43 43 ] 44 - | `Secondary -> Tailwind.tw [ 44 + | `Secondary -> Tailwind.Css.tw [ 45 45 Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V200 ()); 46 46 Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V900 ()); 47 47 Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V300 ())); 48 48 ] 49 - | `Outline -> Tailwind.tw [ 49 + | `Outline -> Tailwind.Css.tw [ 50 50 Tailwind.Effects.border; 51 51 Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V300 ()); 52 52 Tailwind.Color.bg Tailwind.Color.transparent; 53 53 Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V100 ())); 54 54 ] 55 - | `Ghost -> Tailwind.tw [ 55 + | `Ghost -> Tailwind.Css.tw [ 56 56 Tailwind.Color.bg Tailwind.Color.transparent; 57 57 Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V100 ())); 58 58 ] 59 - | `Link -> Tailwind.tw [ 59 + | `Link -> Tailwind.Css.tw [ 60 60 Tailwind.Color.bg Tailwind.Color.transparent; 61 61 Tailwind.Color.text (Tailwind.Color.make `Blue ~variant:`V600 ()); 62 62 Tailwind.Css.make "underline-offset-4"; ··· 64 64 ] 65 65 66 66 let size_classes = function 67 - | `Default -> Tailwind.tw [ 67 + | `Default -> Tailwind.Css.tw [ 68 68 Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 1.0))); 69 69 Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 0.5))); 70 70 ] 71 - | `Sm -> Tailwind.tw [ 71 + | `Sm -> Tailwind.Css.tw [ 72 72 Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 0.75))); 73 73 Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 0.375))); 74 74 ] 75 - | `Lg -> Tailwind.tw [ 75 + | `Lg -> Tailwind.Css.tw [ 76 76 Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 2.0))); 77 77 Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 0.75))); 78 78 ] 79 - | `Icon -> Tailwind.tw [ 79 + | `Icon -> Tailwind.Css.tw [ 80 80 Tailwind.Layout.(to_class (width (Tailwind.Size.rem 2.5))); 81 81 Tailwind.Layout.(to_class (height (Tailwind.Size.rem 2.5))); 82 82 ] 83 83 84 84 let state_classes = function 85 85 | `Default -> Tailwind.Css.empty 86 - | `Loading -> Tailwind.tw [ 86 + | `Loading -> Tailwind.Css.tw [ 87 87 Tailwind.Css.make "cursor-not-allowed"; 88 88 Tailwind.Effects.(to_class (opacity 75)); 89 89 ] 90 - | `Disabled -> Tailwind.tw [ 90 + | `Disabled -> Tailwind.Css.tw [ 91 91 Tailwind.Css.make "cursor-not-allowed"; 92 92 Tailwind.Effects.(to_class (opacity 50)); 93 93 ] ··· 104 104 } 105 105 106 106 let to_html button = 107 - let button_classes = Tailwind.tw [ 107 + let button_classes = Tailwind.Css.tw [ 108 108 base_button_classes; 109 109 variant_classes button.variant; 110 110 size_classes button.size; ··· 121 121 let all_attrs = base_attrs @ state_attrs @ custom_attrs in 122 122 123 123 let loading_spinner = match button.state with 124 - | `Loading -> [El.span ~at:[classes_attr (Tailwind.tw [ 124 + | `Loading -> [El.span ~at:[classes_attr (Tailwind.Css.tw [ 125 125 Tailwind.Css.make "animate-spin"; 126 126 Tailwind.Spacing.(to_class (mr (Tailwind.Size.rem 0.5))); 127 127 ])] [El.txt "⟳"]]
+14 -14
lib/tailwind-html/card.ml
··· 24 24 let classes_attr tailwind_classes = 25 25 At.class' (Tailwind.to_string tailwind_classes) 26 26 27 - let base_card_classes = Tailwind.tw [ 27 + let base_card_classes = Tailwind.Css.tw [ 28 28 Tailwind.Effects.rounded_lg; 29 29 Tailwind.Color.bg Tailwind.Color.white; 30 30 Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V900 ()); 31 31 ] 32 32 33 33 let variant_classes = function 34 - | Default -> Tailwind.tw [ 34 + | Default -> Tailwind.Css.tw [ 35 35 Tailwind.Effects.border; 36 36 Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V200 ()); 37 37 Tailwind.Effects.shadow_sm; 38 38 ] 39 - | Outlined -> Tailwind.tw [ 39 + | Outlined -> Tailwind.Css.tw [ 40 40 Tailwind.Effects.border_2; 41 41 Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V300 ()); 42 42 ] 43 - | Elevated -> Tailwind.tw [ 43 + | Elevated -> Tailwind.Css.tw [ 44 44 Tailwind.Effects.shadow_lg; 45 45 Tailwind.Effects.border; 46 46 Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V200 ()); 47 47 ] 48 - | Flat -> Tailwind.tw [ 48 + | Flat -> Tailwind.Css.tw [ 49 49 Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V50 ()); 50 50 ] 51 51 ··· 63 63 } 64 64 65 65 let to_html card = 66 - let card_classes = Tailwind.tw [ 66 + let card_classes = Tailwind.Css.tw [ 67 67 base_card_classes; 68 68 variant_classes card.variant; 69 69 (if card.padding then Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5))) else Tailwind.Css.empty); 70 70 (if card.hoverable then Tailwind.Variants.hover (Tailwind.Effects.shadow_md) else Tailwind.Css.empty); 71 - (if card.clickable then Tailwind.tw [ 71 + (if card.clickable then Tailwind.Css.tw [ 72 72 Tailwind.Css.make "cursor-pointer"; 73 73 Tailwind.Variants.hover (Tailwind.Effects.shadow_md); 74 74 ] else Tailwind.Css.empty); ··· 90 90 91 91 (** Card header section *) 92 92 let header ?classes ?title ?subtitle ?actions ~children () = 93 - let header_classes = Tailwind.tw [ 93 + let header_classes = Tailwind.Css.tw [ 94 94 Tailwind.Display.flex; 95 95 Tailwind.Flexbox.(to_class (direction `Col)); 96 96 Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5))); ··· 98 98 ] in 99 99 100 100 let title_element = match title with 101 - | Some t -> Some (El.h3 ~at:[classes_attr (Tailwind.tw [ 101 + | Some t -> Some (El.h3 ~at:[classes_attr (Tailwind.Css.tw [ 102 102 Tailwind.Typography.(to_class (font_size `Lg)); 103 103 Tailwind.Typography.(to_class (font_weight `Semibold)); 104 104 Tailwind.Spacing.(to_class (mb (Tailwind.Size.rem 0.5))); ··· 107 107 in 108 108 109 109 let subtitle_element = match subtitle with 110 - | Some s -> Some (El.p ~at:[classes_attr (Tailwind.tw [ 110 + | Some s -> Some (El.p ~at:[classes_attr (Tailwind.Css.tw [ 111 111 Tailwind.Typography.(to_class (font_size `Sm)); 112 112 Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V600 ()); 113 113 ])] [El.txt s]) ··· 125 125 126 126 (** Card body section *) 127 127 let body ?classes ~children () = 128 - let body_classes = Tailwind.tw [ 128 + let body_classes = Tailwind.Css.tw [ 129 129 Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5))); 130 130 Tailwind.Spacing.(to_class (pt (Tailwind.Size.zero))); 131 131 (match classes with Some c -> c | None -> Tailwind.Css.empty); ··· 135 135 136 136 (** Card footer section *) 137 137 let footer ?classes ?actions ~children () = 138 - let footer_classes = Tailwind.tw [ 138 + let footer_classes = Tailwind.Css.tw [ 139 139 Tailwind.Display.flex; 140 140 Tailwind.Flexbox.(to_class (align_items `Center)); 141 141 Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5))); ··· 148 148 149 149 (** Card image section *) 150 150 let image ?classes ?alt ?(cover=true) ~src () = 151 - let img_classes = Tailwind.tw [ 151 + let img_classes = Tailwind.Css.tw [ 152 152 Tailwind.Layout.w_full; 153 153 Tailwind.Layout.(to_class (height (Tailwind.Size.rem 12.0))); 154 154 (if cover then Tailwind.Layout.(to_class (object_fit `Cover)) else Tailwind.Css.empty); ··· 183 183 | None -> [] 184 184 in 185 185 186 - let grid_classes = Tailwind.tw (base_classes @ col_classes @ gap_classes @ 186 + let grid_classes = Tailwind.Css.tw (base_classes @ col_classes @ gap_classes @ 187 187 (match classes with Some c -> [c] | None -> [])) in 188 188 189 189 let card_elements = List.map to_html cards in
+1 -1
lib/tailwind-html/component.ml
··· 23 23 (* Add classes to a component *) 24 24 let add_classes new_classes comp = { 25 25 comp with classes = match comp.classes with 26 - | Some existing -> Some (Tailwind.tw [existing; new_classes]) 26 + | Some existing -> Some (Tailwind.Css.tw [existing; new_classes]) 27 27 | None -> Some new_classes 28 28 } 29 29
+7 -7
lib/tailwind-html/form.ml
··· 47 47 let classes_attr tailwind_classes = 48 48 At.class' (Tailwind.to_string tailwind_classes) 49 49 50 - let base_input_classes = Tailwind.tw [ 50 + let base_input_classes = Tailwind.Css.tw [ 51 51 Tailwind.Display.flex; 52 52 Tailwind.Layout.(to_class (height (Tailwind.Size.rem 2.5))); 53 53 Tailwind.Layout.w_full; ··· 61 61 ] 62 62 63 63 let validation_classes = function 64 - | Some Valid -> Tailwind.tw [ 64 + | Some Valid -> Tailwind.Css.tw [ 65 65 Tailwind.Color.border (Tailwind.Color.make `Green ~variant:`V500 ()); 66 66 Tailwind.Variants.focus (Tailwind.Color.border (Tailwind.Color.make `Green ~variant:`V600 ())); 67 67 ] 68 - | Some Invalid -> Tailwind.tw [ 68 + | Some Invalid -> Tailwind.Css.tw [ 69 69 Tailwind.Color.border (Tailwind.Color.make `Red ~variant:`V500 ()); 70 70 Tailwind.Variants.focus (Tailwind.Color.border (Tailwind.Color.make `Red ~variant:`V600 ())); 71 71 ] 72 - | Some Warning -> Tailwind.tw [ 72 + | Some Warning -> Tailwind.Css.tw [ 73 73 Tailwind.Color.border (Tailwind.Color.make `Yellow ~variant:`V500 ()); 74 74 Tailwind.Variants.focus (Tailwind.Color.border (Tailwind.Color.make `Yellow ~variant:`V600 ())); 75 75 ] ··· 202 202 | Datetime_local -> "datetime-local" 203 203 204 204 let to_html field = 205 - let field_classes = Tailwind.tw [ 205 + let field_classes = Tailwind.Css.tw [ 206 206 base_input_classes; 207 207 validation_classes field.validation; 208 208 (match field.classes with Some c -> c | None -> Tailwind.Css.empty); ··· 255 255 | None -> input_element 256 256 257 257 let group ?classes ~fields () = 258 - let group_classes = Tailwind.tw [ 258 + let group_classes = Tailwind.Css.tw [ 259 259 Tailwind.Display.grid; 260 260 Tailwind.Layout.w_full; 261 261 Tailwind.Spacing.(to_class (gap `All (Tailwind.Size.rem 1.0))); ··· 266 266 El.div ~at:[classes_attr group_classes] field_elements 267 267 268 268 let form ?action ?method_ ?classes ?attributes ~fields ?submit () = 269 - let form_classes = Tailwind.tw [ 269 + let form_classes = Tailwind.Css.tw [ 270 270 Tailwind.Display.grid; 271 271 Tailwind.Layout.w_full; 272 272 Tailwind.Spacing.(to_class (gap `All (Tailwind.Size.rem 1.5)));
+12 -12
lib/tailwind-html/layout.ml
··· 96 96 let size_class = container_size_to_class size in 97 97 let center_class = if center then Tailwind.Css.make "mx-auto" else Tailwind.Css.empty in 98 98 let padding_class = if padding then Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 1.0))) else Tailwind.Css.empty in 99 - Tailwind.tw [size_class; center_class; padding_class] 99 + Tailwind.Css.tw [size_class; center_class; padding_class] 100 100 101 101 | Flex (direction, justify, align, wrap, gap) -> 102 102 let dir_classes = match direction with Some d -> [Tailwind.Flexbox.(to_class (direction d))] | None -> [] in ··· 104 104 let align_classes = match align with Some a -> [Tailwind.Flexbox.(to_class (align_items a))] | None -> [] in 105 105 let wrap_classes = match wrap with Some w -> [Tailwind.Flexbox.(to_class (wrap w))] | None -> [] in 106 106 let gap_classes = match gap with Some g -> [Tailwind.Spacing.(to_class (gap `All g))] | None -> [] in 107 - Tailwind.tw ([Tailwind.Display.flex] @ dir_classes @ justify_classes @ align_classes @ wrap_classes @ gap_classes) 107 + Tailwind.Css.tw ([Tailwind.Display.flex] @ dir_classes @ justify_classes @ align_classes @ wrap_classes @ gap_classes) 108 108 109 109 | Grid (cols, rows, gap, gap_x, gap_y, _flow) -> 110 110 let col_classes = match cols with Some c -> [Tailwind.Grid.(to_class (template_cols c))] | None -> [] in ··· 113 113 let gap_x_classes = match gap_x with Some g -> [Tailwind.Spacing.(to_class (gap `X g))] | None -> [] in 114 114 let gap_y_classes = match gap_y with Some g -> [Tailwind.Spacing.(to_class (gap `Y g))] | None -> [] in 115 115 let flow_classes = [] in 116 - Tailwind.tw ([Tailwind.Display.grid] @ col_classes @ row_classes @ gap_classes @ gap_x_classes @ gap_y_classes @ flow_classes) 116 + Tailwind.Css.tw ([Tailwind.Display.grid] @ col_classes @ row_classes @ gap_classes @ gap_x_classes @ gap_y_classes @ flow_classes) 117 117 118 118 | Stack (gap, align) -> 119 119 let gap_classes = match gap with Some g -> [Tailwind.Spacing.(to_class (gap `All g))] | None -> [] in 120 120 let align_classes = match align with Some a -> [Tailwind.Flexbox.(to_class (align_items a))] | None -> [] in 121 - Tailwind.tw ([Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Col))] @ gap_classes @ align_classes) 121 + Tailwind.Css.tw ([Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Col))] @ gap_classes @ align_classes) 122 122 123 123 | Row (gap, justify, align, wrap) -> 124 124 let gap_classes = match gap with Some g -> [Tailwind.Spacing.(to_class (gap `All g))] | None -> [] in 125 125 let justify_classes = match justify with Some j -> [Tailwind.Flexbox.(to_class (justify j))] | None -> [] in 126 126 let align_classes = match align with Some a -> [Tailwind.Flexbox.(to_class (align_items a))] | None -> [] in 127 127 let wrap_classes = match wrap with Some true -> [Tailwind.Flexbox.(to_class (wrap `Wrap))] | Some false -> [Tailwind.Flexbox.(to_class (wrap `Nowrap))] | None -> [] in 128 - Tailwind.tw ([Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Row))] @ gap_classes @ justify_classes @ align_classes @ wrap_classes) 128 + Tailwind.Css.tw ([Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Row))] @ gap_classes @ justify_classes @ align_classes @ wrap_classes) 129 129 130 130 | Sidebar (_side, _width, _collapsible, _sidebar_content, _main_content) -> 131 - Tailwind.tw [Tailwind.Display.flex] 131 + Tailwind.Css.tw [Tailwind.Display.flex] 132 132 133 133 | Page (_header, _footer, _sidebar, _main) -> 134 - Tailwind.tw [Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Col)); Tailwind.Layout.h_screen] 134 + Tailwind.Css.tw [Tailwind.Display.flex; Tailwind.Flexbox.(to_class (direction `Col)); Tailwind.Layout.h_screen] 135 135 in 136 136 137 - let final_classes = Tailwind.tw [ 137 + let final_classes = Tailwind.Css.tw [ 138 138 base_classes; 139 139 (match layout.classes with Some c -> c | None -> Tailwind.Css.empty); 140 140 ] in ··· 146 146 match layout.layout_type with 147 147 | Sidebar (_side, width, _collapsible, sidebar_content, main_content) -> 148 148 let sidebar_width = match width with Some w -> w | None -> Tailwind.Size.rem 16.0 in 149 - let sidebar_classes = Tailwind.tw [ 149 + let sidebar_classes = Tailwind.Css.tw [ 150 150 Tailwind.Layout.(to_class (width sidebar_width)); 151 151 Tailwind.Flexbox.(to_class (shrink (Some 0))); 152 152 Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V50 ()); 153 153 ] in 154 - let main_classes = Tailwind.tw [ 154 + let main_classes = Tailwind.Css.tw [ 155 155 Tailwind.Flexbox.(to_class (grow (Some 1))); 156 156 Tailwind.Layout.(to_class (overflow `All `Auto)); 157 157 ] in ··· 177 177 | Some s -> Tailwind.Layout.(to_class (height s)) 178 178 | None -> Tailwind.Layout.(to_class (height (Tailwind.Size.rem 1.0))) 179 179 in 180 - El.div ~at:[classes_attr (Tailwind.tw [size_class])] [] 180 + El.div ~at:[classes_attr (Tailwind.Css.tw [size_class])] [] 181 181 182 182 let divider ?orientation ?classes () = 183 183 let base_classes = match orientation with ··· 192 192 Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V300 ()); 193 193 ] 194 194 in 195 - let divider_classes = Tailwind.tw (base_classes @ 195 + let divider_classes = Tailwind.Css.tw (base_classes @ 196 196 (match classes with Some c -> [c] | None -> [])) in 197 197 El.div ~at:[classes_attr divider_classes] []
+2 -2
lib/tailwind-html/tailwind_html.ml
··· 62 62 let weight_styles = match weight with Some w -> [Tailwind.Typography.(to_class (font_weight w))] | None -> [] in 63 63 let color_styles = match color with Some c -> [Tailwind.Color.text c] | None -> [] in 64 64 let align_styles = match align with Some a -> [Tailwind.Typography.(to_class (text_align a))] | None -> [] in 65 - let text_classes = Tailwind.tw (base_styles @ size_styles @ weight_styles @ color_styles @ align_styles) in 65 + let text_classes = Tailwind.Css.tw (base_styles @ size_styles @ weight_styles @ color_styles @ align_styles) in 66 66 let final_classes = match classes with 67 - | Some c -> Tailwind.tw [text_classes; c] 67 + | Some c -> Tailwind.Css.tw [text_classes; c] 68 68 | None -> text_classes 69 69 in 70 70 span ~classes:final_classes [Htmlit.El.txt text_content]
+3 -1
lib/tailwind/css.ml
··· 16 16 | [] -> true 17 17 | _ -> false 18 18 19 - let of_strings ss = ss 19 + let of_strings ss = ss 20 + 21 + let tw = concat
+4 -1
lib/tailwind/css.mli
··· 25 25 val is_empty : t -> bool 26 26 27 27 (** Create CSS classes from a list of strings *) 28 - val of_strings : string list -> t 28 + val of_strings : string list -> t 29 + 30 + (** Combine multiple CSS classes (alias for concat) *) 31 + val tw : t list -> t
+30
lib/tailwind/effects.ml
··· 128 128 | `Out -> "ease-out" 129 129 | `In_out -> "ease-in-out" 130 130 in 131 + Css.make class_name 132 + 133 + (* Text shadow utilities *) 134 + let text_shadow shadow_size = 135 + let class_name = match shadow_size with 136 + | `None -> "text-shadow-none" 137 + | `Sm -> "text-shadow-sm" 138 + | `Base -> "text-shadow" 139 + | `Lg -> "text-shadow-lg" 140 + | `Xl -> "text-shadow-xl" 141 + in 142 + Css.make class_name 143 + 144 + (* Mask utilities *) 145 + let mask mask_type = 146 + let class_name = match mask_type with 147 + | `Auto -> "mask-auto" 148 + | `Cover -> "mask-cover" 149 + | `Contain -> "mask-contain" 150 + in 151 + Css.make class_name 152 + 153 + (* 3D perspective *) 154 + let perspective perspective_type = 155 + let class_name = match perspective_type with 156 + | `None -> "perspective-none" 157 + | `Distant -> "perspective-distant" 158 + | `Normal -> "perspective-normal" 159 + | `Near -> "perspective-near" 160 + in 131 161 Css.make class_name
+10 -1
lib/tailwind/effects.mli
··· 102 102 val duration : int -> Css.t 103 103 104 104 (** Ease timing functions *) 105 - val ease : timing_function -> Css.t 105 + val ease : timing_function -> Css.t 106 + 107 + (** Text shadow utilities *) 108 + val text_shadow : [`None | `Sm | `Base | `Lg | `Xl] -> Css.t 109 + 110 + (** Mask utilities *) 111 + val mask : [`Auto | `Cover | `Contain] -> Css.t 112 + 113 + (** 3D perspective *) 114 + val perspective : [`None | `Distant | `Normal | `Near] -> Css.t
+20 -1
lib/tailwind/layout.ml
··· 101 101 let h_full = Css.make "h-full" 102 102 let h_screen = Css.make "h-screen" 103 103 let h_auto = Css.make "h-auto" 104 - let h_fit = Css.make "h-fit" 104 + let h_fit = Css.make "h-fit" 105 + 106 + (* Accessibility utilities *) 107 + let sr_only = Css.make "sr-only" 108 + 109 + let focus_ring ?color ?width () = 110 + let base_classes = [ 111 + Css.make "focus:outline-none"; 112 + Css.make "focus:ring-2"; 113 + Css.make "focus:ring-offset-2"; 114 + ] in 115 + let color_class = match color with 116 + | Some c -> [Color.ring c] 117 + | None -> [Css.make "focus:ring-blue-500"] 118 + in 119 + let width_class = match width with 120 + | Some _ -> [] (* Could implement width variations *) 121 + | None -> [] 122 + in 123 + Css.concat (base_classes @ color_class @ width_class)
+8
lib/tailwind/layout.mli
··· 69 69 (** Convert to CSS class *) 70 70 val to_class : t -> Css.t 71 71 72 + (** Accessibility utilities *) 73 + 74 + (** Screen reader only (visually hidden but accessible) *) 75 + val sr_only : Css.t 76 + 77 + (** Focus ring utility *) 78 + val focus_ring : ?color:Color.t -> ?width:Effects.border_width -> unit -> Css.t 79 + 72 80 (** Common width utilities *) 73 81 val w_full : Css.t 74 82 val w_screen : Css.t
-90
lib/tailwind/tailwind.ml
··· 1 1 type t = Css.t 2 2 3 - (* Module aliases *) 4 3 module Css = Css 5 4 module Color = Color 6 5 module Size = Size ··· 17 16 module Reset = Reset 18 17 module Patterns = Patterns 19 18 20 - (* Convenience aliases *) 21 - module C = Color 22 - module S = Spacing 23 - module E = Effects 24 - module T = Typography 25 - module F = Flexbox 26 - module G = Grid 27 - module P = Patterns 28 - module R = Reset 29 - 30 - let tw classes = Css.concat classes 31 - 32 - let class_list pairs = 33 - List.fold_left (fun acc (classes, condition) -> 34 - if condition then Css.combine acc classes else acc 35 - ) Css.empty pairs 36 - 37 19 let to_string = Css.to_string 38 - 39 - (* Core utility functions *) 40 - 41 - let sr_only = 42 - tw [ 43 - Css.make "sr-only"; 44 - ] 45 - 46 - let focus_ring ?color ?width () = 47 - let base_classes = [ 48 - Css.make "focus:outline-none"; 49 - Css.make "focus:ring-2"; 50 - Css.make "focus:ring-offset-2"; 51 - ] in 52 - let color_class = match color with 53 - | Some c -> [Color.ring c] 54 - | None -> [Css.make "focus:ring-blue-500"] 55 - in 56 - let width_class = match width with 57 - | Some _ -> [] (* Could implement width variations *) 58 - | None -> [] 59 - in 60 - tw (base_classes @ color_class @ width_class) 61 - 62 - 63 - module V4 = struct 64 - let container_query size classes = 65 - let container_class = match size with 66 - | `Xs -> "@xs:" 67 - | `Sm -> "@sm:" 68 - | `Md -> "@md:" 69 - | `Lg -> "@lg:" 70 - | `Xl -> "@xl:" 71 - | `Xl2 -> "@2xl:" 72 - | `Xl3 -> "@3xl:" 73 - | `Xl4 -> "@4xl:" 74 - | `Xl5 -> "@5xl:" 75 - | `Xl6 -> "@6xl:" 76 - | `Xl7 -> "@7xl:" 77 - in 78 - Css.make (container_class ^ Css.to_string classes) 79 - 80 - let starting_style classes = 81 - Css.make ("@starting-style " ^ Css.to_string classes) 82 - 83 - let text_shadow shadow_size = 84 - let class_name = match shadow_size with 85 - | `None -> "text-shadow-none" 86 - | `Sm -> "text-shadow-sm" 87 - | `Base -> "text-shadow" 88 - | `Lg -> "text-shadow-lg" 89 - | `Xl -> "text-shadow-xl" 90 - in 91 - Css.make class_name 92 - 93 - let mask mask_type = 94 - let class_name = match mask_type with 95 - | `Auto -> "mask-auto" 96 - | `Cover -> "mask-cover" 97 - | `Contain -> "mask-contain" 98 - in 99 - Css.make class_name 100 - 101 - let perspective perspective_type = 102 - let class_name = match perspective_type with 103 - | `None -> "perspective-none" 104 - | `Distant -> "perspective-distant" 105 - | `Normal -> "perspective-normal" 106 - | `Near -> "perspective-near" 107 - in 108 - Css.make class_name 109 - end
-41
lib/tailwind/tailwind.mli
··· 20 20 module Reset = Reset 21 21 module Patterns = Patterns 22 22 23 - (** Convenience aliases for shorter imports *) 24 - module C = Color 25 - module S = Spacing 26 - module E = Effects 27 - module T = Typography 28 - module F = Flexbox 29 - module G = Grid 30 - module P = Patterns 31 - module R = Reset 32 - 33 - (** Combine multiple CSS classes *) 34 - val tw : Css.t list -> Css.t 35 - 36 - (** Conditionally include classes *) 37 - val class_list : (Css.t * bool) list -> Css.t 38 - 39 23 (** Convert CSS classes to string *) 40 24 val to_string : t -> string 41 25 42 - (** Core utility functions *) 43 - 44 - (** Screen reader only (visually hidden but accessible) *) 45 - val sr_only : t 46 - 47 - (** Focus ring utility *) 48 - val focus_ring : ?color:Color.t -> ?width:Effects.border_width -> unit -> t 49 - 50 - (** V4 specific features *) 51 - module V4 : sig 52 - (** Container query support *) 53 - val container_query : Responsive.container_size -> t -> t 54 - 55 - (** Starting style animation *) 56 - val starting_style : t -> t 57 - 58 - (** Text shadow utilities *) 59 - val text_shadow : [`None | `Sm | `Base | `Lg | `Xl] -> t 60 - 61 - (** Mask utilities *) 62 - val mask : [`Auto | `Cover | `Contain] -> t 63 - 64 - (** 3D perspective *) 65 - val perspective : [`None | `Distant | `Normal | `Near] -> t 66 - end
+2 -1
lib/tailwind/variants.ml
··· 98 98 let first classes = Css.make ("first:" ^ Css.to_string classes) 99 99 let last classes = Css.make ("last:" ^ Css.to_string classes) 100 100 let odd classes = Css.make ("odd:" ^ Css.to_string classes) 101 - let even classes = Css.make ("even:" ^ Css.to_string classes) 101 + let even classes = Css.make ("even:" ^ Css.to_string classes) 102 + let starting_style classes = Css.make ("@starting-style:" ^ Css.to_string classes)
+2 -1
lib/tailwind/variants.mli
··· 103 103 val first : Css.t -> Css.t 104 104 val last : Css.t -> Css.t 105 105 val odd : Css.t -> Css.t 106 - val even : Css.t -> Css.t 106 + val even : Css.t -> Css.t 107 + val starting_style : Css.t -> Css.t
+1 -6
test/dune
··· 1 - (executable 2 - (public_name test_tailwind) 1 + (test 3 2 (name test_runner) 4 3 (package tailwind) 5 4 (modules test_runner test_simple) 6 5 (libraries tailwind tailwind-html alcotest)) 7 - 8 - (rule 9 - (alias runtest) 10 - (action (run ./test_runner.exe)))
+1 -1
test/test_simple.ml
··· 8 8 Alcotest.(check string) "basic combination" "p-4 m-2" (Css.to_string combined); 9 9 10 10 (* Test tw function *) 11 - let classes = tw [css1; css2] in 11 + let classes = Css.tw [css1; css2] in 12 12 Alcotest.(check string) "tw function" "p-4 m-2" (Css.to_string classes); 13 13 14 14 (* Test patterns *)
+2 -2
test/test_tailwind.ml
··· 1 1 open Tailwind 2 2 3 3 let test_tw_combinator () = 4 - let classes = tw [ 4 + let classes = Css.tw [ 5 5 Color.bg (Color.make `Blue ~variant:`V500 ()); 6 6 Effects.rounded_md; 7 7 Spacing.(to_class (p (Size.rem 1.0))); ··· 38 38 Alcotest.(check string) "screen reader only" "sr-only" result 39 39 40 40 let test_module_integration () = 41 - let complex_button = tw [ 41 + let complex_button = Css.tw [ 42 42 Color.bg (Color.make `Blue ~variant:`V500 ()); 43 43 Color.text (Color.make `White ()); 44 44 Spacing.(to_class (px (Size.rem 1.0)));