Tailwind classes in OCaml

Compare changes

Choose any two refs to compare.

+7
.agent/CLAUDE.md
···
+
My goal is to build a high quality professions OCaml library to generate
+
Tailwind CSS components. Build a core `tailwind` library that serialises the
+
CSS into strings. Then build a `tailwind-html` library that uses the Htmlit
+
OCaml HTML generation library https://github.com/dbuenzli/htmlit for common
+
components.
+
+
You can find full Tailwind docs in tailwind-llms.txt in this directory.
+1422
.agent/tailwind-llms.txt
···
+
# Tailwind CSS v4 LLM Development Guidelines
+
+
You are an expert web developer specializing in Tailwind CSS v4. Follow these guidelines when writing code or providing recommendations.
+
+
## Core Principles
+
+
Tailwind CSS v4 is a complete rewrite with a new high-performance Oxide engine, CSS-first configuration, and modern web platform features. It requires modern browsers (Safari 16.4+, Chrome 111+, Firefox 128+) and is NOT compatible with older browsers.
+
+
## Installation & Setup
+
+
### Basic Setup
+
```css
+
/* styles.css */
+
@import "tailwindcss";
+
```
+
+
### With Vite
+
```js
+
// vite.config.js
+
import { defineConfig } from 'vite'
+
import tailwindcss from '@tailwindcss/vite'
+
+
export default defineConfig({
+
plugins: [tailwindcss()]
+
})
+
```
+
+
### Package Installation
+
```bash
+
npm install tailwindcss@next @tailwindcss/vite@next
+
```
+
+
## Configuration (CSS-First)
+
+
**IMPORTANT**: v4 uses CSS-first configuration, NOT JavaScript config files. Use the `@theme` directive in your CSS file:
+
+
```css
+
@import "tailwindcss";
+
+
@theme {
+
/* Colors (use OKLCH for wider gamut) */
+
--color-brand-50: oklch(0.98 0.01 142.12);
+
--color-brand-500: oklch(0.64 0.15 142.12);
+
--color-brand-900: oklch(0.25 0.08 142.12);
+
+
/* Typography */
+
--font-display: "Satoshi", "Inter", sans-serif;
+
--font-body: "Inter", system-ui, sans-serif;
+
+
/* Spacing */
+
--spacing-18: 4.5rem;
+
--spacing-72: 18rem;
+
+
/* Breakpoints */
+
--breakpoint-3xl: 1920px;
+
--breakpoint-4xl: 2560px;
+
+
/* Shadows */
+
--shadow-brutal: 8px 8px 0px 0px #000;
+
+
/* Animation */
+
--animate-wiggle: wiggle 1s ease-in-out infinite;
+
}
+
+
/* Define keyframes for animations */
+
@keyframes wiggle {
+
0%, 100% { transform: rotate(-3deg); }
+
50% { transform: rotate(3deg); }
+
}
+
```
+
+
### Legacy Config Support (if needed)
+
```css
+
@import "tailwindcss";
+
@config "./tailwind.config.js";
+
```
+
+
## Breaking Changes from v3
+
+
### Import Changes
+
- โŒ `@tailwind base; @tailwind components; @tailwind utilities;`
+
- โœ… `@import "tailwindcss";`
+
+
### Removed Utilities
+
- `text-opacity-*` โ†’ Use `text-{color}/{opacity}` instead
+
- `bg-opacity-*` โ†’ Use `bg-{color}/{opacity}` instead
+
- `border-opacity-*` โ†’ Use `border-{color}/{opacity}` instead
+
- `flex-grow-*` โ†’ Use `grow-*`
+
- `flex-shrink-*` โ†’ Use `shrink-*`
+
- `decoration-slice` โ†’ Use `box-decoration-slice`
+
+
### Renamed Utilities
+
- `shadow-sm` โ†’ `shadow-xs`
+
- `rounded-sm` โ†’ `rounded-xs`
+
- `blur-sm` โ†’ `blur-xs`
+
- `bg-gradient-*` โ†’ `bg-linear-*`
+
+
### Default Behavior Changes
+
- **Border**: No longer defaults to gray-200, uses `currentColor`
+
- **Ring**: Changed from 3px blue to 1px `currentColor`
+
- **Outline**: Now 1px by default for consistency
+
+
## Custom Utilities
+
+
Use the `@utility` directive instead of `@layer utilities`:
+
+
```css
+
@utility btn {
+
padding: 0.5rem 1rem;
+
border-radius: 0.375rem;
+
font-weight: 500;
+
transition: all 0.2s;
+
}
+
+
@utility btn-primary {
+
background: var(--color-blue-600);
+
color: white;
+
+
&:hover {
+
background: var(--color-blue-700);
+
}
+
}
+
+
/* Functional utilities with parameters */
+
@utility margin-auto {
+
margin: auto;
+
}
+
+
@utility flex-center {
+
display: flex;
+
justify-content: center;
+
align-items: center;
+
}
+
```
+
+
## Custom Variants
+
+
```css
+
@custom-variant theme-dark {
+
&:where([data-theme="dark"] *) {
+
@slot;
+
}
+
}
+
+
@custom-variant any-hover {
+
@media (any-hover: hover) {
+
&:hover {
+
@slot;
+
}
+
}
+
}
+
```
+
+
## New Features in v4
+
+
### Container Queries (Built-in)
+
```html
+
<div class="@container">
+
<div class="grid grid-cols-1 @sm:grid-cols-2 @lg:grid-cols-3">
+
<div class="@min-w-64:text-lg @max-w-96:bg-blue-100">
+
Responsive to container size
+
</div>
+
</div>
+
</div>
+
```
+
+
### 3D Transforms
+
```html
+
<div class="perspective-1000">
+
<div class="rotate-x-45 rotate-y-12 scale-z-110 translate-z-24 transform-3d">
+
3D transformed element
+
</div>
+
</div>
+
```
+
+
### Enhanced Gradients
+
```html
+
<!-- Linear gradients with angles -->
+
<div class="bg-linear-45 from-blue-500 to-purple-500"></div>
+
+
<!-- Radial gradients -->
+
<div class="bg-radial from-red-500 via-yellow-500 to-orange-500"></div>
+
+
<!-- Conic gradients -->
+
<div class="bg-conic from-pink-500 via-blue-500 to-green-500"></div>
+
```
+
+
### Text Shadows
+
```html
+
<h1 class="text-shadow-lg text-shadow-blue-500/50">
+
Text with colored shadow
+
</h1>
+
```
+
+
### Mask Utilities
+
```html
+
<div class="mask-radial mask-cover">
+
<img src="image.jpg" alt="Masked image" />
+
</div>
+
```
+
+
### New Variants
+
+
#### @starting-style (for animations)
+
```html
+
<div class="opacity-100 @starting-style:opacity-0 transition-opacity">
+
Animates in on mount
+
</div>
+
```
+
+
#### not-* variant
+
```html
+
<div class="bg-blue-500 not-hover:bg-gray-500">
+
Blue except when hovering
+
</div>
+
```
+
+
#### nth-* variants
+
```html
+
<div class="nth-2:bg-red-500 nth-odd:bg-blue-500">
+
Nth child styling
+
</div>
+
```
+
+
#### inert variant
+
```html
+
<div class="inert:opacity-50 inert:pointer-events-none">
+
Styled when inert
+
</div>
+
```
+
+
#### in-* variant (like group-* but without group class)
+
```html
+
<article>
+
<h2 class="in-article:text-lg">Styled when inside article</h2>
+
</article>
+
```
+
+
### Modern Color System
+
v4 uses OKLCH color space for wider gamut support:
+
+
```css
+
@theme {
+
--color-brand-primary: oklch(0.7 0.15 180);
+
--color-brand-accent: oklch(0.8 0.2 45);
+
}
+
```
+
+
## Multi-Theme Strategy
+
+
```css
+
@import "tailwindcss";
+
+
@theme {
+
--color-primary: oklch(0.5 0.2 240);
+
--color-background: oklch(0.98 0.01 240);
+
}
+
+
@layer base {
+
[data-theme='dark'] {
+
--color-primary: oklch(0.7 0.2 240);
+
--color-background: oklch(0.15 0.02 240);
+
}
+
+
[data-theme='high-contrast'] {
+
--color-primary: oklch(0.0 0 0);
+
--color-background: oklch(1.0 0 0);
+
}
+
}
+
```
+
+
## Best Practices
+
+
### 1. Use CSS Variables for Dynamic Values
+
```html
+
<div class="bg-[var(--dynamic-color)] text-[var(--dynamic-size)]">
+
Dynamic styling
+
</div>
+
```
+
+
### 2. Leverage the New Color System
+
```html
+
<!-- Better contrast and vibrancy with OKLCH -->
+
<div class="bg-blue-500 text-white">
+
Vivid colors on modern displays
+
</div>
+
```
+
+
### 3. Container Queries for True Responsive Design
+
```html
+
<div class="@container">
+
<div class="p-4 @lg:p-8 @xl:p-12">
+
Responds to container, not viewport
+
</div>
+
</div>
+
```
+
+
### 4. Modern CSS Features
+
```html
+
<!-- Native cascade layers -->
+
<div class="layer-[utilities]:z-10">
+
Proper layer management
+
</div>
+
+
<!-- Color mixing -->
+
<div class="bg-blue-500/50">
+
Uses color-mix() under the hood
+
</div>
+
```
+
+
## Performance Optimizations
+
+
v4's Oxide engine provides:
+
- 5x faster full builds
+
- 100x faster incremental builds
+
- Automatic content detection
+
- Built-in import handling
+
- Native vendor prefixing
+
+
## File Organization
+
+
```
+
src/
+
โ”œโ”€โ”€ styles/
+
โ”‚ โ”œโ”€โ”€ main.css # @import "tailwindcss" + @theme
+
โ”‚ โ”œโ”€โ”€ components.css # @utility definitions
+
โ”‚ โ””โ”€โ”€ utilities.css # Additional @utility definitions
+
โ””โ”€โ”€ components/
+
โ””โ”€โ”€ *.vue/jsx/html # Your components
+
```
+
+
## Common Patterns
+
+
### Theme-aware Components
+
```css
+
@utility card {
+
background: var(--color-background);
+
border: 1px solid var(--color-border);
+
border-radius: 0.5rem;
+
padding: 1.5rem;
+
box-shadow: var(--shadow-sm);
+
}
+
```
+
+
### Responsive Typography
+
```html
+
<h1 class="text-2xl @sm:text-3xl @lg:text-4xl @xl:text-5xl">
+
Container-responsive heading
+
</h1>
+
```
+
+
### Animation with @starting-style
+
```html
+
<div class="translate-y-0 @starting-style:translate-y-full transition-transform duration-500">
+
Slides up on mount
+
</div>
+
```
+
+
## Debugging Tips
+
+
1. **Use browser dev tools** to inspect CSS variables
+
2. **Check cascade layers** in dev tools
+
3. **Verify modern browser support** for OKLCH colors
+
4. **Use @reference** for CSS modules/component styles
+
5. **Restart dev server** after major theme changes
+
+
## Migration from v3
+
+
1. Replace `@tailwind` directives with `@import "tailwindcss"`
+
2. Move config from JS to CSS using `@theme`
+
3. Update deprecated utility classes
+
4. Replace `@layer utilities` with `@utility`
+
5. Test in modern browsers only
+
6. Use the official upgrade tool: `npx @tailwindcss/upgrade@next`
+
+
## Complete Utility Class Reference
+
+
### Layout
+
+
#### Display
+
```
+
block, inline-block, inline, flex, inline-flex, table, inline-table, table-caption, table-cell, table-column, table-column-group, table-footer-group, table-header-group, table-row-group, table-row, flow-root, grid, inline-grid, contents, list-item, hidden
+
```
+
+
#### Position
+
```
+
static, fixed, absolute, relative, sticky
+
```
+
+
#### Top/Right/Bottom/Left
+
```
+
inset-0, inset-x-0, inset-y-0, start-0, end-0, top-0, right-0, bottom-0, left-0
+
inset-px, inset-x-px, inset-y-px, start-px, end-px, top-px, right-px, bottom-px, left-px
+
inset-0.5, inset-1, inset-1.5, inset-2, inset-2.5, inset-3, inset-3.5, inset-4, inset-5, inset-6, inset-7, inset-8, inset-9, inset-10, inset-11, inset-12, inset-14, inset-16, inset-20, inset-24, inset-28, inset-32, inset-36, inset-40, inset-44, inset-48, inset-52, inset-56, inset-60, inset-64, inset-72, inset-80, inset-96
+
inset-auto, inset-1/2, inset-1/3, inset-2/3, inset-1/4, inset-2/4, inset-3/4, inset-full
+
```
+
+
#### Visibility & Z-Index
+
```
+
visible, invisible, collapse
+
z-0, z-10, z-20, z-30, z-40, z-50, z-auto
+
```
+
+
#### Overflow
+
```
+
overflow-auto, overflow-hidden, overflow-clip, overflow-visible, overflow-scroll
+
overflow-x-auto, overflow-x-hidden, overflow-x-clip, overflow-x-visible, overflow-x-scroll
+
overflow-y-auto, overflow-y-hidden, overflow-y-clip, overflow-y-visible, overflow-y-scroll
+
```
+
+
### Flexbox & Grid
+
+
#### Flex Direction
+
```
+
flex-row, flex-row-reverse, flex-col, flex-col-reverse
+
```
+
+
#### Flex Wrap
+
```
+
flex-wrap, flex-wrap-reverse, flex-nowrap
+
```
+
+
#### Flex
+
```
+
flex-1, flex-auto, flex-initial, flex-none
+
```
+
+
#### Grow & Shrink
+
```
+
grow, grow-0, shrink, shrink-0
+
```
+
+
#### Order
+
```
+
order-1, order-2, order-3, order-4, order-5, order-6, order-7, order-8, order-9, order-10, order-11, order-12, order-first, order-last, order-none
+
```
+
+
#### Grid Template Columns
+
```
+
grid-cols-1, grid-cols-2, grid-cols-3, grid-cols-4, grid-cols-5, grid-cols-6, grid-cols-7, grid-cols-8, grid-cols-9, grid-cols-10, grid-cols-11, grid-cols-12, grid-cols-none, grid-cols-subgrid
+
```
+
+
#### Grid Column Start/End
+
```
+
col-auto, col-span-1, col-span-2, col-span-3, col-span-4, col-span-5, col-span-6, col-span-7, col-span-8, col-span-9, col-span-10, col-span-11, col-span-12, col-span-full
+
col-start-1, col-start-2, col-start-3, col-start-4, col-start-5, col-start-6, col-start-7, col-start-8, col-start-9, col-start-10, col-start-11, col-start-12, col-start-13, col-start-auto
+
col-end-1, col-end-2, col-end-3, col-end-4, col-end-5, col-end-6, col-end-7, col-end-8, col-end-9, col-end-10, col-end-11, col-end-12, col-end-13, col-end-auto
+
```
+
+
#### Grid Template Rows
+
```
+
grid-rows-1, grid-rows-2, grid-rows-3, grid-rows-4, grid-rows-5, grid-rows-6, grid-rows-7, grid-rows-8, grid-rows-9, grid-rows-10, grid-rows-11, grid-rows-12, grid-rows-none, grid-rows-subgrid
+
```
+
+
#### Grid Row Start/End
+
```
+
row-auto, row-span-1, row-span-2, row-span-3, row-span-4, row-span-5, row-span-6, row-span-7, row-span-8, row-span-9, row-span-10, row-span-11, row-span-12, row-span-full
+
row-start-1, row-start-2, row-start-3, row-start-4, row-start-5, row-start-6, row-start-7, row-start-8, row-start-9, row-start-10, row-start-11, row-start-12, row-start-13, row-start-auto
+
row-end-1, row-end-2, row-end-3, row-end-4, row-end-5, row-end-6, row-end-7, row-end-8, row-end-9, row-end-10, row-end-11, row-end-12, row-end-13, row-end-auto
+
```
+
+
#### Gap
+
```
+
gap-0, gap-x-0, gap-y-0, gap-px, gap-x-px, gap-y-px
+
gap-0.5, gap-1, gap-1.5, gap-2, gap-2.5, gap-3, gap-3.5, gap-4, gap-5, gap-6, gap-7, gap-8, gap-9, gap-10, gap-11, gap-12, gap-14, gap-16, gap-20, gap-24, gap-28, gap-32, gap-36, gap-40, gap-44, gap-48, gap-52, gap-56, gap-60, gap-64, gap-72, gap-80, gap-96
+
```
+
+
#### Justify & Align
+
```
+
justify-normal, justify-start, justify-end, justify-center, justify-between, justify-around, justify-evenly, justify-stretch
+
justify-items-start, justify-items-end, justify-items-center, justify-items-stretch
+
justify-self-auto, justify-self-start, justify-self-end, justify-self-center, justify-self-stretch
+
align-items-start, align-items-end, align-items-center, align-items-baseline, align-items-stretch
+
align-content-normal, align-content-center, align-content-start, align-content-end, align-content-between, align-content-around, align-content-evenly, align-content-baseline, align-content-stretch
+
align-self-auto, align-self-start, align-self-end, align-self-center, align-self-stretch, align-self-baseline
+
place-content-center, place-content-start, place-content-end, place-content-between, place-content-around, place-content-evenly, place-content-baseline, place-content-stretch
+
place-items-start, place-items-end, place-items-center, place-items-baseline, place-items-stretch
+
place-self-auto, place-self-start, place-self-end, place-self-center, place-self-stretch
+
```
+
+
### Spacing
+
+
#### Padding
+
```
+
p-0, p-px, p-0.5, p-1, p-1.5, p-2, p-2.5, p-3, p-3.5, p-4, p-5, p-6, p-7, p-8, p-9, p-10, p-11, p-12, p-14, p-16, p-20, p-24, p-28, p-32, p-36, p-40, p-44, p-48, p-52, p-56, p-60, p-64, p-72, p-80, p-96
+
px-0, py-0, pl-0, pr-0, pt-0, pb-0, ps-0, pe-0
+
```
+
+
#### Margin
+
```
+
m-0, m-px, m-0.5, m-1, m-1.5, m-2, m-2.5, m-3, m-3.5, m-4, m-5, m-6, m-7, m-8, m-9, m-10, m-11, m-12, m-14, m-16, m-20, m-24, m-28, m-32, m-36, m-40, m-44, m-48, m-52, m-56, m-60, m-64, m-72, m-80, m-96, m-auto
+
mx-0, my-0, ml-0, mr-0, mt-0, mb-0, ms-0, me-0
+
-m-0, -m-px, -m-0.5, -m-1, -m-1.5, -m-2, -m-2.5, -m-3, -m-3.5, -m-4, -m-5, -m-6, -m-7, -m-8, -m-9, -m-10, -m-11, -m-12, -m-14, -m-16, -m-20, -m-24, -m-28, -m-32, -m-36, -m-40, -m-44, -m-48, -m-52, -m-56, -m-60, -m-64, -m-72, -m-80, -m-96
+
```
+
+
#### Space Between
+
```
+
space-x-0, space-x-px, space-x-0.5, space-x-1, space-x-1.5, space-x-2, space-x-2.5, space-x-3, space-x-3.5, space-x-4, space-x-5, space-x-6, space-x-7, space-x-8, space-x-9, space-x-10, space-x-11, space-x-12, space-x-14, space-x-16, space-x-20, space-x-24, space-x-28, space-x-32, space-x-36, space-x-40, space-x-44, space-x-48, space-x-52, space-x-56, space-x-60, space-x-64, space-x-72, space-x-80, space-x-96, space-x-reverse
+
space-y-0, space-y-px, space-y-0.5, space-y-1, space-y-1.5, space-y-2, space-y-2.5, space-y-3, space-y-3.5, space-y-4, space-y-5, space-y-6, space-y-7, space-y-8, space-y-9, space-y-10, space-y-11, space-y-12, space-y-14, space-y-16, space-y-20, space-y-24, space-y-28, space-y-32, space-y-36, space-y-40, space-y-44, space-y-48, space-y-52, space-y-56, space-y-60, space-y-64, space-y-72, space-y-80, space-y-96, space-y-reverse
+
```
+
+
### Sizing
+
+
#### Width
+
```
+
w-0, w-px, w-0.5, w-1, w-1.5, w-2, w-2.5, w-3, w-3.5, w-4, w-5, w-6, w-7, w-8, w-9, w-10, w-11, w-12, w-14, w-16, w-20, w-24, w-28, w-32, w-36, w-40, w-44, w-48, w-52, w-56, w-60, w-64, w-72, w-80, w-96, w-auto, w-1/2, w-1/3, w-2/3, w-1/4, w-2/4, w-3/4, w-1/5, w-2/5, w-3/5, w-4/5, w-1/6, w-2/6, w-3/6, w-4/6, w-5/6, w-1/12, w-2/12, w-3/12, w-4/12, w-5/12, w-6/12, w-7/12, w-8/12, w-9/12, w-10/12, w-11/12, w-full, w-screen, w-svw, w-lvw, w-dvw, w-min, w-max, w-fit
+
```
+
+
#### Height
+
```
+
h-0, h-px, h-0.5, h-1, h-1.5, h-2, h-2.5, h-3, h-3.5, h-4, h-5, h-6, h-7, h-8, h-9, h-10, h-11, h-12, h-14, h-16, h-20, h-24, h-28, h-32, h-36, h-40, h-44, h-48, h-52, h-56, h-60, h-64, h-72, h-80, h-96, h-auto, h-1/2, h-1/3, h-2/3, h-1/4, h-2/4, h-3/4, h-1/5, h-2/5, h-3/5, h-4/5, h-1/6, h-2/6, h-3/6, h-4/6, h-5/6, h-full, h-screen, h-svh, h-lvh, h-dvh, h-min, h-max, h-fit
+
```
+
+
#### Size (Width + Height)
+
```
+
size-0, size-px, size-0.5, size-1, size-1.5, size-2, size-2.5, size-3, size-3.5, size-4, size-5, size-6, size-7, size-8, size-9, size-10, size-11, size-12, size-14, size-16, size-20, size-24, size-28, size-32, size-36, size-40, size-44, size-48, size-52, size-56, size-60, size-64, size-72, size-80, size-96, size-auto, size-1/2, size-1/3, size-2/3, size-1/4, size-2/4, size-3/4, size-1/5, size-2/5, size-3/5, size-4/5, size-1/6, size-2/6, size-3/6, size-4/6, size-5/6, size-1/12, size-2/12, size-3/12, size-4/12, size-5/12, size-6/12, size-7/12, size-8/12, size-9/12, size-10/12, size-11/12, size-full, size-min, size-max, size-fit
+
```
+
+
#### Min/Max Width
+
```
+
min-w-0, min-w-full, min-w-min, min-w-max, min-w-fit
+
max-w-0, max-w-xs, max-w-sm, max-w-md, max-w-lg, max-w-xl, max-w-2xl, max-w-3xl, max-w-4xl, max-w-5xl, max-w-6xl, max-w-7xl, max-w-full, max-w-min, max-w-max, max-w-fit, max-w-prose, max-w-screen-sm, max-w-screen-md, max-w-screen-lg, max-w-screen-xl, max-w-screen-2xl
+
```
+
+
#### Min/Max Height
+
```
+
min-h-0, min-h-full, min-h-screen, min-h-svh, min-h-lvh, min-h-dvh, min-h-min, min-h-max, min-h-fit
+
max-h-0, max-h-px, max-h-0.5, max-h-1, max-h-1.5, max-h-2, max-h-2.5, max-h-3, max-h-3.5, max-h-4, max-h-5, max-h-6, max-h-7, max-h-8, max-h-9, max-h-10, max-h-11, max-h-12, max-h-14, max-h-16, max-h-20, max-h-24, max-h-28, max-h-32, max-h-36, max-h-40, max-h-44, max-h-48, max-h-52, max-h-56, max-h-60, max-h-64, max-h-72, max-h-80, max-h-96, max-h-full, max-h-screen, max-h-svh, max-h-lvh, max-h-dvh, max-h-min, max-h-max, max-h-fit
+
```
+
+
### Typography
+
+
#### Font Family
+
```
+
font-sans, font-serif, font-mono
+
```
+
+
#### Font Size
+
```
+
text-xs, text-sm, text-base, text-lg, text-xl, text-2xl, text-3xl, text-4xl, text-5xl, text-6xl, text-7xl, text-8xl, text-9xl
+
```
+
+
#### Font Weight
+
```
+
font-thin, font-extralight, font-light, font-normal, font-medium, font-semibold, font-bold, font-extrabold, font-black
+
```
+
+
#### Font Style
+
```
+
italic, not-italic
+
```
+
+
#### Font Variant Numeric
+
```
+
normal-nums, ordinal, slashed-zero, lining-nums, oldstyle-nums, proportional-nums, tabular-nums, diagonal-fractions, stacked-fractions
+
```
+
+
#### Font Stretch (NEW in v4)
+
```
+
font-stretch-ultra-condensed, font-stretch-extra-condensed, font-stretch-condensed, font-stretch-semi-condensed, font-stretch-normal, font-stretch-semi-expanded, font-stretch-expanded, font-stretch-extra-expanded, font-stretch-ultra-expanded
+
```
+
+
#### Letter Spacing
+
```
+
tracking-tighter, tracking-tight, tracking-normal, tracking-wide, tracking-wider, tracking-widest
+
```
+
+
#### Line Clamp
+
```
+
line-clamp-1, line-clamp-2, line-clamp-3, line-clamp-4, line-clamp-5, line-clamp-6, line-clamp-none
+
```
+
+
#### Line Height
+
```
+
leading-3, leading-4, leading-5, leading-6, leading-7, leading-8, leading-9, leading-10, leading-none, leading-tight, leading-snug, leading-normal, leading-relaxed, leading-loose
+
```
+
+
#### List Style
+
```
+
list-none, list-disc, list-decimal, list-inside, list-outside
+
```
+
+
#### Text Align
+
```
+
text-left, text-center, text-right, text-justify, text-start, text-end
+
```
+
+
#### Text Color
+
```
+
text-inherit, text-current, text-transparent, text-black, text-white
+
text-slate-50, text-slate-100, text-slate-200, text-slate-300, text-slate-400, text-slate-500, text-slate-600, text-slate-700, text-slate-800, text-slate-900, text-slate-950
+
text-gray-50, text-gray-100, text-gray-200, text-gray-300, text-gray-400, text-gray-500, text-gray-600, text-gray-700, text-gray-800, text-gray-900, text-gray-950
+
text-zinc-50, text-zinc-100, text-zinc-200, text-zinc-300, text-zinc-400, text-zinc-500, text-zinc-600, text-zinc-700, text-zinc-800, text-zinc-900, text-zinc-950
+
text-neutral-50, text-neutral-100, text-neutral-200, text-neutral-300, text-neutral-400, text-neutral-500, text-neutral-600, text-neutral-700, text-neutral-800, text-neutral-900, text-neutral-950
+
text-stone-50, text-stone-100, text-stone-200, text-stone-300, text-stone-400, text-stone-500, text-stone-600, text-stone-700, text-stone-800, text-stone-900, text-stone-950
+
text-red-50, text-red-100, text-red-200, text-red-300, text-red-400, text-red-500, text-red-600, text-red-700, text-red-800, text-red-900, text-red-950
+
text-orange-50, text-orange-100, text-orange-200, text-orange-300, text-orange-400, text-orange-500, text-orange-600, text-orange-700, text-orange-800, text-orange-900, text-orange-950
+
text-amber-50, text-amber-100, text-amber-200, text-amber-300, text-amber-400, text-amber-500, text-amber-600, text-amber-700, text-amber-800, text-amber-900, text-amber-950
+
text-yellow-50, text-yellow-100, text-yellow-200, text-yellow-300, text-yellow-400, text-yellow-500, text-yellow-600, text-yellow-700, text-yellow-800, text-yellow-900, text-yellow-950
+
text-lime-50, text-lime-100, text-lime-200, text-lime-300, text-lime-400, text-lime-500, text-lime-600, text-lime-700, text-lime-800, text-lime-900, text-lime-950
+
text-green-50, text-green-100, text-green-200, text-green-300, text-green-400, text-green-500, text-green-600, text-green-700, text-green-800, text-green-900, text-green-950
+
text-emerald-50, text-emerald-100, text-emerald-200, text-emerald-300, text-emerald-400, text-emerald-500, text-emerald-600, text-emerald-700, text-emerald-800, text-emerald-900, text-emerald-950
+
text-teal-50, text-teal-100, text-teal-200, text-teal-300, text-teal-400, text-teal-500, text-teal-600, text-teal-700, text-teal-800, text-teal-900, text-teal-950
+
text-cyan-50, text-cyan-100, text-cyan-200, text-cyan-300, text-cyan-400, text-cyan-500, text-cyan-600, text-cyan-700, text-cyan-800, text-cyan-900, text-cyan-950
+
text-sky-50, text-sky-100, text-sky-200, text-sky-300, text-sky-400, text-sky-500, text-sky-600, text-sky-700, text-sky-800, text-sky-900, text-sky-950
+
text-blue-50, text-blue-100, text-blue-200, text-blue-300, text-blue-400, text-blue-500, text-blue-600, text-blue-700, text-blue-800, text-blue-900, text-blue-950
+
text-indigo-50, text-indigo-100, text-indigo-200, text-indigo-300, text-indigo-400, text-indigo-500, text-indigo-600, text-indigo-700, text-indigo-800, text-indigo-900, text-indigo-950
+
text-violet-50, text-violet-100, text-violet-200, text-violet-300, text-violet-400, text-violet-500, text-violet-600, text-violet-700, text-violet-800, text-violet-900, text-violet-950
+
text-purple-50, text-purple-100, text-purple-200, text-purple-300, text-purple-400, text-purple-500, text-purple-600, text-purple-700, text-purple-800, text-purple-900, text-purple-950
+
text-fuchsia-50, text-fuchsia-100, text-fuchsia-200, text-fuchsia-300, text-fuchsia-400, text-fuchsia-500, text-fuchsia-600, text-fuchsia-700, text-fuchsia-800, text-fuchsia-900, text-fuchsia-950
+
text-pink-50, text-pink-100, text-pink-200, text-pink-300, text-pink-400, text-pink-500, text-pink-600, text-pink-700, text-pink-800, text-pink-900, text-pink-950
+
text-rose-50, text-rose-100, text-rose-200, text-rose-300, text-rose-400, text-rose-500, text-rose-600, text-rose-700, text-rose-800, text-rose-900, text-rose-950
+
```
+
+
#### Text Decoration
+
```
+
underline, overline, line-through, no-underline
+
decoration-solid, decoration-double, decoration-dotted, decoration-dashed, decoration-wavy
+
decoration-auto, decoration-from-font, decoration-0, decoration-1, decoration-2, decoration-4, decoration-8
+
underline-offset-auto, underline-offset-0, underline-offset-1, underline-offset-2, underline-offset-4, underline-offset-8
+
```
+
+
#### Text Transform
+
```
+
uppercase, lowercase, capitalize, normal-case
+
```
+
+
#### Text Overflow
+
```
+
truncate, text-ellipsis, text-clip
+
```
+
+
#### Text Shadow (NEW in v4)
+
```
+
text-shadow-sm, text-shadow, text-shadow-lg, text-shadow-xl, text-shadow-none
+
```
+
+
#### Overflow Wrap (NEW in v4)
+
```
+
overflow-wrap-normal, overflow-wrap-break-word, overflow-wrap-anywhere
+
```
+
+
#### Vertical Align
+
```
+
align-baseline, align-top, align-middle, align-bottom, align-text-top, align-text-bottom, align-sub, align-super
+
```
+
+
#### Whitespace
+
```
+
whitespace-normal, whitespace-nowrap, whitespace-pre, whitespace-pre-line, whitespace-pre-wrap, whitespace-break-spaces
+
```
+
+
#### Word Break
+
```
+
break-normal, break-words, break-all, break-keep
+
```
+
+
#### Hyphens
+
```
+
hyphens-none, hyphens-manual, hyphens-auto
+
```
+
+
#### Content
+
```
+
content-none
+
```
+
+
### Backgrounds
+
+
#### Background Attachment
+
```
+
bg-fixed, bg-local, bg-scroll
+
```
+
+
#### Background Clip
+
```
+
bg-clip-border, bg-clip-padding, bg-clip-content, bg-clip-text
+
```
+
+
#### Background Color
+
All color utilities work with `bg-` prefix (same as text colors above)
+
+
#### Background Origin
+
```
+
bg-origin-border, bg-origin-padding, bg-origin-content
+
```
+
+
#### Background Position
+
```
+
bg-bottom, bg-center, bg-left, bg-left-bottom, bg-left-top, bg-right, bg-right-bottom, bg-right-top, bg-top
+
```
+
+
#### Background Repeat
+
```
+
bg-repeat, bg-no-repeat, bg-repeat-x, bg-repeat-y, bg-repeat-round, bg-repeat-space
+
```
+
+
#### Background Size
+
```
+
bg-auto, bg-cover, bg-contain
+
```
+
+
#### Background Image
+
```
+
bg-none
+
bg-linear-to-t, bg-linear-to-tr, bg-linear-to-r, bg-linear-to-br, bg-linear-to-b, bg-linear-to-bl, bg-linear-to-l, bg-linear-to-tl
+
```
+
+
#### Enhanced Gradients (NEW in v4)
+
```
+
bg-linear-0, bg-linear-45, bg-linear-90, bg-linear-135, bg-linear-180, bg-linear-225, bg-linear-270, bg-linear-315
+
bg-radial, bg-radial-at-t, bg-radial-at-tr, bg-radial-at-r, bg-radial-at-br, bg-radial-at-b, bg-radial-at-bl, bg-radial-at-l, bg-radial-at-tl, bg-radial-at-c
+
bg-conic, bg-conic-at-t, bg-conic-at-tr, bg-conic-at-r, bg-conic-at-br, bg-conic-at-b, bg-conic-at-bl, bg-conic-at-l, bg-conic-at-tl, bg-conic-at-c
+
```
+
+
#### Gradient Color Stops
+
```
+
from-inherit, from-current, from-transparent, from-black, from-white, from-{color}
+
via-inherit, via-current, via-transparent, via-black, via-white, via-{color}
+
to-inherit, to-current, to-transparent, to-black, to-white, to-{color}
+
```
+
+
### Borders
+
+
#### Border Radius
+
```
+
rounded-none, rounded-xs, rounded-sm, rounded, rounded-md, rounded-lg, rounded-xl, rounded-2xl, rounded-3xl, rounded-full
+
rounded-s-none, rounded-s-xs, rounded-s-sm, rounded-s, rounded-s-md, rounded-s-lg, rounded-s-xl, rounded-s-2xl, rounded-s-3xl
+
rounded-e-none, rounded-e-xs, rounded-e-sm, rounded-e, rounded-e-md, rounded-e-lg, rounded-e-xl, rounded-e-2xl, rounded-e-3xl
+
rounded-t-none, rounded-t-xs, rounded-t-sm, rounded-t, rounded-t-md, rounded-t-lg, rounded-t-xl, rounded-t-2xl, rounded-t-3xl
+
rounded-r-none, rounded-r-xs, rounded-r-sm, rounded-r, rounded-r-md, rounded-r-lg, rounded-r-xl, rounded-r-2xl, rounded-r-3xl
+
rounded-b-none, rounded-b-xs, rounded-b-sm, rounded-b, rounded-b-md, rounded-b-lg, rounded-b-xl, rounded-b-2xl, rounded-b-3xl
+
rounded-l-none, rounded-l-xs, rounded-l-sm, rounded-l, rounded-l-md, rounded-l-lg, rounded-l-xl, rounded-l-2xl, rounded-l-3xl
+
rounded-ss-none, rounded-ss-xs, rounded-ss-sm, rounded-ss, rounded-ss-md, rounded-ss-lg, rounded-ss-xl, rounded-ss-2xl, rounded-ss-3xl
+
rounded-se-none, rounded-se-xs, rounded-se-sm, rounded-se, rounded-se-md, rounded-se-lg, rounded-se-xl, rounded-se-2xl, rounded-se-3xl
+
rounded-ee-none, rounded-ee-xs, rounded-ee-sm, rounded-ee, rounded-ee-md, rounded-ee-lg, rounded-ee-xl, rounded-ee-2xl, rounded-ee-3xl
+
rounded-es-none, rounded-es-xs, rounded-es-sm, rounded-es, rounded-es-md, rounded-es-lg, rounded-es-xl, rounded-es-2xl, rounded-es-3xl
+
rounded-tl-none, rounded-tl-xs, rounded-tl-sm, rounded-tl, rounded-tl-md, rounded-tl-lg, rounded-tl-xl, rounded-tl-2xl, rounded-tl-3xl
+
rounded-tr-none, rounded-tr-xs, rounded-tr-sm, rounded-tr, rounded-tr-md, rounded-tr-lg, rounded-tr-xl, rounded-tr-2xl, rounded-tr-3xl
+
rounded-br-none, rounded-br-xs, rounded-br-sm, rounded-br, rounded-br-md, rounded-br-lg, rounded-br-xl, rounded-br-2xl, rounded-br-3xl
+
rounded-bl-none, rounded-bl-xs, rounded-bl-sm, rounded-bl, rounded-bl-md, rounded-bl-lg, rounded-bl-xl, rounded-bl-2xl, rounded-bl-3xl
+
```
+
+
#### Border Width
+
```
+
border-0, border-2, border-4, border-8, border, border-x, border-y, border-s, border-e, border-t, border-r, border-b, border-l
+
```
+
+
#### Border Color
+
All color utilities work with `border-` prefix (same as text/bg colors)
+
+
#### Border Style
+
```
+
border-solid, border-dashed, border-dotted, border-double, border-hidden, border-none
+
```
+
+
#### Divide Width
+
```
+
divide-x-0, divide-x-2, divide-x-4, divide-x-8, divide-x, divide-y-0, divide-y-2, divide-y-4, divide-y-8, divide-y, divide-x-reverse, divide-y-reverse
+
```
+
+
#### Divide Color
+
All color utilities work with `divide-` prefix
+
+
#### Divide Style
+
```
+
divide-solid, divide-dashed, divide-dotted, divide-double, divide-none
+
```
+
+
#### Outline Width
+
```
+
outline-0, outline-1, outline-2, outline-4, outline-8
+
```
+
+
#### Outline Color
+
All color utilities work with `outline-` prefix
+
+
#### Outline Style
+
```
+
outline-none, outline, outline-dashed, outline-dotted, outline-double
+
```
+
+
#### Outline Offset
+
```
+
outline-offset-0, outline-offset-1, outline-offset-2, outline-offset-4, outline-offset-8
+
```
+
+
#### Ring Width
+
```
+
ring-0, ring-1, ring-2, ring, ring-4, ring-8, ring-inset
+
```
+
+
#### Ring Color
+
All color utilities work with `ring-` prefix
+
+
#### Ring Offset Width
+
```
+
ring-offset-0, ring-offset-1, ring-offset-2, ring-offset-4, ring-offset-8
+
```
+
+
#### Ring Offset Color
+
All color utilities work with `ring-offset-` prefix
+
+
### Effects
+
+
#### Box Shadow
+
```
+
shadow-xs, shadow-sm, shadow, shadow-md, shadow-lg, shadow-xl, shadow-2xl, shadow-inner, shadow-none
+
```
+
+
#### Box Shadow Color
+
All color utilities work with `shadow-` prefix
+
+
#### Drop Shadow (NEW colored support in v4)
+
```
+
drop-shadow-sm, drop-shadow, drop-shadow-md, drop-shadow-lg, drop-shadow-xl, drop-shadow-2xl, drop-shadow-none
+
```
+
+
#### Opacity
+
```
+
opacity-0, opacity-5, opacity-10, opacity-15, opacity-20, opacity-25, opacity-30, opacity-35, opacity-40, opacity-45, opacity-50, opacity-55, opacity-60, opacity-65, opacity-70, opacity-75, opacity-80, opacity-85, opacity-90, opacity-95, opacity-100
+
```
+
+
#### Mix Blend Mode
+
```
+
mix-blend-normal, mix-blend-multiply, mix-blend-screen, mix-blend-overlay, mix-blend-darken, mix-blend-lighten, mix-blend-color-dodge, mix-blend-color-burn, mix-blend-hard-light, mix-blend-soft-light, mix-blend-difference, mix-blend-exclusion, mix-blend-hue, mix-blend-saturation, mix-blend-color, mix-blend-luminosity, mix-blend-plus-darker, mix-blend-plus-lighter
+
```
+
+
#### Background Blend Mode
+
```
+
bg-blend-normal, bg-blend-multiply, bg-blend-screen, bg-blend-overlay, bg-blend-darken, bg-blend-lighten, bg-blend-color-dodge, bg-blend-color-burn, bg-blend-hard-light, bg-blend-soft-light, bg-blend-difference, bg-blend-exclusion, bg-blend-hue, bg-blend-saturation, bg-blend-color, bg-blend-luminosity
+
```
+
+
### Filters
+
+
#### Blur
+
```
+
blur-none, blur-xs, blur-sm, blur, blur-md, blur-lg, blur-xl, blur-2xl, blur-3xl
+
```
+
+
#### Brightness
+
```
+
brightness-0, brightness-50, brightness-75, brightness-90, brightness-95, brightness-100, brightness-105, brightness-110, brightness-125, brightness-150, brightness-200
+
```
+
+
#### Contrast
+
```
+
contrast-0, contrast-50, contrast-75, contrast-100, contrast-125, contrast-150, contrast-200
+
```
+
+
#### Grayscale
+
```
+
grayscale-0, grayscale
+
```
+
+
#### Hue Rotate
+
```
+
hue-rotate-0, hue-rotate-15, hue-rotate-30, hue-rotate-60, hue-rotate-90, hue-rotate-180, -hue-rotate-180, -hue-rotate-90, -hue-rotate-60, -hue-rotate-30, -hue-rotate-15
+
```
+
+
#### Invert
+
```
+
invert-0, invert
+
```
+
+
#### Saturate
+
```
+
saturate-0, saturate-50, saturate-100, saturate-150, saturate-200
+
```
+
+
#### Sepia
+
```
+
sepia-0, sepia
+
```
+
+
#### Backdrop Blur
+
```
+
backdrop-blur-none, backdrop-blur-xs, backdrop-blur-sm, backdrop-blur, backdrop-blur-md, backdrop-blur-lg, backdrop-blur-xl, backdrop-blur-2xl, backdrop-blur-3xl
+
```
+
+
#### Backdrop Brightness
+
```
+
backdrop-brightness-0, backdrop-brightness-50, backdrop-brightness-75, backdrop-brightness-90, backdrop-brightness-95, backdrop-brightness-100, backdrop-brightness-105, backdrop-brightness-110, backdrop-brightness-125, backdrop-brightness-150, backdrop-brightness-200
+
```
+
+
#### Backdrop Contrast
+
```
+
backdrop-contrast-0, backdrop-contrast-50, backdrop-contrast-75, backdrop-contrast-100, backdrop-contrast-125, backdrop-contrast-150, backdrop-contrast-200
+
```
+
+
#### Backdrop Grayscale
+
```
+
backdrop-grayscale-0, backdrop-grayscale
+
```
+
+
#### Backdrop Hue Rotate
+
```
+
backdrop-hue-rotate-0, backdrop-hue-rotate-15, backdrop-hue-rotate-30, backdrop-hue-rotate-60, backdrop-hue-rotate-90, backdrop-hue-rotate-180, -backdrop-hue-rotate-180, -backdrop-hue-rotate-90, -backdrop-hue-rotate-60, -backdrop-hue-rotate-30, -backdrop-hue-rotate-15
+
```
+
+
#### Backdrop Invert
+
```
+
backdrop-invert-0, backdrop-invert
+
```
+
+
#### Backdrop Saturate
+
```
+
backdrop-saturate-0, backdrop-saturate-50, backdrop-saturate-100, backdrop-saturate-150, backdrop-saturate-200
+
```
+
+
#### Backdrop Sepia
+
```
+
backdrop-sepia-0, backdrop-sepia
+
```
+
+
### Masks (NEW in v4)
+
+
#### Mask Image
+
```
+
mask-none
+
```
+
+
#### Mask Size
+
```
+
mask-auto, mask-cover, mask-contain
+
```
+
+
#### Mask Repeat
+
```
+
mask-repeat, mask-no-repeat, mask-repeat-x, mask-repeat-y, mask-repeat-round, mask-repeat-space
+
```
+
+
#### Mask Position
+
```
+
mask-bottom, mask-center, mask-left, mask-left-bottom, mask-left-top, mask-right, mask-right-bottom, mask-right-top, mask-top
+
```
+
+
#### Mask Origin
+
```
+
mask-origin-border, mask-origin-padding, mask-origin-content
+
```
+
+
#### Mask Clip
+
```
+
mask-clip-border, mask-clip-padding, mask-clip-content
+
```
+
+
#### Mask Composite
+
```
+
mask-composite-add, mask-composite-subtract, mask-composite-intersect, mask-composite-exclude
+
```
+
+
#### Mask Mode
+
```
+
mask-mode-match-source, mask-mode-luminance, mask-mode-alpha
+
```
+
+
#### Mask Type
+
```
+
mask-type-luminance, mask-type-alpha
+
```
+
+
### Tables
+
+
#### Border Collapse
+
```
+
border-collapse, border-separate
+
```
+
+
#### Border Spacing
+
```
+
border-spacing-0, border-spacing-px, border-spacing-0.5, border-spacing-1, border-spacing-1.5, border-spacing-2, border-spacing-2.5, border-spacing-3, border-spacing-3.5, border-spacing-4, border-spacing-5, border-spacing-6, border-spacing-7, border-spacing-8, border-spacing-9, border-spacing-10, border-spacing-11, border-spacing-12, border-spacing-14, border-spacing-16, border-spacing-20, border-spacing-24, border-spacing-28, border-spacing-32, border-spacing-36, border-spacing-40, border-spacing-44, border-spacing-48, border-spacing-52, border-spacing-56, border-spacing-60, border-spacing-64, border-spacing-72, border-spacing-80, border-spacing-96
+
border-spacing-x-0, border-spacing-y-0 (and all other spacing values)
+
```
+
+
#### Table Layout
+
```
+
table-auto, table-fixed
+
```
+
+
#### Caption Side
+
```
+
caption-top, caption-bottom
+
```
+
+
### Transforms
+
+
#### Scale
+
```
+
scale-0, scale-50, scale-75, scale-90, scale-95, scale-100, scale-105, scale-110, scale-125, scale-150
+
scale-x-0, scale-x-50, scale-x-75, scale-x-90, scale-x-95, scale-x-100, scale-x-105, scale-x-110, scale-x-125, scale-x-150
+
scale-y-0, scale-y-50, scale-y-75, scale-y-90, scale-y-95, scale-y-100, scale-y-105, scale-y-110, scale-y-125, scale-y-150
+
```
+
+
#### Scale Z (NEW in v4)
+
```
+
scale-z-0, scale-z-50, scale-z-75, scale-z-90, scale-z-95, scale-z-100, scale-z-105, scale-z-110, scale-z-125, scale-z-150
+
```
+
+
#### Rotate
+
```
+
rotate-0, rotate-1, rotate-2, rotate-3, rotate-6, rotate-12, rotate-45, rotate-90, rotate-180, -rotate-180, -rotate-90, -rotate-45, -rotate-12, -rotate-6, -rotate-3, -rotate-2, -rotate-1
+
```
+
+
#### Rotate X/Y (NEW in v4)
+
```
+
rotate-x-0, rotate-x-1, rotate-x-2, rotate-x-3, rotate-x-6, rotate-x-12, rotate-x-45, rotate-x-90, rotate-x-180, -rotate-x-180, -rotate-x-90, -rotate-x-45, -rotate-x-12, -rotate-x-6, -rotate-x-3, -rotate-x-2, -rotate-x-1
+
rotate-y-0, rotate-y-1, rotate-y-2, rotate-y-3, rotate-y-6, rotate-y-12, rotate-y-45, rotate-y-90, rotate-y-180, -rotate-y-180, -rotate-y-90, -rotate-y-45, -rotate-y-12, -rotate-y-6, -rotate-y-3, -rotate-y-2, -rotate-y-1
+
```
+
+
#### Translate
+
```
+
translate-x-0, translate-x-px, translate-x-0.5, translate-x-1, translate-x-1.5, translate-x-2, translate-x-2.5, translate-x-3, translate-x-3.5, translate-x-4, translate-x-5, translate-x-6, translate-x-7, translate-x-8, translate-x-9, translate-x-10, translate-x-11, translate-x-12, translate-x-14, translate-x-16, translate-x-20, translate-x-24, translate-x-28, translate-x-32, translate-x-36, translate-x-40, translate-x-44, translate-x-48, translate-x-52, translate-x-56, translate-x-60, translate-x-64, translate-x-72, translate-x-80, translate-x-96, translate-x-1/2, translate-x-1/3, translate-x-2/3, translate-x-1/4, translate-x-2/4, translate-x-3/4, translate-x-full
+
translate-y-0, translate-y-px, translate-y-0.5, translate-y-1, translate-y-1.5, translate-y-2, translate-y-2.5, translate-y-3, translate-y-3.5, translate-y-4, translate-y-5, translate-y-6, translate-y-7, translate-y-8, translate-y-9, translate-y-10, translate-y-11, translate-y-12, translate-y-14, translate-y-16, translate-y-20, translate-y-24, translate-y-28, translate-y-32, translate-y-36, translate-y-40, translate-y-44, translate-y-48, translate-y-52, translate-y-56, translate-y-60, translate-y-64, translate-y-72, translate-y-80, translate-y-96, translate-y-1/2, translate-y-1/3, translate-y-2/3, translate-y-1/4, translate-y-2/4, translate-y-3/4, translate-y-full
+
```
+
+
#### Translate Z (NEW in v4)
+
```
+
translate-z-0, translate-z-px, translate-z-0.5, translate-z-1, translate-z-1.5, translate-z-2, translate-z-2.5, translate-z-3, translate-z-3.5, translate-z-4, translate-z-5, translate-z-6, translate-z-7, translate-z-8, translate-z-9, translate-z-10, translate-z-11, translate-z-12, translate-z-14, translate-z-16, translate-z-20, translate-z-24, translate-z-28, translate-z-32, translate-z-36, translate-z-40, translate-z-44, translate-z-48, translate-z-52, translate-z-56, translate-z-60, translate-z-64, translate-z-72, translate-z-80, translate-z-96
+
```
+
+
#### Skew
+
```
+
skew-x-0, skew-x-1, skew-x-2, skew-x-3, skew-x-6, skew-x-12, -skew-x-12, -skew-x-6, -skew-x-3, -skew-x-2, -skew-x-1
+
skew-y-0, skew-y-1, skew-y-2, skew-y-3, skew-y-6, skew-y-12, -skew-y-12, -skew-y-6, -skew-y-3, -skew-y-2, -skew-y-1
+
```
+
+
#### Transform Origin
+
```
+
origin-center, origin-top, origin-top-right, origin-right, origin-bottom-right, origin-bottom, origin-bottom-left, origin-left, origin-top-left
+
```
+
+
#### Transform Style (NEW in v4)
+
```
+
transform-style-flat, transform-style-preserve-3d
+
```
+
+
#### Perspective (NEW in v4)
+
```
+
perspective-none, perspective-250, perspective-500, perspective-750, perspective-1000, perspective-distant
+
```
+
+
#### Perspective Origin (NEW in v4)
+
```
+
perspective-origin-center, perspective-origin-top, perspective-origin-top-right, perspective-origin-right, perspective-origin-bottom-right, perspective-origin-bottom, perspective-origin-bottom-left, perspective-origin-left, perspective-origin-top-left
+
```
+
+
### Interactivity
+
+
#### Accent Color
+
```
+
accent-auto, accent-inherit, accent-current, accent-transparent, accent-black, accent-white
+
accent-{color} (all color utilities work with accent- prefix)
+
```
+
+
#### Appearance
+
```
+
appearance-none, appearance-auto
+
```
+
+
#### Cursor
+
```
+
cursor-auto, cursor-default, cursor-pointer, cursor-wait, cursor-text, cursor-move, cursor-help, cursor-not-allowed, cursor-none, cursor-context-menu, cursor-progress, cursor-cell, cursor-crosshair, cursor-vertical-text, cursor-alias, cursor-copy, cursor-no-drop, cursor-grab, cursor-grabbing, cursor-all-scroll, cursor-col-resize, cursor-row-resize, cursor-n-resize, cursor-e-resize, cursor-s-resize, cursor-w-resize, cursor-ne-resize, cursor-nw-resize, cursor-se-resize, cursor-sw-resize, cursor-ew-resize, cursor-ns-resize, cursor-nesw-resize, cursor-nwse-resize, cursor-zoom-in, cursor-zoom-out
+
```
+
+
#### Caret Color
+
All color utilities work with `caret-` prefix
+
+
#### Pointer Events
+
```
+
pointer-events-none, pointer-events-auto
+
```
+
+
#### Resize
+
```
+
resize-none, resize, resize-y, resize-x
+
```
+
+
#### Scroll Behavior
+
```
+
scroll-auto, scroll-smooth
+
```
+
+
#### Scroll Margin
+
```
+
scroll-m-0, scroll-m-px, scroll-m-0.5, scroll-m-1, scroll-m-1.5, scroll-m-2, scroll-m-2.5, scroll-m-3, scroll-m-3.5, scroll-m-4, scroll-m-5, scroll-m-6, scroll-m-7, scroll-m-8, scroll-m-9, scroll-m-10, scroll-m-11, scroll-m-12, scroll-m-14, scroll-m-16, scroll-m-20, scroll-m-24, scroll-m-28, scroll-m-32, scroll-m-36, scroll-m-40, scroll-m-44, scroll-m-48, scroll-m-52, scroll-m-56, scroll-m-60, scroll-m-64, scroll-m-72, scroll-m-80, scroll-m-96
+
scroll-mx-0, scroll-my-0, scroll-ms-0, scroll-me-0, scroll-mt-0, scroll-mr-0, scroll-mb-0, scroll-ml-0 (and all spacing values)
+
```
+
+
#### Scroll Padding
+
```
+
scroll-p-0, scroll-p-px, scroll-p-0.5, scroll-p-1, scroll-p-1.5, scroll-p-2, scroll-p-2.5, scroll-p-3, scroll-p-3.5, scroll-p-4, scroll-p-5, scroll-p-6, scroll-p-7, scroll-p-8, scroll-p-9, scroll-p-10, scroll-p-11, scroll-p-12, scroll-p-14, scroll-p-16, scroll-p-20, scroll-p-24, scroll-p-28, scroll-p-32, scroll-p-36, scroll-p-40, scroll-p-44, scroll-p-48, scroll-p-52, scroll-p-56, scroll-p-60, scroll-p-64, scroll-p-72, scroll-p-80, scroll-p-96
+
scroll-px-0, scroll-py-0, scroll-ps-0, scroll-pe-0, scroll-pt-0, scroll-pr-0, scroll-pb-0, scroll-pl-0 (and all spacing values)
+
```
+
+
#### Scroll Snap Align
+
```
+
snap-start, snap-end, snap-center, snap-align-none
+
```
+
+
#### Scroll Snap Stop
+
```
+
snap-normal, snap-always
+
```
+
+
#### Scroll Snap Type
+
```
+
snap-none, snap-x, snap-y, snap-both, snap-mandatory, snap-proximity
+
```
+
+
#### Touch Action
+
```
+
touch-auto, touch-none, touch-pan-x, touch-pan-left, touch-pan-right, touch-pan-y, touch-pan-up, touch-pan-down, touch-pinch-zoom, touch-manipulation
+
```
+
+
#### User Select
+
```
+
select-none, select-text, select-all, select-auto
+
```
+
+
#### Will Change
+
```
+
will-change-auto, will-change-scroll, will-change-contents, will-change-transform
+
```
+
+
### SVG
+
+
#### Fill
+
```
+
fill-none, fill-inherit, fill-current, fill-transparent, fill-black, fill-white
+
fill-{color} (all color utilities work with fill- prefix)
+
```
+
+
#### Stroke
+
```
+
stroke-none, stroke-inherit, stroke-current, stroke-transparent, stroke-black, stroke-white
+
stroke-{color} (all color utilities work with stroke- prefix)
+
```
+
+
#### Stroke Width
+
```
+
stroke-0, stroke-1, stroke-2
+
```
+
+
### Accessibility
+
+
#### Screen Readers
+
```
+
sr-only, not-sr-only
+
```
+
+
#### Forced Color Adjust
+
```
+
forced-color-adjust-auto, forced-color-adjust-none
+
```
+
+
### Container Queries (NEW in v4)
+
+
#### Container Type
+
```
+
@container, @container-normal, @container-size, @container-inline-size
+
```
+
+
#### Container Query Variants
+
```
+
@xs:, @sm:, @md:, @lg:, @xl:, @2xl:, @3xl:, @4xl:, @5xl:, @6xl:, @7xl:
+
@min-w-0:, @min-w-xs:, @min-w-sm:, @min-w-md:, @min-w-lg:, @min-w-xl:, @min-w-2xl:, @min-w-3xl:, @min-w-4xl:, @min-w-5xl:, @min-w-6xl:, @min-w-7xl:
+
@max-w-xs:, @max-w-sm:, @max-w-md:, @max-w-lg:, @max-w-xl:, @max-w-2xl:, @max-w-3xl:, @max-w-4xl:, @max-w-5xl:, @max-w-6xl:, @max-w-7xl:
+
@min-h-0:, @min-h-xs:, @min-h-sm:, @min-h-md:, @min-h-lg:, @min-h-xl:, @min-h-2xl:, @min-h-3xl:, @min-h-4xl:, @min-h-5xl:, @min-h-6xl:, @min-h-7xl:
+
@max-h-xs:, @max-h-sm:, @max-h-md:, @max-h-lg:, @max-h-xl:, @max-h-2xl:, @max-h-3xl:, @max-h-4xl:, @max-h-5xl:, @max-h-6xl:, @max-h-7xl:
+
```
+
+
### Responsive Design
+
+
#### Breakpoint Variants
+
```
+
sm:, md:, lg:, xl:, 2xl:
+
max-sm:, max-md:, max-lg:, max-xl:, max-2xl:
+
```
+
+
### State Variants
+
+
#### Hover, Focus, etc.
+
```
+
hover:, focus:, focus-within:, focus-visible:, active:, visited:, target:, disabled:, enabled:, checked:, indeterminate:, default:, required:, valid:, invalid:, in-range:, out-of-range:, placeholder-shown:, autofill:, read-only:
+
```
+
+
#### Group States
+
```
+
group-hover:, group-focus:, group-focus-within:, group-focus-visible:, group-active:, group-visited:, group-target:, group-disabled:, group-enabled:, group-checked:, group-indeterminate:, group-default:, group-required:, group-valid:, group-invalid:, group-in-range:, group-out-of-range:, group-placeholder-shown:, group-autofill:, group-read-only:
+
```
+
+
#### Peer States
+
```
+
peer-hover:, peer-focus:, peer-focus-within:, peer-focus-visible:, peer-active:, peer-visited:, peer-target:, peer-disabled:, peer-enabled:, peer-checked:, peer-indeterminate:, peer-default:, peer-required:, peer-valid:, peer-invalid:, peer-in-range:, peer-out-of-range:, peer-placeholder-shown:, peer-autofill:, peer-read-only:
+
```
+
+
#### NEW Variants in v4
+
```
+
@starting-style:, not-*, nth-*, in-*, inert:, open: (for popovers)
+
```
+
+
### Media Queries
+
+
#### Dark Mode
+
```
+
dark:
+
```
+
+
#### Motion
+
```
+
motion-safe:, motion-reduce:
+
```
+
+
#### Contrast
+
```
+
contrast-more:, contrast-less:
+
```
+
+
#### Print
+
```
+
print:
+
```
+
+
#### Orientation
+
```
+
portrait:, landscape:
+
```
+
+
### Content
+
```
+
content-none, content-['text']
+
```
+
+
### Arbitrary Values
+
You can use arbitrary values with square brackets for any property:
+
```
+
w-[123px], h-[456px], text-[#bada55], bg-[url('...')], top-[117px], left-[344px]
+
m-[12px], p-[24px], grid-cols-[200px_minmax(900px,_1fr)_100px]
+
```
+
+
### Arbitrary Properties
+
```
+
[mask-type:luminance], [tab-size:4], [@supports(backdrop-filter:blur(0))]:bg-white/75
+
```
+
+
### Arbitrary Variants
+
```
+
[&:nth-child(3)]:, [&:hover]:, [&_p]:, [@media(min-width:600px)]:
+
[@supports(backdrop-filter:blur(0))]:, [data-theme="dark"]:
+
```
+
+
## Common v4 Pitfalls to Avoid
+
+
### Don't Use These Deprecated Patterns
+
- โŒ `@tailwind base; @tailwind components; @tailwind utilities;`
+
- โŒ `text-opacity-50` โ†’ Use `text-white/50` instead
+
- โŒ `bg-opacity-25` โ†’ Use `bg-blue-500/25` instead
+
- โŒ `border` without color (now uses currentColor, not gray-200)
+
- โŒ `ring` without explicit width (now 1px, was 3px)
+
- โŒ `@layer utilities` โ†’ Use `@utility` instead
+
- โŒ JavaScript config for new projects โ†’ Use CSS `@theme`
+
+
### Modern v4 Alternatives
+
- โœ… `@import "tailwindcss";`
+
- โœ… `text-white/50` for semi-transparent text
+
- โœ… `bg-blue-500/25` for semi-transparent backgrounds
+
- โœ… `border border-gray-200` for explicit border color
+
- โœ… `ring-3` for 3px ring width
+
- โœ… `@utility` for custom utilities
+
- โœ… `@theme` for configuration
+
+
## Performance Best Practices
+
+
### Leverage v4's Performance Features
+
- Use automatic content detection (no manual `content` config needed)
+
- Prefer container queries over viewport queries for true component responsiveness
+
- Use CSS variables from `@theme` for dynamic styling
+
- Leverage the new OKLCH color system for better color consistency
+
+
### Efficient Class Usage
+
```html
+
<!-- Good: Use size-* for square elements -->
+
<div class="size-12"></div>
+
+
<!-- Instead of: -->
+
<div class="w-12 h-12"></div>
+
+
<!-- Good: Use container queries for component responsiveness -->
+
<div class="@container">
+
<div class="p-4 @lg:p-8">Content</div>
+
</div>
+
+
<!-- Good: Use CSS variables for dynamic values -->
+
<div class="bg-[var(--theme-primary)] text-[var(--theme-on-primary)]">
+
Dynamic theming
+
</div>
+
```
+
+
## Framework Integration
+
+
### Svelte 5
+
```svelte
+
<script>
+
let { variant = "primary", children } = $props();
+
+
const buttonClasses = $derived(() => [
+
'px-4 py-2 rounded-md font-medium transition-colors',
+
variant === 'primary'
+
? 'bg-brand text-white hover:bg-brand/90'
+
: 'bg-gray-100 text-gray-900 hover:bg-gray-200'
+
].join(' '));
+
</script>
+
+
<button class={buttonClasses}>
+
{@render children()}
+
</button>
+
+
<style>
+
@import "tailwindcss";
+
+
@theme {
+
--color-brand: oklch(0.5 0.2 240);
+
}
+
</style>
+
```
+
+
## Debugging & Development
+
+
### Browser DevTools Tips
+
1. **Inspect CSS Variables**: Check `:root` in DevTools to see all theme variables
+
2. **Check Cascade Layers**: Use the Layers panel to understand style precedence
+
3. **Verify OKLCH Support**: Test colors in modern browsers vs fallbacks
+
4. **Container Query Debugging**: Use the @container panel in DevTools
+
+
### Common Debug Commands
+
```bash
+
# Check if utilities are being generated
+
npx tailwindcss --watch --content "./src/**/*.{html,js,jsx,ts,tsx}"
+
+
# Verify v4 installation
+
npm list tailwindcss
+
+
# Check for conflicting PostCSS plugins
+
npm list | grep postcss
+
```
+
+
### VS Code Extensions
+
- Tailwind CSS IntelliSense (updated for v4)
+
- PostCSS Language Support
+
+
## v3 to v4 Migration Checklist
+
+
### Pre-Migration
+
- [ ] Backup your project
+
- [ ] Ensure Node.js 20+ is installed
+
- [ ] Check browser support requirements (Safari 16.4+, Chrome 111+, Firefox 128+)
+
+
### Automated Migration
+
```bash
+
npx @tailwindcss/upgrade@next
+
```
+
+
### Manual Verification
+
- [ ] Replace `@tailwind` directives with `@import "tailwindcss"`
+
- [ ] Move `tailwind.config.js` content to CSS `@theme`
+
- [ ] Update deprecated utility classes
+
- [ ] Test container queries functionality
+
- [ ] Verify custom component styles
+
- [ ] Check 3D transform support
+
- [ ] Test mask utilities if used
+
- [ ] Validate color consistency (OKLCH vs RGB)
+
+
### Testing
+
- [ ] Test in all target browsers
+
- [ ] Verify responsive design still works
+
- [ ] Check dark mode functionality
+
- [ ] Test custom animations
+
- [ ] Validate accessibility features
+
+
## Production-Ready Component Patterns
+
+
### Modern Card Component
+
```html
+
<div class="@container group">
+
<article class="
+
bg-white dark:bg-gray-900
+
rounded-xl shadow-sm border border-gray-200 dark:border-gray-800
+
overflow-hidden transition-all duration-200
+
hover:shadow-md hover:-translate-y-0.5
+
@sm:flex @sm:items-center
+
">
+
<div class="@sm:flex-shrink-0">
+
<img class="h-48 w-full object-cover @sm:h-full @sm:w-48" src="..." alt="...">
+
</div>
+
<div class="p-6 @sm:p-8">
+
<h3 class="text-lg font-semibold text-gray-900 dark:text-white @lg:text-xl">
+
Card Title
+
</h3>
+
<p class="mt-2 text-gray-600 dark:text-gray-300 @lg:text-lg">
+
Card description that adapts to container size.
+
</p>
+
</div>
+
</article>
+
</div>
+
```
+
+
### 3D Interactive Button
+
```html
+
<button class="
+
relative px-6 py-3 bg-blue-600 text-white font-medium rounded-lg
+
transform-3d perspective-1000
+
transition-all duration-200
+
hover:rotate-x-12 hover:scale-105 hover:shadow-xl
+
active:scale-95 active:rotate-x-6
+
focus:outline-none focus:ring-2 focus:ring-blue-500/50
+
">
+
3D Button
+
</button>
+
```
+
+
Remember: Tailwind CSS v4 is designed for modern browsers and modern development workflows. Embrace the new CSS-first approach and leverage the powerful new features for better performance and developer experience.
+13
.tangled/workflows/build.yml
···
+
when:
+
- event: ["push", "pull_request"]
+
branch: ["main"]
+
+
dependencies:
+
nixpkgs:
+
- dune
+
- opam
+
+
steps:
+
- name: dune
+
command: |
+
dune build
+1 -3
CLAUDE.md
···
-
My goal is to build a high quality professions OCaml library to generate Tailwind CSS components. Build a core `tailwind` library that serialises the CSS into strings. Then build a `tailwind-html` library that uses the Htmlit OCaml HTML generation library https://github.com/dbuenzli/htmlit for common components.
-
-
You can find full Tailwind docs in tailwind-llms.txt
+
Look in .agent/ for instructions
+18
LICENSE.md
···
+
(*
+
* ISC License
+
*
+
* Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>
+
*
+
* Permission to use, copy, modify, and distribute this software for any
+
* purpose with or without fee is hereby granted, provided that the above
+
* copyright notice and this permission notice appear in all copies.
+
*
+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
*
+
*)
+276 -148
README.md
···
# Tailwind OCaml
-
An OCaml library for generating Tailwind CSS classes with compile-time
-
validation and a companion HTML generation library using Htmlit.
+
Type-safe Tailwind CSS generation for OCaml with a revolutionary GADT-based interface for succinct, compile-time validated styling.
This project provides two main libraries:
- **`tailwind`**: Core library for type-safe Tailwind CSS class generation
-
- **`tailwind-html`**: HTML component library built on top of [Htmlit](https://github.com/dbuenzli/htmlit)
+
- **`tailwind-html`**: High-level HTML component library with GADT-based heterogeneous list interface built on [Htmlit](https://github.com/dbuenzli/htmlit)
## Features
-
- Compile-time validation of Tailwind classes
-
- Type-safe color variants and sizes
-
- Exhaustive pattern matching for all utility classes
+
- **GADT-based Interface**: Succinct heterogeneous list syntax with compile-time type safety
+
- **Zero Runtime Cost**: All CSS generation happens at compile time
+
- **Comprehensive Grid Support**: Full CSS Grid integration with type-safe properties
+
- **Type-Safe Colors & Spacing**: Exhaustive variants with compile-time validation
+
- **Built-in Components**: Pre-styled buttons, cards, and layout helpers
-
### Comprehensive Coverage
-
- **Typography**: Font sizes, weights, line heights, text alignment, decorations
-
- **Layout**: Display, position, flexbox, grid, spacing
-
- **Colors**: Full color palette with variants
+
### Complete Tailwind Coverage
+
- **Typography**: Font sizes, weights, text alignment with type-safe variants
+
- **Layout**: CSS Grid, Flexbox, spacing with compile-time validation
+
- **Colors**: Full palette (gray, blue, red, green, etc.) with variant checking
- **Effects**: Shadows, borders, rounded corners, transitions
-
- **Responsive**: Breakpoint-based responsive utilities
-
- **Variants**: Hover, focus, and other state variants
+
- **Components**: Pre-built buttons, cards, and layout helpers
+
- **Type Safety**: GADT-based heterogeneous lists prevent invalid combinations
-
### Using Dune
+
## Quick Start
-
Add to your `dune-project`:
-
-
```dune
-
(package
-
(name myproject)
-
(depends
-
ocaml
-
dune
-
tailwind
-
tailwind-html
-
htmlit))
-
```
-
-
## Quick Start
+
### GADT Interface (Recommended)
-
### Basic Usage
+
The new GADT-based interface provides succinct, type-safe styling with heterogeneous lists:
```ocaml
-
open Tailwind
+
open Htmlit
+
open Tailwind_html
-
(* Create a styled div *)
-
let styled_div =
-
let classes = tw [
-
Display.flex;
-
Flexbox.(to_class (justify `Center));
-
Flexbox.(to_class (align_items `Center));
-
Color.bg (Color.make `Gray ~variant:`V100 ());
-
Spacing.(to_class (p (Size.rem 2.0)));
-
] in
-
Printf.sprintf "<div class=\"%s\">Content</div>" (to_string classes)
+
(* Create a centered card with CSS Grid *)
+
let create_hero_section () =
+
div ~styles:[
+
grid;
+
grid_cols 1;
+
gap (rem 2.0);
+
padding (rem 3.0);
+
text_center;
+
] [
+
h1 ~styles:[
+
font_size `Xl3;
+
font_weight `Bold;
+
text_color (blue 600);
+
margin_bottom (rem 1.5);
+
] [txt "Welcome to Tailwind OCaml"];
+
+
p ~styles:[
+
font_size `Lg;
+
text_color (gray 600);
+
margin_bottom (rem 2.0);
+
] [txt "Type-safe CSS with compile-time guarantees"];
+
+
(* Built-in button components *)
+
btn_primary ~size:`Lg [txt "Get Started"];
+
]
```
-
### With Htmlit Integration
+
### CSS Grid Layouts
```ocaml
-
open Htmlit
-
open Tailwind
+
(* Three-column responsive grid *)
+
div ~styles:[
+
grid;
+
grid_cols 3;
+
gap (rem 1.5);
+
] [
+
card [h3 [txt "Feature 1"]; p [txt "Description"]];
+
card [h3 [txt "Feature 2"]; p [txt "Description"]];
+
card [h3 [txt "Feature 3"]; p [txt "Description"]];
+
]
+
```
-
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
+
### Built-in Components
-
let create_card title content =
-
El.div ~at:[classes_attr (tw [
-
Patterns.card;
-
Spacing.(to_class (p (Size.rem 1.5)));
-
Effects.shadow_md;
-
])] [
-
El.h2 ~at:[classes_attr (tw [
-
Typography.(to_class (font_size `Xl));
-
Typography.(to_class (font_weight `Bold));
-
Spacing.(to_class (mb (Size.rem 1.0)));
-
])] [El.txt title];
-
El.p [El.txt content];
-
]
+
```ocaml
+
(* Pre-styled components with size variants *)
+
btn_primary ~size:`Lg [txt "Primary Action"];
+
btn_secondary [txt "Secondary Action"];
+
btn_outline ~size:`Sm [txt "Outline Button"];
+
+
(* Layout helpers *)
+
container [
+
card [
+
h2 ~styles:[font_size `Xl; margin_bottom (rem 1.0)] [txt "Card Title"];
+
p ~styles:[text_color (gray 600)] [txt "Card content with automatic styling"];
+
];
+
]
```
## Examples
-
The `examples/` directory contains several demonstration files:
+
The `examples/` directory showcases the GADT interface across various use cases:
-
### Running Examples
+
### Available Examples
```bash
# Build all examples
dune build examples/
-
# Run comprehensive showcase (generates HTML + CSS)
-
dune exec examples/comprehensive_showcase.exe
+
# Hello World with GADT interface
+
dune exec examples/hello_tailwind_01.exe > hello.html
+
+
# Colors and Typography showcase
+
dune exec examples/colors_and_typography_02.exe > colors.html
+
+
# CSS Grid and Layout demonstrations
+
dune exec examples/layout_and_spacing_03.exe > layout.html
-
# Run basic usage example
-
dune exec examples/basic_usage.exe
+
# Responsive design patterns
+
dune exec examples/responsive_design_04.exe > responsive.html
-
# Run HTML integration example
-
dune exec examples/tailwind_html_example.exe
+
# Visual effects and styling
+
dune exec examples/effects_and_variants_05.exe > effects.html
+
+
# Component patterns and reusable elements
+
dune exec examples/patterns_and_components_06.exe > patterns.html
+
+
# Complete application showcase
+
dune exec examples/comprehensive_showcase_07.exe > showcase.html
+
+
# Button component demonstration
+
dune exec examples/button_demo.exe > buttons.html
+
+
# Generate index page linking all examples
+
dune exec examples/index_html_generator.exe > index.html
```
-
### Comprehensive Showcase
+
### Example Highlights
+
+
**CSS Grid Layout (`layout_and_spacing_03.ml`)**:
+
```ocaml
+
(* Three-column grid with gap variations *)
+
div ~styles:[
+
grid;
+
grid_cols 3;
+
gap (rem 1.0);
+
] [
+
div ~styles:[bg_color (blue 100); padding (rem 1.0)] [txt "Item 1"];
+
div ~styles:[bg_color (green 100); padding (rem 1.0)] [txt "Item 2"];
+
div ~styles:[bg_color (purple 100); padding (rem 1.0)] [txt "Item 3"];
+
]
-
The comprehensive showcase demonstrates all library features and generates:
-
- `showcase.html` - Complete HTML page with all Tailwind classes
-
- `input.css` - Tailwind v4 CSS with custom theme extensions
+
(* Asymmetric grid gaps *)
+
div ~styles:[
+
grid;
+
grid_cols 2;
+
gap_x (rem 2.0);
+
gap_y (rem 0.5);
+
] (List.init 4 (fun i ->
+
div ~styles:[bg_color (purple 200); text_center] [
+
txt (Printf.sprintf "Box %d" (i + 1))
+
]
+
))
+
```
-
```bash
-
dune exec examples/comprehensive_showcase.exe
-
# Then open showcase.html in your browser
+
**Built-in Components (`button_demo.ml`)**:
+
```ocaml
+
(* Size variants with consistent styling *)
+
div ~styles:[flex; flex_col; gap (rem 1.0)] [
+
btn_primary ~size:`Sm [txt "Small Primary"];
+
btn_primary [txt "Default Primary"];
+
btn_primary ~size:`Lg [txt "Large Primary"];
+
btn_secondary [txt "Secondary Button"];
+
btn_outline [txt "Outline Button"];
+
]
+
```
+
+
**Responsive Cards (`comprehensive_showcase_07.ml`)**:
+
```ocaml
+
section ~styles:[margin_bottom (rem 4.0)] [
+
h3 ~styles:[font_size `Xl2; text_center; margin_bottom (rem 3.0)] [
+
txt "Features"
+
];
+
+
div ~styles:[grid; grid_cols 1; gap (rem 2.0)] [
+
card [
+
h4 ~styles:[font_size `Xl; font_weight `Semibold; text_color (blue 600)] [
+
txt "๐ŸŽฏ Type Safety"
+
];
+
p ~styles:[text_color (gray 600)] [
+
txt "Catch styling errors at compile time with GADT-based type checking."
+
];
+
];
+
card [
+
h4 ~styles:[font_size `Xl; font_weight `Semibold; text_color (green 600)] [
+
txt "โšก Performance"
+
];
+
p ~styles:[text_color (gray 600)] [
+
txt "Zero runtime overhead with compile-time CSS generation."
+
];
+
];
+
];
+
]
```
## Tailwind v4 Support
···
npx tailwindcss@next -i input.css -o output.css
```
-
## Module Documentation
+
## API Reference
-
### Core Modules
+
### `Tailwind_html` (GADT Interface)
-
#### `Tailwind`
-
Main module that exports all utilities and provides the `tw` function for composing classes.
+
The high-level GADT interface provides succinct, type-safe styling with heterogeneous lists:
-
#### `Color`
-
Type-safe color system with variants:
+
#### Layout Properties
```ocaml
-
Color.bg (Color.make `Blue ~variant:`V600 ())
-
Color.text Color.white
-
Color.border (Color.make `Gray ~variant:`V200 ())
+
~styles:[
+
(* Display *)
+
grid | flex | block | inline | hidden;
+
+
(* Grid System *)
+
grid_cols 3 | grid_rows 2;
+
gap (rem 1.0) | gap_x (rem 1.5) | gap_y (rem 0.5);
+
+
(* Flexbox *)
+
flex_col | flex_row;
+
justify_center | justify_between | justify_end;
+
items_center | items_start | items_end;
+
+
(* Sizing *)
+
width full | height screen;
+
min_height screen | max_width (rem 64.0);
+
]
```
-
#### `Typography`
-
Font utilities:
+
#### Typography Properties
```ocaml
-
Typography.(to_class (font_size `Xl2))
-
Typography.(to_class (font_weight `Bold))
-
Typography.(to_class (line_height `Relaxed))
+
~styles:[
+
(* Font Sizes *)
+
font_size `Xs | font_size `Sm | font_size `Base | font_size `Lg;
+
font_size `Xl | font_size `Xl2 | font_size `Xl3;
+
+
(* Font Weights *)
+
font_weight `Light | font_weight `Normal | font_weight `Medium;
+
font_weight `Semibold | font_weight `Bold;
+
+
(* Text Styling *)
+
text_center | text_left | text_right;
+
text_color (blue 600) | text_color (gray 500);
+
]
```
-
#### `Spacing`
-
Margin and padding utilities:
+
#### Color System
```ocaml
-
Spacing.(to_class (p (Size.rem 1.0))) (* padding *)
-
Spacing.(to_class (mx Size.auto)) (* margin-x auto *)
-
Spacing.(to_class (gap `All (Size.px 16.0))) (* gap *)
+
~styles:[
+
(* Background Colors *)
+
bg_color (blue 50) | bg_color (gray 100) | bg_color (red 500);
+
bg_color (Tailwind.Color.white) | bg_color (green 600);
+
+
(* Text Colors *)
+
text_color (gray 800) | text_color (blue 600) | text_color (red 500);
+
+
(* Border Colors *)
+
border_color (gray 200) | border_color (blue 300);
+
]
```
-
#### `Layout`
-
Layout utilities:
+
#### Spacing Properties
```ocaml
-
Layout.(to_class (width (Size.percent 100.0)))
-
Layout.(to_class (height Size.screen))
-
Layout.(to_class (max_width (Size.rem 64.0)))
+
~styles:[
+
(* Padding *)
+
padding (rem 1.0) | padding_x (rem 1.5) | padding_y (rem 2.0);
+
+
(* Margin *)
+
margin (rem 1.0) | margin_x auto | margin_bottom (rem 2.0);
+
margin_top (rem 1.5) | margin_left (rem 0.5);
+
]
```
-
#### `Flexbox`
-
Flexbox utilities:
+
#### Visual Effects
```ocaml
-
Display.flex
-
Flexbox.(to_class (justify `Between))
-
Flexbox.(to_class (align_items `Center))
-
Flexbox.(to_class (direction `Col))
+
~styles:[
+
(* Shadows *)
+
shadow `Sm | shadow `Md | shadow `Lg | shadow `Xl;
+
+
(* Borders *)
+
border | rounded `Sm | rounded `Md | rounded `Lg | rounded `Full;
+
+
(* Transitions *)
+
transition;
+
]
```
-
#### `Grid`
-
CSS Grid utilities:
+
#### Built-in Components
```ocaml
-
Display.grid
-
Grid.(to_class (template_cols (`Cols 3)))
-
Grid.(to_class (gap (Size.rem 1.0)))
-
```
+
(* Button Components *)
+
btn_primary ~size:`Lg [txt "Primary Button"];
+
btn_secondary ~size:`Sm [txt "Secondary Button"];
+
btn_outline [txt "Outline Button"];
+
+
(* Layout Components *)
+
container [content]; (* Max-width container with auto margins *)
+
card [content]; (* Pre-styled card with padding and shadow *)
-
#### `Effects`
-
Visual effects:
-
```ocaml
-
Effects.shadow_lg
-
Effects.rounded_md
-
Effects.border
-
Effects.transition `All
+
(* HTML Elements with Styling *)
+
h1 ~styles:[font_size `Xl3; font_weight `Bold] [txt "Heading"];
+
p ~styles:[text_color (gray 600); margin_bottom (rem 1.0)] [txt "Paragraph"];
+
div ~styles:[grid; grid_cols 2; gap (rem 1.0)] [content];
+
section ~styles:[margin_bottom (rem 2.0)] [content];
```
-
#### `Responsive`
-
Responsive utilities:
-
```ocaml
-
Responsive.(to_class (at_breakpoint `Md Display.flex))
-
Responsive.(to_class (at_breakpoint `Lg (Grid.(to_class (template_cols (`Cols 4))))))
-
```
+
### Low-Level `Tailwind` Module
-
#### `Variants`
-
State variants:
-
```ocaml
-
Variants.hover (Color.bg (Color.make `Blue ~variant:`V700 ()))
-
Variants.focus Effects.ring
-
```
+
For advanced use cases, the core `Tailwind` module provides detailed control:
-
#### `Patterns`
-
Common layout patterns:
```ocaml
-
Patterns.container ()
-
Patterns.card
-
Patterns.flex_center
-
Patterns.stack ~gap:(Size.rem 1.0) ()
-
Patterns.sticky_header
+
open Tailwind
+
+
let classes = Css.tw [
+
Display.grid;
+
Grid.(to_class (template_cols (`Cols 3)));
+
Spacing.(to_class (gap `All (Size.rem 1.0)));
+
Color.bg (Color.make `Blue ~variant:`V50 ());
+
]
+
+
let html_class = to_string classes (* "grid grid-cols-3 gap-4 bg-blue-50" *)
```
-
### HTML Components (`tailwind-html`)
+
### Getting Started
-
Pre-built components using Htmlit:
+
Add to your `dune-project`:
+
```dune
+
(package
+
(name myproject)
+
(depends
+
ocaml
+
dune
+
tailwind
+
tailwind-html
+
htmlit))
+
```
+
Then in your OCaml code:
```ocaml
+
open Htmlit
open Tailwind_html
-
(* Button component *)
-
Button.primary ~text:"Click me" ~onclick:"handleClick()"
-
-
(* Card component *)
-
Card.simple ~title:"Card Title" ~content:"Card content here"
-
-
(* Layout components *)
-
Layout.container [
-
Layout.row [
-
Layout.col ~span:6 [content];
-
Layout.col ~span:6 [content];
-
]
+
let my_page = El.html [
+
El.head [El.title [txt "My App"]];
+
El.body ~at:[classes_attr [min_height screen; bg_color (gray 50)]] [
+
container [
+
h1 ~styles:[font_size `Xl3; text_center; margin_bottom (rem 2.0)] [
+
txt "Welcome to Type-Safe CSS!"
+
];
+
btn_primary [txt "Get Started"];
+
];
+
];
]
```
+7 -15
dune-project
···
-
(lang dune 3.0)
+
(lang dune 3.18)
(name tailwind)
(generate_opam_files true)
-
(source
-
(github yourusername/tailwind-ocaml))
+
(authors "Anil Madhavapeddy")
-
(authors "Your Name")
-
-
(maintainers "Your Name")
-
-
(license MIT)
+
(maintainers "Anil Madhavapeddy")
-
(documentation https://yourusername.github.io/tailwind-ocaml/)
+
(license ISC)
(package
(name tailwind)
(synopsis "Type-safe Tailwind CSS generation for OCaml")
-
(description "A comprehensive OCaml library for generating Tailwind CSS classes with full type safety")
+
(description "Library for generating Tailwind CSS classes")
(depends
ocaml
-
(dune (>= 3.0))
(alcotest :with-test)
(qcheck :with-test)
(odoc :with-doc)))
···
(package
(name tailwind-html)
(synopsis "Tailwind CSS integration with Htmlit")
-
(description "High-level component library using Tailwind CSS with Htmlit")
-
(allow_empty)
+
(description "Html combinators for Tailwind CSS")
(depends
ocaml
-
(dune (>= 3.0))
tailwind
(htmlit (>= 0.1.0))
(alcotest :with-test)
(qcheck :with-test)
-
(odoc :with-doc)))
+
(odoc :with-doc)))
-65
examples/advanced_features.ml
···
-
let () =
-
Printf.printf "=== Advanced Tailwind Features ===\n";
-
-
(* V4 Container Queries *)
-
let container_responsive = Tailwind.V4.container_query `Lg
-
(Tailwind.Css.make "text-2xl") in
-
Printf.printf "Container Query (V4): %s\n" (Tailwind.to_string container_responsive);
-
-
(* V4 Starting Style *)
-
let starting_animation = Tailwind.V4.starting_style
-
(Tailwind.Css.make "opacity-0") in
-
Printf.printf "Starting Style (V4): %s\n" (Tailwind.to_string starting_animation);
-
-
(* V4 Text Shadow *)
-
let text_shadow = Tailwind.V4.text_shadow `Lg in
-
Printf.printf "Text Shadow (V4): %s\n" (Tailwind.to_string text_shadow);
-
-
(* Advanced Variants - Pseudo-classes *)
-
let hover_effect = Tailwind.Variants.hover (Tailwind.Css.make "bg-blue-600") in
-
Printf.printf "Hover Effect: %s\n" (Tailwind.to_string hover_effect);
-
-
let focus_visible = Tailwind.Variants.apply
-
(Tailwind.Variants.pseudo `Focus_visible (Tailwind.Css.make "ring-2"))
-
(Tailwind.Css.make "input") in
-
Printf.printf "Focus Visible: %s\n" (Tailwind.to_string focus_visible);
-
-
(* Responsive with Media Features *)
-
let dark_mode = Tailwind.Responsive.(apply
-
(media `Dark (Tailwind.Css.make "bg-gray-900"))
-
(Tailwind.Css.make "bg-white")) in
-
Printf.printf "Dark Mode: %s\n" (Tailwind.to_string dark_mode);
-
-
let motion_safe = Tailwind.Responsive.(apply
-
(media `Motion_safe (Tailwind.Css.make "transition-all"))
-
(Tailwind.Css.make "transform")) in
-
Printf.printf "Motion Safe: %s\n" (Tailwind.to_string motion_safe);
-
-
(* Advanced Effects *)
-
let backdrop_blur = Tailwind.Effects.(to_class (backdrop_blur `Lg)) in
-
Printf.printf "Backdrop Blur: %s\n" (Tailwind.to_string backdrop_blur);
-
-
let transform_origin = Tailwind.Effects.(to_class (transform_origin `Top_right)) in
-
Printf.printf "Transform Origin: %s\n" (Tailwind.to_string transform_origin);
-
-
let scale_transform = Tailwind.Effects.(to_class (scale `X 125)) in
-
Printf.printf "Scale Transform: %s\n" (Tailwind.to_string scale_transform);
-
-
let rotate_transform = Tailwind.Effects.(to_class (rotate 45)) in
-
Printf.printf "Rotate Transform: %s\n" (Tailwind.to_string rotate_transform);
-
-
let translate_transform = Tailwind.Effects.(to_class (translate `Y (Tailwind.Size.rem 2.0))) in
-
Printf.printf "Translate Transform: %s\n" (Tailwind.to_string translate_transform);
-
-
(* Complex Combination *)
-
let complex_card = Tailwind.tw [
-
Tailwind.Color.bg (Tailwind.Color.make `White ());
-
Tailwind.Effects.rounded_lg;
-
Tailwind.Effects.shadow_md;
-
backdrop_blur;
-
Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5)));
-
Tailwind.Effects.(to_class (transform `Gpu));
-
Tailwind.Effects.transition `All;
-
hover_effect;
-
] in
-
Printf.printf "Complex Card: %s\n" (Tailwind.to_string complex_card)
-45
examples/basic_usage.ml
···
-
(* Basic usage examples for the Tailwind OCaml library *)
-
-
(* This example shows how to use the library in its current form *)
-
-
let () =
-
(* The current implementation provides these utilities *)
-
let flex_center_classes = Tailwind.Patterns.flex_center in
-
let focus_ring_classes = Tailwind.focus_ring () in
-
let container_classes = Tailwind.Patterns.container ~center:true () in
-
-
(* Reset utilities *)
-
let button_reset = Tailwind.Reset.button in
-
let input_reset = Tailwind.Reset.input in
-
let sr_only = Tailwind.sr_only in
-
-
(* Transitions *)
-
let transition_all = Tailwind.Effects.transition `All in
-
let duration_300 = Tailwind.Effects.duration 300 in
-
let ease_in_out = Tailwind.Effects.ease `In_out in
-
-
(* Conditional classes *)
-
let conditional_classes = Tailwind.class_list [
-
(Tailwind.Patterns.flex_center, true);
-
(Tailwind.Reset.button, false);
-
] in
-
-
Printf.printf "=== Tailwind OCaml Library Usage Examples ===\n";
-
Printf.printf "Flex center: %s\n" (Tailwind.to_string flex_center_classes);
-
Printf.printf "Focus ring: %s\n" (Tailwind.to_string focus_ring_classes);
-
Printf.printf "Container: %s\n" (Tailwind.to_string container_classes);
-
Printf.printf "Button reset: %s\n" (Tailwind.to_string button_reset);
-
Printf.printf "Input reset: %s\n" (Tailwind.to_string input_reset);
-
Printf.printf "Screen reader only: %s\n" (Tailwind.to_string sr_only);
-
Printf.printf "Transition all: %s\n" (Tailwind.to_string transition_all);
-
Printf.printf "Duration 300ms: %s\n" (Tailwind.to_string duration_300);
-
Printf.printf "Ease in-out: %s\n" (Tailwind.to_string ease_in_out);
-
Printf.printf "Conditional classes: %s\n" (Tailwind.to_string conditional_classes);
-
-
(* Combining classes *)
-
let combined_classes = Tailwind.tw [
-
flex_center_classes;
-
container_classes;
-
transition_all;
-
] in
-
Printf.printf "Combined classes: %s\n" (Tailwind.to_string combined_classes)
+100
examples/button_demo.ml
···
+
(* Button Demo - Showcasing GADT-based button interface *)
+
+
open Htmlit
+
open Tailwind_html
+
+
let create_button_demo () =
+
let html = El.html [
+
El.head [
+
El.meta ~at:[At.charset "utf-8"] ();
+
El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] ();
+
El.title [txt "Button Demo"];
+
El.link ~at:[At.rel "stylesheet"; At.href "button_demo.css"] ();
+
];
+
El.body ~at:[classes_attr [
+
min_height screen;
+
bg_color (gray 50);
+
padding (rem 2.0);
+
]] [
+
container [
+
h1 ~styles:[
+
font_size `Xl3;
+
font_weight `Bold;
+
text_color (gray 800);
+
text_center;
+
margin_bottom (rem 2.0);
+
] [txt "Button Component Demo"];
+
+
p ~styles:[
+
font_size `Lg;
+
text_color (gray 600);
+
text_center;
+
margin_bottom (rem 3.0);
+
] [txt "Showcase of built-in button components using GADT interface"];
+
+
(* Primary buttons section *)
+
card [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "Primary Buttons"];
+
+
div ~styles:[
+
flex;
+
flex_col;
+
margin_bottom (rem 1.0);
+
] [
+
btn_primary ~size:`Sm [txt "Small Primary"];
+
btn_primary [txt "Default Primary"];
+
btn_primary ~size:`Lg [txt "Large Primary"];
+
];
+
];
+
+
(* Secondary buttons section *)
+
card [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "Secondary Buttons"];
+
+
div ~styles:[
+
flex;
+
flex_col;
+
margin_bottom (rem 1.0);
+
] [
+
btn_secondary ~size:`Sm [txt "Small Secondary"];
+
btn_secondary [txt "Default Secondary"];
+
btn_secondary ~size:`Lg [txt "Large Secondary"];
+
];
+
];
+
+
(* Outline buttons section *)
+
card [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "Outline Buttons"];
+
+
div ~styles:[
+
flex;
+
flex_col;
+
] [
+
btn_outline ~size:`Sm [txt "Small Outline"];
+
btn_outline [txt "Default Outline"];
+
btn_outline ~size:`Lg [txt "Large Outline"];
+
];
+
];
+
];
+
];
+
] in
+
html
+
+
let () =
+
let html = create_button_demo () in
+
print_string (El.to_string ~doctype:true html)
+73 -174
examples/colors_and_typography_02.ml
···
-
(* Example 02: Colors and Typography - Exploring the Type System *)
+
(* Example 02: Colors and Typography - GADT interface showcase *)
open Htmlit
-
open Tailwind
-
-
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
+
open Tailwind_html
let create_color_demo () =
-
(* Color variants demonstration *)
-
let color_examples = [
-
("Blue 400", Color.make `Blue ~variant:`V400 ());
-
("Blue 600", Color.make `Blue ~variant:`V600 ());
-
("Green 500", Color.make `Green ~variant:`V500 ());
-
("Red 500", Color.make `Red ~variant:`V500 ());
-
("Purple 600", Color.make `Purple ~variant:`V600 ());
-
("Gray 700", Color.make `Gray ~variant:`V700 ());
-
] in
-
-
let typography_examples = [
-
("Extra Small", Typography.(to_class (font_size `Xs)));
-
("Small", Typography.(to_class (font_size `Sm)));
-
("Base", Typography.(to_class (font_size `Base)));
-
("Large", Typography.(to_class (font_size `Lg)));
-
("Extra Large", Typography.(to_class (font_size `Xl)));
-
("2X Large", Typography.(to_class (font_size `Xl2)));
-
] in
-
-
(* Create HTML demonstration *)
-
let html_doc = El.html [
+
let html = El.html [
El.head [
El.meta ~at:[At.charset "utf-8"] ();
El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] ();
-
El.title [El.txt "Colors and Typography"];
+
El.title [txt "Colors and Typography"];
El.link ~at:[At.rel "stylesheet"; At.href "colors_and_typography_02.css"] ();
];
-
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 [
-
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.body ~at:[classes_attr [
+
min_height screen;
+
bg_color (gray 50);
+
padding (rem 2.0);
+
]] [
+
container [
+
h1 ~styles:[
+
font_size `Xl2;
+
font_weight `Bold;
+
text_color (gray 800);
+
text_center;
+
margin_bottom (rem 2.0);
+
] [txt "Colors and Typography Demo"];
-
El.p ~at:[classes_attr (tw [
-
Typography.(to_class (font_size `Lg));
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
]); At.class' "text-center mb-12"] [
-
El.txt "Explore the type-safe color system and typography utilities in Tailwind OCaml."
-
];
+
p ~styles:[
+
font_size `Lg;
+
text_color (gray 600);
+
text_center;
+
margin_bottom (rem 3.0);
+
] [txt "Explore type-safe colors and typography with the GADT interface"];
-
(* Color Palette Section *)
-
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (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"];
+
(* Color demonstrations *)
+
section ~styles:[margin_bottom (rem 3.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 2.0);
+
] [txt "Color Palette"];
-
El.div ~at:[classes_attr (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 [
-
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 [
-
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 [
-
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 [
-
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])] [
-
El.txt "The quick brown fox jumps over the lazy dog"
-
];
-
]
-
) color_examples);
+
(* Using CSS Grid for color cards *)
+
div ~styles:[
+
grid;
+
grid_cols 2;
+
gap (rem 1.0);
+
] [
+
card [
+
p ~styles:[text_color (blue 600); font_size `Lg]
+
[txt "Blue 600 - Primary color"];
+
];
+
card [
+
p ~styles:[text_color (green 500); font_size `Lg]
+
[txt "Green 500 - Success color"];
+
];
+
card [
+
p ~styles:[text_color (red 500); font_size `Lg]
+
[txt "Red 500 - Error color"];
+
];
+
card [
+
p ~styles:[text_color (purple 600); font_size `Lg]
+
[txt "Purple 600 - Accent color"];
+
];
+
];
];
-
(* Typography Scale Section *)
-
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (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"];
+
(* Typography scale *)
+
section [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 2.0);
+
] [txt "Typography Scale"];
-
El.div ~at:[classes_attr (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 [
-
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 [
-
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 [
-
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.p ~at:[classes_attr (tw [typ_class])] [
-
El.txt "The quick brown fox jumps over the lazy dog"
-
];
-
]
-
) typography_examples);
-
];
-
-
(* Font Weights Section *)
-
El.section [
-
El.h2 ~at:[classes_attr (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 "Font Weights"];
-
-
let weight_examples = [
-
("Light", Typography.(to_class (font_weight `Light)));
-
("Normal", Typography.(to_class (font_weight `Normal)));
-
("Medium", Typography.(to_class (font_weight `Medium)));
-
("Semibold", Typography.(to_class (font_weight `Semibold)));
-
("Bold", Typography.(to_class (font_weight `Bold)));
-
("Extrabold", Typography.(to_class (font_weight `Extrabold)));
-
] in
-
-
El.div ~at:[classes_attr (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 [
-
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 [
-
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 [
-
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.p ~at:[classes_attr (tw [
-
weight_class;
-
Typography.(to_class (font_size `Lg));
-
])] [
-
El.txt "The quick brown fox jumps over the lazy dog"
-
];
-
]
-
) weight_examples);
+
card [
+
p ~styles:[font_size `Xs; margin_bottom (rem 1.0)] [txt "Extra Small (xs) - Supporting text"];
+
p ~styles:[font_size `Sm; margin_bottom (rem 1.0)] [txt "Small (sm) - Caption text"];
+
p ~styles:[font_size `Base; margin_bottom (rem 1.0)] [txt "Base - Body text"];
+
p ~styles:[font_size `Lg; margin_bottom (rem 1.0)] [txt "Large (lg) - Lead text"];
+
p ~styles:[font_size `Xl; margin_bottom (rem 1.0)] [txt "Extra Large (xl) - Heading"];
+
p ~styles:[font_size `Xl2] [txt "2XL - Large heading"];
+
];
];
];
];
] in
-
html_doc
+
html
let () =
-
(* Output HTML to stdout *)
-
let html_doc = create_color_demo () in
-
print_string (El.to_string ~doctype:true html_doc)
+
let html = create_color_demo () in
+
print_string (El.to_string ~doctype:true html)
-287
examples/complete_demo.ml
···
-
(* Complete demonstration of Tailwind OCaml library with HTML generation *)
-
-
open Htmlit
-
-
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
-
-
let create_navbar () =
-
let nav_classes = Tailwind.tw [
-
Tailwind.Color.bg Tailwind.Color.white;
-
Tailwind.Effects.shadow_sm;
-
Tailwind.Effects.border;
-
Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V200 ());
-
] in
-
-
El.nav ~at:[classes_attr nav_classes] [
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Css.make "max-w-7xl";
-
Tailwind.Css.make "mx-auto";
-
Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 1.0)));
-
])] [
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Display.flex;
-
Tailwind.Flexbox.(to_class (justify `Between));
-
Tailwind.Flexbox.(to_class (align_items `Center));
-
Tailwind.Layout.(to_class (height (Tailwind.Size.rem 4.0)));
-
])] [
-
(* Brand *)
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Typography.(to_class (font_size `Xl));
-
Tailwind.Typography.(to_class (font_weight `Bold));
-
Tailwind.Color.text (Tailwind.Color.make `Blue ~variant:`V600 ());
-
])] [El.txt "Tailwind OCaml"];
-
-
(* Navigation items *)
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Display.hidden;
-
Tailwind.Responsive.(to_class (at_breakpoint `Md (Tailwind.Display.flex)));
-
Tailwind.Spacing.(to_class (gap `All (Tailwind.Size.rem 2.0)));
-
])] [
-
El.a ~at:[
-
At.href "#";
-
classes_attr (Tailwind.tw [
-
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V600 ());
-
Tailwind.Variants.hover (Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V900 ()));
-
]);
-
] [El.txt "Features"];
-
El.a ~at:[
-
At.href "#";
-
classes_attr (Tailwind.tw [
-
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V600 ());
-
Tailwind.Variants.hover (Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V900 ()));
-
]);
-
] [El.txt "Docs"];
-
El.a ~at:[
-
At.href "#";
-
classes_attr (Tailwind.tw [
-
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V600 ());
-
Tailwind.Variants.hover (Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V900 ()));
-
]);
-
] [El.txt "About"];
-
];
-
-
(* CTA Button *)
-
El.button ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V600 ());
-
Tailwind.Color.text Tailwind.Color.white;
-
Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 1.0)));
-
Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 0.5)));
-
Tailwind.Effects.rounded_md;
-
Tailwind.Typography.(to_class (font_size `Sm));
-
Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V700 ()));
-
])] [El.txt "Get Started"];
-
];
-
];
-
]
-
-
let create_hero () =
-
El.section ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Position.(to_class (position `Relative));
-
Tailwind.Display.flex;
-
Tailwind.Flexbox.(to_class (align_items `Center));
-
Tailwind.Flexbox.(to_class (justify `Center));
-
Tailwind.Layout.(to_class (min_height (Tailwind.Size.screen)));
-
Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V900 ());
-
Tailwind.Color.text Tailwind.Color.white;
-
])] [
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Css.make "text-center";
-
Tailwind.Css.make "max-w-4xl";
-
Tailwind.Css.make "mx-auto";
-
Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 1.0)));
-
])] [
-
El.h1 ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Typography.(to_class (font_size `Xl4));
-
Tailwind.Typography.(to_class (font_weight `Bold));
-
Tailwind.Spacing.(to_class (mb (Tailwind.Size.rem 1.5)));
-
])] [El.txt "Type-Safe Tailwind CSS for OCaml"];
-
-
El.p ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Typography.(to_class (font_size `Xl));
-
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V300 ());
-
Tailwind.Spacing.(to_class (mb (Tailwind.Size.rem 2.0)));
-
])] [El.txt "Build beautiful, responsive web interfaces with the power of OCaml's type system and Tailwind's utility classes."];
-
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Display.flex;
-
Tailwind.Flexbox.(to_class (justify `Center));
-
Tailwind.Spacing.(to_class (gap `All (Tailwind.Size.rem 1.0)));
-
])] [
-
El.button ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V600 ());
-
Tailwind.Color.text Tailwind.Color.white;
-
Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 2.0)));
-
Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 0.75)));
-
Tailwind.Effects.rounded_lg;
-
Tailwind.Typography.(to_class (font_size `Lg));
-
Tailwind.Typography.(to_class (font_weight `Medium));
-
Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V700 ()));
-
])] [El.txt "Get Started"];
-
-
El.button ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Effects.border;
-
Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V300 ());
-
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V300 ());
-
Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 2.0)));
-
Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 0.75)));
-
Tailwind.Effects.rounded_lg;
-
Tailwind.Typography.(to_class (font_size `Lg));
-
Tailwind.Typography.(to_class (font_weight `Medium));
-
Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V800 ()));
-
])] [El.txt "View Docs"];
-
];
-
];
-
]
-
-
let create_feature_card ~icon ~title ~description =
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Effects.rounded_lg;
-
Tailwind.Effects.border;
-
Tailwind.Color.border (Tailwind.Color.make `Gray ~variant:`V200 ());
-
Tailwind.Color.bg Tailwind.Color.white;
-
Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5)));
-
Tailwind.Effects.shadow_sm;
-
])] [
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Spacing.(to_class (mb (Tailwind.Size.rem 1.0)));
-
])] [El.txt icon];
-
-
El.h3 ~at:[classes_attr (Tailwind.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)));
-
])] [El.txt title];
-
-
El.p ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V600 ());
-
])] [El.txt description];
-
]
-
-
let create_features () =
-
El.section ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 5.0)));
-
])] [
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Css.make "max-w-7xl";
-
Tailwind.Css.make "mx-auto";
-
Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 1.0)));
-
])] [
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Css.make "text-center";
-
Tailwind.Spacing.(to_class (mb (Tailwind.Size.rem 3.0)));
-
])] [
-
El.h2 ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Typography.(to_class (font_size `Xl3));
-
Tailwind.Typography.(to_class (font_weight `Bold));
-
Tailwind.Spacing.(to_class (mb (Tailwind.Size.rem 1.0)));
-
])] [El.txt "Why Choose Tailwind OCaml?"];
-
-
El.p ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Typography.(to_class (font_size `Lg));
-
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V600 ());
-
])] [El.txt "Everything you need to build modern web applications with OCaml"];
-
];
-
-
El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Display.grid;
-
Tailwind.Grid.(to_class (template_cols (`Cols 1)));
-
Tailwind.Responsive.(to_class (at_breakpoint `Md (Tailwind.Grid.(to_class (template_cols (`Cols 2))))));
-
Tailwind.Responsive.(to_class (at_breakpoint `Lg (Tailwind.Grid.(to_class (template_cols (`Cols 3))))));
-
Tailwind.Spacing.(to_class (gap `All (Tailwind.Size.rem 2.0)));
-
])] [
-
create_feature_card ~icon:"๐Ÿ”’" ~title:"Type Safety"
-
~description:"Catch CSS errors at compile time with OCaml's powerful type system";
-
create_feature_card ~icon:"โšก" ~title:"Performance"
-
~description:"Zero runtime overhead - all CSS classes are generated at compile time";
-
create_feature_card ~icon:"๐ŸŽจ" ~title:"Full Tailwind"
-
~description:"Complete coverage of Tailwind CSS v4 including the latest features";
-
create_feature_card ~icon:"๐Ÿ”ง" ~title:"Composable"
-
~description:"Build complex layouts by composing simple, reusable utility functions";
-
create_feature_card ~icon:"๐Ÿ“ฑ" ~title:"Responsive"
-
~description:"First-class support for responsive design and media queries";
-
create_feature_card ~icon:"๐Ÿš€" ~title:"Modern"
-
~description:"Support for CSS Grid, Flexbox, and modern web standards";
-
];
-
];
-
]
-
-
let () =
-
Printf.printf "=== Complete Tailwind OCaml Demo ===\n";
-
-
let html_doc = El.html [
-
El.head [
-
El.meta ~at:[At.charset "utf-8"] ();
-
El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] ();
-
El.title [El.txt "Tailwind OCaml - Type-Safe CSS Utilities"];
-
El.script ~at:[At.src "https://cdn.tailwindcss.com"] [];
-
];
-
-
El.body [
-
create_navbar ();
-
create_hero ();
-
create_features ();
-
];
-
] in
-
-
let html_string = El.to_string ~doctype:true html_doc in
-
-
Printf.printf "Generated complete website (%d characters)\n" (String.length html_string);
-
-
(* Show a snippet of the generated HTML *)
-
let preview_length = 800 in
-
let preview = if String.length html_string > preview_length then
-
(String.sub html_string 0 preview_length) ^ "..."
-
else html_string in
-
-
Printf.printf "\nHTML Preview:\n%s\n" preview;
-
-
(* Demonstrate advanced class combinations *)
-
Printf.printf "\n=== Advanced Class Combinations ===\n";
-
-
let responsive_card = Tailwind.tw [
-
(* Base styles *)
-
Tailwind.Effects.rounded_lg;
-
Tailwind.Color.bg Tailwind.Color.white;
-
Tailwind.Effects.shadow_sm;
-
-
(* Responsive padding *)
-
Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.0)));
-
Tailwind.Responsive.(to_class (at_breakpoint `Md (Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5))))));
-
Tailwind.Responsive.(to_class (at_breakpoint `Lg (Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 2.0))))));
-
-
(* Hover effects *)
-
Tailwind.Effects.transition `All;
-
Tailwind.Variants.hover (Tailwind.Effects.shadow_md);
-
-
(* Dark mode support *)
-
Tailwind.Responsive.(to_class (media `Dark (Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V800 ()))));
-
] in
-
Printf.printf "Responsive Card: %s\n" (Tailwind.to_string responsive_card);
-
-
let complex_button = Tailwind.tw [
-
(* Button base *)
-
Tailwind.Display.inline_flex;
-
Tailwind.Flexbox.(to_class (align_items `Center));
-
Tailwind.Flexbox.(to_class (justify `Center));
-
Tailwind.Effects.rounded_md;
-
-
(* Typography *)
-
Tailwind.Typography.(to_class (font_size `Sm));
-
Tailwind.Typography.(to_class (font_weight `Medium));
-
-
(* Colors with variants *)
-
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 ()));
-
Tailwind.Variants.focus (Tailwind.Css.make "focus:ring-2");
-
Tailwind.Variants.disabled (Tailwind.Effects.(to_class (opacity 50)));
-
-
(* V4 features *)
-
Tailwind.V4.starting_style (Tailwind.Effects.(to_class (opacity 0)));
-
] in
-
Printf.printf "Complex Button: %s\n" (Tailwind.to_string complex_button);
-
-
Printf.printf "\nโœ… Complete demo generated successfully!\n";
-
Printf.printf "๐Ÿ“„ Ready to serve as a static HTML file\n";
-
Printf.printf "๐ŸŽจ Demonstrates full Tailwind OCaml capabilities\n"
+189 -203
examples/comprehensive_showcase_07.ml
···
-
(* Example 07: Comprehensive Showcase - Full Application Demo *)
+
(* Example 07: Comprehensive Showcase - Full application demo with GADT *)
open Htmlit
-
open Tailwind
+
open Tailwind_html
-
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
-
-
let create_comprehensive_html_page () =
-
(* Document structure with all features demonstrated *)
-
let html_doc = El.html [
+
let create_showcase () =
+
let html = El.html [
El.head [
El.meta ~at:[At.charset "utf-8"] ();
El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] ();
-
El.title [El.txt "Tailwind OCaml - Complete Feature Showcase"];
+
El.title [txt "Comprehensive Showcase"];
El.link ~at:[At.rel "stylesheet"; At.href "comprehensive_showcase_07.css"] ();
];
-
-
El.body ~at:[classes_attr (Tailwind.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 [
-
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 [
-
Patterns.container ();
-
Spacing.(to_class (px (Size.rem 1.0)));
-
])] [
-
El.div ~at:[classes_attr (Tailwind.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 [
-
Typography.(to_class (font_size `Xl2));
-
Typography.(to_class (font_weight `Bold));
-
Color.text (Color.make `Blue ~variant:`V600 ());
-
])] [El.txt "Tailwind OCaml"];
+
El.body ~at:[classes_attr [
+
min_height screen;
+
bg_color (gray 50);
+
]] [
+
(* Header *)
+
header ~styles:[
+
bg_color (Tailwind.Color.white);
+
shadow `Md;
+
padding (rem 1.0);
+
] [
+
container [
+
div ~styles:[
+
flex;
+
justify_between;
+
items_center;
+
] [
+
h1 ~styles:[
+
font_size `Xl;
+
font_weight `Bold;
+
text_color (blue 600);
+
] [txt "TailwindOCaml"];
-
(* Navigation items with hover effects *)
-
El.nav ~at:[classes_attr (Tailwind.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 [
-
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 [
-
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 [
-
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 [
-
Color.bg (Color.make `Blue ~variant:`V600 ());
-
Color.text Color.white;
-
Spacing.(to_class (px (Size.rem 1.0)));
-
Spacing.(to_class (py (Size.rem 0.5)));
-
Effects.rounded_md;
-
Typography.(to_class (font_size `Sm));
-
Typography.(to_class (font_weight `Medium));
-
Variants.hover (Color.bg (Color.make `Blue ~variant:`V700 ()));
-
Effects.transition `All;
-
])] [El.txt "Get Started"];
+
nav ~styles:[flex] [
+
a ~styles:[
+
padding_x (rem 1.0);
+
text_color (gray 700);
+
font_weight `Medium;
+
] ~href:"#features" [txt "Features"];
+
a ~styles:[
+
padding_x (rem 1.0);
+
text_color (gray 700);
+
font_weight `Medium;
+
] ~href:"#demo" [txt "Demo"];
+
a ~styles:[
+
padding_x (rem 1.0);
+
text_color (gray 700);
+
font_weight `Medium;
+
] ~href:"#contact" [txt "Contact"];
];
];
];
];
-
(* Main Content *)
-
El.main [
-
(* Hero Section *)
-
El.section ~at:[At.id "hero"; classes_attr (Tailwind.tw [
-
Layout.(to_class (min_height Size.screen));
-
Display.flex;
-
Flexbox.(to_class (align_items `Center));
-
Flexbox.(to_class (justify `Center));
-
Color.bg (Color.make `Gray ~variant:`V900 ());
-
Color.text Color.white;
-
])] [
-
El.div ~at:[At.class' "text-center container px-8"] [
-
El.h1 ~at:[classes_attr (Tailwind.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"];
+
(* Hero Section *)
+
main ~styles:[padding_y (rem 4.0)] [
+
container [
+
div ~styles:[text_center; margin_bottom (rem 4.0)] [
+
h2 ~styles:[
+
font_size `Xl3;
+
font_weight `Bold;
+
text_color (gray 800);
+
margin_bottom (rem 1.5);
+
] [txt "Type-Safe CSS with GADT Interface"];
-
El.p ~at:[classes_attr (Tailwind.tw [
-
Typography.(to_class (font_size `Xl));
-
Color.text (Color.make `Gray ~variant:`V100 ());
-
Spacing.(to_class (mb (Size.rem 2.0)));
-
Typography.(to_class (line_height `Relaxed));
-
])] [El.txt "Build beautiful, responsive web interfaces with OCaml's type system and Tailwind's utility classes."];
+
p ~styles:[
+
font_size `Xl;
+
text_color (gray 600);
+
margin_bottom (rem 2.0);
+
] [txt "Build beautiful, maintainable UIs with compile-time guarantees"];
-
El.div ~at:[At.class' "flex flex-wrap gap-4 justify-center"] [
-
El.button ~at:[At.class' "btn-primary"] [El.txt "๐Ÿš€ Get Started"];
-
El.button ~at:[At.class' "btn-ghost text-white hover:bg-white hover:text-gray-900"] [El.txt "๐Ÿ“– View Docs"];
+
div ~styles:[flex; justify_center] [
+
btn_primary ~size:`Lg [txt "Get Started"];
+
btn_outline ~size:`Lg [txt "Learn More"];
];
];
-
];
-
-
(* Features Grid *)
-
El.section ~at:[At.class' "section bg-white"] [
-
El.div ~at:[At.class' "container"] [
-
El.h2 ~at:[At.class' "text-3xl font-bold text-center mb-12"] [El.txt "Features"];
+
+
(* Features Grid *)
+
section ~styles:[margin_bottom (rem 4.0)] [
+
h3 ~styles:[
+
font_size `Xl2;
+
font_weight `Bold;
+
text_color (gray 800);
+
text_center;
+
margin_bottom (rem 3.0);
+
] [txt "Features"];
-
El.div ~at:[At.class' "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"] [
-
(* Feature cards *)
-
El.div ~at:[At.class' "card p-6"] [
-
El.div ~at:[At.class' "w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center mb-4"] [
-
El.span ~at:[At.class' "text-2xl"] [El.txt "๐ŸŽจ"];
-
];
-
El.h3 ~at:[At.class' "text-lg font-semibold mb-2"] [El.txt "Type-Safe Classes"];
-
El.p ~at:[At.class' "text-gray-600"] [
-
El.txt "Compile-time validation ensures your Tailwind classes are always correct."
-
];
-
];
-
-
El.div ~at:[At.class' "card p-6"] [
-
El.div ~at:[At.class' "w-12 h-12 bg-green-100 rounded-lg flex items-center justify-center mb-4"] [
-
El.span ~at:[At.class' "text-2xl"] [El.txt "โšก"];
-
];
-
El.h3 ~at:[At.class' "text-lg font-semibold mb-2"] [El.txt "Fast Development"];
-
El.p ~at:[At.class' "text-gray-600"] [
-
El.txt "Autocomplete and type hints speed up your development workflow."
+
div ~styles:[
+
grid;
+
grid_cols 1;
+
gap (rem 2.0);
+
] [
+
card [
+
h4 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (blue 600);
+
margin_bottom (rem 1.0);
+
] [txt "๐ŸŽฏ Type Safety"];
+
p ~styles:[text_color (gray 600)] [
+
txt "Catch styling errors at compile time with GADT-based type checking."
];
];
-
El.div ~at:[At.class' "card p-6"] [
-
El.div ~at:[At.class' "w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center mb-4"] [
-
El.span ~at:[At.class' "text-2xl"] [El.txt "๐Ÿ”ง"];
-
];
-
El.h3 ~at:[At.class' "text-lg font-semibold mb-2"] [El.txt "Modular Design"];
-
El.p ~at:[At.class' "text-gray-600"] [
-
El.txt "Organized modules for colors, typography, layout, and more."
+
card [
+
h4 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (green 600);
+
margin_bottom (rem 1.0);
+
] [txt "โšก Performance"];
+
p ~styles:[text_color (gray 600)] [
+
txt "Zero runtime overhead with compile-time CSS generation."
];
];
-
El.div ~at:[At.class' "card p-6"] [
-
El.div ~at:[At.class' "w-12 h-12 bg-red-100 rounded-lg flex items-center justify-center mb-4"] [
-
El.span ~at:[At.class' "text-2xl"] [El.txt "๐Ÿ“ฑ"];
-
];
-
El.h3 ~at:[At.class' "text-lg font-semibold mb-2"] [El.txt "Responsive Design"];
-
El.p ~at:[At.class' "text-gray-600"] [
-
El.txt "Built-in responsive utilities for all screen sizes."
+
card [
+
h4 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (purple 600);
+
margin_bottom (rem 1.0);
+
] [txt "๐Ÿ”ง Developer Experience"];
+
p ~styles:[text_color (gray 600)] [
+
txt "Succinct syntax with heterogeneous lists and type inference."
];
];
+
];
+
];
+
+
(* Demo Section *)
+
section ~styles:[margin_bottom (rem 4.0)] [
+
h3 ~styles:[
+
font_size `Xl2;
+
font_weight `Bold;
+
text_color (gray 800);
+
text_center;
+
margin_bottom (rem 3.0);
+
] [txt "Live Demo"];
+
+
card ~elevated:true [
+
h4 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 800);
+
margin_bottom (rem 1.5);
+
] [txt "Interactive Component"];
-
El.div ~at:[At.class' "card p-6"] [
-
El.div ~at:[At.class' "w-12 h-12 bg-yellow-100 rounded-lg flex items-center justify-center mb-4"] [
-
El.span ~at:[At.class' "text-2xl"] [El.txt "๐ŸŽฏ"];
-
];
-
El.h3 ~at:[At.class' "text-lg font-semibold mb-2"] [El.txt "Production Ready"];
-
El.p ~at:[At.class' "text-gray-600"] [
-
El.txt "Generate optimized CSS with Tailwind v4 CLI integration."
-
];
+
div ~styles:[margin_bottom (rem 2.0)] [
+
El.label ~at:[At.for' "demo-input"; classes_attr [
+
block;
+
font_weight `Medium;
+
text_color (gray 700);
+
margin_bottom (rem 0.5);
+
]] [txt "Try it out:"];
+
El.input ~at:[At.type' "text"; At.id "demo-input"; At.placeholder "Type something..."; classes_attr [
+
width full;
+
padding (rem 0.75);
+
border;
+
border_color (gray 300);
+
rounded `Md;
+
]] ();
];
-
El.div ~at:[At.class' "card p-6"] [
-
El.div ~at:[At.class' "w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4"] [
-
El.span ~at:[At.class' "text-2xl"] [El.txt "๐Ÿš€"];
-
];
-
El.h3 ~at:[At.class' "text-lg font-semibold mb-2"] [El.txt "Modern Workflow"];
-
El.p ~at:[At.class' "text-gray-600"] [
-
El.txt "Integrates seamlessly with dune and modern OCaml tooling."
-
];
+
div ~styles:[flex; justify_end] [
+
btn_secondary [txt "Cancel"];
+
btn_primary [txt "Submit"];
];
];
];
-
];
-
-
(* Code Example Section *)
-
El.section ~at:[At.class' "section bg-gray-50"] [
-
El.div ~at:[At.class' "container"] [
-
El.h2 ~at:[At.class' "text-3xl font-bold text-center mb-12"] [El.txt "Simple & Intuitive"];
+
+
(* Statistics *)
+
section ~styles:[margin_bottom (rem 4.0)] [
+
h3 ~styles:[
+
font_size `Xl2;
+
font_weight `Bold;
+
text_color (gray 800);
+
text_center;
+
margin_bottom (rem 3.0);
+
] [txt "By the Numbers"];
-
El.div ~at:[At.class' "max-w-4xl mx-auto"] [
-
El.div ~at:[At.class' "bg-gray-900 rounded-lg p-6 text-white"] [
-
El.pre ~at:[At.class' "text-sm overflow-x-auto"] [
-
El.code [El.txt {|open Tailwind
-
-
let button_classes = tw [
-
Color.bg (Color.make `Blue ~variant:`V600 ());
-
Color.text Color.white;
-
Spacing.(to_class (px (Size.rem 1.0)));
-
Spacing.(to_class (py (Size.rem 0.5)));
-
Effects.rounded_md;
-
Typography.(to_class (font_weight `Semibold));
-
Variants.hover (Color.bg (Color.make `Blue ~variant:`V700 ()));
-
]
-
-
let button =
-
El.button ~at:[At.class' (to_string button_classes)] [
-
El.txt "Click me!"
-
]|}];
-
];
+
div ~styles:[flex; justify_between; text_center] [
+
div [
+
p ~styles:[
+
font_size `Xl3;
+
font_weight `Bold;
+
text_color (blue 600);
+
] [txt "100%"];
+
p ~styles:[text_color (gray 600)] [txt "Type Safe"];
+
];
+
+
div [
+
p ~styles:[
+
font_size `Xl3;
+
font_weight `Bold;
+
text_color (green 600);
+
] [txt "0ms"];
+
p ~styles:[text_color (gray 600)] [txt "Runtime Cost"];
+
];
+
+
div [
+
p ~styles:[
+
font_size `Xl3;
+
font_weight `Bold;
+
text_color (purple 600);
+
] [txt "โˆž"];
+
p ~styles:[text_color (gray 600)] [txt "Possibilities"];
];
];
];
···
];
(* Footer *)
-
El.footer ~at:[At.class' "bg-gray-800 text-white py-12"] [
-
El.div ~at:[At.class' "container text-center"] [
-
El.p ~at:[At.class' "text-lg font-semibold mb-4"] [El.txt "Tailwind OCaml"];
-
El.p ~at:[At.class' "text-gray-300 mb-6"] [
-
El.txt "Type-safe Tailwind CSS for OCaml applications"
+
footer ~styles:[
+
bg_color (gray 800);
+
text_color (gray 200);
+
padding_y (rem 2.0);
+
text_center;
+
] [
+
container [
+
p ~styles:[margin_bottom (rem 1.0)] [
+
txt "ยฉ 2024 TailwindOCaml. Built with type-safe GADT interface."
];
-
El.div ~at:[At.class' "flex flex-wrap gap-8 justify-center"] [
-
El.a ~at:[At.href "#"; At.class' "text-gray-300 hover:text-white transition-colors"] [
-
El.txt "Documentation"
-
];
-
El.a ~at:[At.href "#"; At.class' "text-gray-300 hover:text-white transition-colors"] [
-
El.txt "GitHub"
-
];
-
El.a ~at:[At.href "#"; At.class' "text-gray-300 hover:text-white transition-colors"] [
-
El.txt "Examples"
-
];
-
El.a ~at:[At.href "#"; At.class' "text-gray-300 hover:text-white transition-colors"] [
-
El.txt "Support"
-
];
+
p ~styles:[font_size `Sm; text_color (gray 400)] [
+
txt "Powered by OCaml, Tailwind CSS, and compile-time guarantees."
];
];
];
];
] in
-
html_doc
+
html
let () =
-
(* Output HTML to stdout *)
-
let html_doc = create_comprehensive_html_page () in
-
let html_string = El.to_string ~doctype:true html_doc in
-
print_string html_string
+
let html = create_showcase () in
+
print_string (El.to_string ~doctype:true html)
+48 -22
examples/dune
···
-
;; Notebook-style examples - progressive learning path
+
;; Examples demonstrating GADT-based Tailwind interface
(executables
(public_names
index
hello_tailwind
colors_and_typography
layout_and_spacing
-
responsive_design
-
effects_and_variants
-
patterns_and_components
-
comprehensive_showcase)
+
responsive_design
+
effects_and_variants
+
patterns_and_components
+
comprehensive_showcase
+
button_demo)
(names
index_00
hello_tailwind_01
···
responsive_design_04
effects_and_variants_05
patterns_and_components_06
-
comprehensive_showcase_07)
+
comprehensive_showcase_07
+
button_demo)
(package tailwind)
(libraries tailwind tailwind-html htmlit unix))
-
;; Legacy examples (maintained for compatibility)
-
(executables
-
(public_names basic_usage module_usage advanced_features simple_html_example complete_demo tailwind_html_example improved_api_demo)
-
(names basic_usage module_usage advanced_features simple_html_example complete_demo tailwind_html_example improved_api_demo)
+
;; HTML index generator
+
(executable
+
(public_name index_html_generator)
+
(name index_html_generator)
(package tailwind)
-
(libraries tailwind htmlit unix))
+
(libraries tailwind tailwind-html htmlit))
;; Generate HTML files from examples
(rule
···
(deps (:exe comprehensive_showcase_07.exe))
(action (with-stdout-to %{target} (run %{exe}))))
+
(rule
+
(target button_demo.html)
+
(deps (:exe button_demo.exe))
+
(action (with-stdout-to %{target} (run %{exe}))))
+
;; Generate CSS files using Tailwind CLI
(rule
(targets hello_tailwind_01.css)
···
input.css
hello_tailwind_01.html)
(action
-
(run npx @tailwindcss/cli --input input.css --output %{targets} --content hello_tailwind_01.html --minify)))
+
(run tailwindcss --input input.css --output %{targets} --minify)))
(rule
(targets colors_and_typography_02.css)
···
input.css
colors_and_typography_02.html)
(action
-
(run npx @tailwindcss/cli --input input.css --output %{targets} --content colors_and_typography_02.html --minify)))
+
(run tailwindcss --input input.css --output %{targets} --minify)))
(rule
(targets layout_and_spacing_03.css)
···
input.css
layout_and_spacing_03.html)
(action
-
(run npx @tailwindcss/cli --input input.css --output %{targets} --content layout_and_spacing_03.html --minify)))
+
(run tailwindcss --input input.css --output %{targets} --minify)))
(rule
(targets responsive_design_04.css)
···
input.css
responsive_design_04.html)
(action
-
(run npx @tailwindcss/cli --input input.css --output %{targets} --content responsive_design_04.html --minify)))
+
(run tailwindcss --input input.css --output %{targets} --minify)))
(rule
(targets effects_and_variants_05.css)
···
input.css
effects_and_variants_05.html)
(action
-
(run npx @tailwindcss/cli --input input.css --output %{targets} --content effects_and_variants_05.html --minify)))
+
(run tailwindcss --input input.css --output %{targets} --minify)))
(rule
(targets patterns_and_components_06.css)
···
input.css
patterns_and_components_06.html)
(action
-
(run npx @tailwindcss/cli --input input.css --output %{targets} --content patterns_and_components_06.html --minify)))
+
(run tailwindcss --input input.css --output %{targets} --minify)))
(rule
(targets comprehensive_showcase_07.css)
···
input.css
comprehensive_showcase_07.html)
(action
-
(run npx @tailwindcss/cli --input input.css --output %{targets} --content comprehensive_showcase_07.html --minify)))
+
(run tailwindcss --input input.css --output %{targets} --minify)))
+
+
(rule
+
(targets button_demo.css)
+
(deps
+
input.css
+
button_demo.html)
+
(action
+
(run tailwindcss --input input.css --output %{targets} --minify)))
+
+
;; Generate index.html page
+
(rule
+
(target index.html)
+
(deps (:exe index_html_generator.exe))
+
(action (with-stdout-to %{target} (run %{exe}))))
;; Alias to build all HTML files
(alias
(name examples-html)
(deps
+
index.html
hello_tailwind_01.html
colors_and_typography_02.html
layout_and_spacing_03.html
responsive_design_04.html
effects_and_variants_05.html
patterns_and_components_06.html
-
comprehensive_showcase_07.html))
+
comprehensive_showcase_07.html
+
button_demo.html))
;; Alias to build all CSS files (requires Tailwind CLI)
-
;; Run: npm install -D @tailwindcss/cli
(alias
(name examples-css)
(deps
···
responsive_design_04.css
effects_and_variants_05.css
patterns_and_components_06.css
-
comprehensive_showcase_07.css))
+
comprehensive_showcase_07.css
+
button_demo.css))
;; Install generated files
(install
(section doc)
(package tailwind)
(files
+
(index.html as examples/index.html)
(hello_tailwind_01.html as examples/hello_tailwind_01.html)
(hello_tailwind_01.css as examples/hello_tailwind_01.css)
(colors_and_typography_02.html as examples/colors_and_typography_02.html)
···
(patterns_and_components_06.html as examples/patterns_and_components_06.html)
(patterns_and_components_06.css as examples/patterns_and_components_06.css)
(comprehensive_showcase_07.html as examples/comprehensive_showcase_07.html)
-
(comprehensive_showcase_07.css as examples/comprehensive_showcase_07.css)))
+
(comprehensive_showcase_07.css as examples/comprehensive_showcase_07.css)
+
(button_demo.html as examples/button_demo.html)
+
(button_demo.css as examples/button_demo.css)))
+183 -279
examples/effects_and_variants_05.ml
···
-
(* Example 05: Effects and Variants - Interactive Elements and Visual Effects *)
+
(* Example 05: Effects and Variants - Visual effects with GADT *)
open Htmlit
-
open Tailwind
-
-
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
+
open Tailwind_html
let create_effects_demo () =
-
-
(* Create comprehensive effects demonstration *)
-
let html_doc = El.html [
+
let html = El.html [
El.head [
El.meta ~at:[At.charset "utf-8"] ();
El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] ();
-
El.title [El.txt "Effects and Variants"];
+
El.title [txt "Effects and Variants"];
El.link ~at:[At.rel "stylesheet"; At.href "effects_and_variants_05.css"] ();
];
-
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 [
-
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 "Effects and Variants Demo"];
+
El.body ~at:[classes_attr [
+
min_height screen;
+
bg_color (gray 50);
+
padding (rem 2.0);
+
]] [
+
container [
+
h1 ~styles:[
+
font_size `Xl2;
+
font_weight `Bold;
+
text_color (gray 800);
+
text_center;
+
margin_bottom (rem 2.0);
+
] [txt "Effects and Variants Demo"];
(* Shadow Effects *)
-
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (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"];
+
section ~styles:[margin_bottom (rem 2.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "Shadow Effects"];
-
El.div ~at:[classes_attr (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 [
-
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 [
-
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 [
-
Typography.(to_class (font_size `Sm));
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
])] [El.txt "shadow-sm"];
+
div ~styles:[
+
grid;
+
grid_cols 1;
+
gap (rem 1.0);
+
] [
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.5);
+
shadow `Sm;
+
rounded `Lg;
+
margin_bottom (rem 1.0);
+
text_center;
+
] [
+
h3 ~styles:[
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 0.5);
+
] [txt "Small Shadow"];
+
p ~styles:[
+
font_size `Sm;
+
text_color (gray 600);
+
] [txt "shadow-sm"];
];
-
El.div ~at:[classes_attr (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 [
-
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 [
-
Typography.(to_class (font_size `Sm));
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
])] [El.txt "shadow-md"];
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.5);
+
shadow `Md;
+
rounded `Lg;
+
margin_bottom (rem 1.0);
+
text_center;
+
] [
+
h3 ~styles:[
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 0.5);
+
] [txt "Medium Shadow"];
+
p ~styles:[
+
font_size `Sm;
+
text_color (gray 600);
+
] [txt "shadow-md"];
];
-
El.div ~at:[classes_attr (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 [
-
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 [
-
Typography.(to_class (font_size `Sm));
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
])] [El.txt "shadow-lg"];
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.5);
+
shadow `Lg;
+
rounded `Lg;
+
text_center;
+
] [
+
h3 ~styles:[
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 0.5);
+
] [txt "Large Shadow"];
+
p ~styles:[
+
font_size `Sm;
+
text_color (gray 600);
+
] [txt "shadow-lg"];
];
];
];
(* Rounded Corners *)
-
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (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"];
+
section ~styles:[margin_bottom (rem 2.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "Border Radius"];
-
El.div ~at:[classes_attr (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 [
-
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"];
+
div ~styles:[
+
grid;
+
grid_cols 2;
+
gap (rem 1.0);
+
] [
+
div ~styles:[
+
bg_color (blue 100);
+
padding (rem 1.0);
+
rounded `Sm;
+
text_center;
+
margin_bottom (rem 1.0);
+
] [txt "Small Radius"];
-
El.div ~at:[classes_attr (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"];
+
div ~styles:[
+
bg_color (green 100);
+
padding (rem 1.0);
+
rounded `Md;
+
text_center;
+
margin_bottom (rem 1.0);
+
] [txt "Medium Radius"];
-
El.div ~at:[classes_attr (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 [
-
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"];
+
div ~styles:[
+
bg_color (purple 100);
+
padding (rem 1.0);
+
rounded `Lg;
+
text_center;
+
margin_bottom (rem 1.0);
+
] [txt "Large Radius"];
-
El.div ~at:[classes_attr (tw [
-
Color.bg (Color.make `Yellow ~variant:`V100 ());
-
Spacing.(to_class (p (Size.rem 1.0)));
-
Effects.rounded_full;
-
]); At.class' "text-center"] [El.txt "Full"];
+
div ~styles:[
+
bg_color (yellow 100);
+
padding (rem 1.0);
+
rounded `Full;
+
text_center;
+
] [txt "Full Radius"];
];
];
(* Interactive Buttons *)
-
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (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"];
+
section ~styles:[margin_bottom (rem 2.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "Interactive Buttons"];
-
El.div ~at:[classes_attr (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 [
-
Color.bg (Color.make `Blue ~variant:`V500 ());
-
Color.text Color.white;
-
Spacing.(to_class (px (Size.rem 1.5)));
-
Spacing.(to_class (py (Size.rem 0.75)));
-
Effects.rounded_md;
-
Typography.(to_class (font_weight `Medium));
-
Effects.transition `All;
-
Variants.hover (Color.bg (Color.make `Blue ~variant:`V600 ()));
-
])] [El.txt "Hover Color"];
-
-
(* Hover shadow *)
-
El.button ~at:[classes_attr (tw [
-
Color.bg (Color.make `Green ~variant:`V500 ());
-
Color.text Color.white;
-
Spacing.(to_class (px (Size.rem 1.5)));
-
Spacing.(to_class (py (Size.rem 0.75)));
-
Effects.rounded_md;
-
Typography.(to_class (font_weight `Medium));
-
Effects.shadow_md;
-
Effects.transition `All;
-
Variants.hover Effects.shadow_lg;
-
])] [El.txt "Hover Shadow"];
-
-
(* Scale effect *)
-
El.button ~at:[classes_attr (tw [
-
Color.bg (Color.make `Purple ~variant:`V500 ());
-
Color.text Color.white;
-
Spacing.(to_class (px (Size.rem 1.5)));
-
Spacing.(to_class (py (Size.rem 0.75)));
-
Effects.rounded_md;
-
Typography.(to_class (font_weight `Medium));
-
Effects.transition `All;
-
]); At.class' "hover:scale-105 active:scale-95"] [El.txt "Scale Effect"];
-
-
(* Focus ring *)
-
El.button ~at:[classes_attr (tw [
-
Color.bg (Color.make `Red ~variant:`V500 ());
-
Color.text Color.white;
-
Spacing.(to_class (px (Size.rem 1.5)));
-
Spacing.(to_class (py (Size.rem 0.75)));
-
Effects.rounded_md;
-
Typography.(to_class (font_weight `Medium));
-
Effects.transition `All;
-
Variants.focus Effects.shadow_md;
-
])] [El.txt "Focus Ring"];
-
];
-
];
-
-
(* Card Hover Effects *)
-
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (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 [
-
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 [
-
Color.bg Color.white;
-
Spacing.(to_class (p (Size.rem 1.5)));
-
Effects.rounded_lg;
-
Effects.shadow_md;
-
Effects.transition `All;
-
Variants.hover Effects.shadow_lg;
-
]); At.class' "cursor-pointer"] [
-
El.h3 ~at:[classes_attr (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 [
-
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 [
-
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 [
-
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 [
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
])] [El.txt "This card both scales up and increases shadow on hover."];
-
];
+
div ~styles:[
+
grid;
+
grid_cols 1;
+
gap (rem 1.0);
+
] [
+
btn_primary [txt "Primary Button with Hover"];
+
btn_secondary [txt "Secondary Button"];
+
btn_outline [txt "Outline Button"];
];
];
(* Border Effects *)
-
El.section [
-
El.h2 ~at:[classes_attr (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"];
+
section [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "Border Effects"];
-
El.div ~at:[classes_attr (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)));
-
])] [
+
div ~styles:[
+
grid;
+
grid_cols 1;
+
gap (rem 1.0);
+
] [
(* Regular border *)
-
El.div ~at:[classes_attr (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 [
-
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 [
-
Typography.(to_class (font_size `Sm));
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
])] [El.txt "border border-gray-200"];
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.5);
+
border;
+
border_color (gray 200);
+
rounded `Lg;
+
text_center;
+
margin_bottom (rem 1.0);
+
] [
+
h3 ~styles:[
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 0.5);
+
] [txt "Regular Border"];
+
p ~styles:[
+
font_size `Sm;
+
text_color (gray 600);
+
] [txt "border border-gray-200"];
];
(* Colored border *)
-
El.div ~at:[classes_attr (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 [
-
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 [
-
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 [
-
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 [
-
Typography.(to_class (font_size `Sm));
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
])] [El.txt "border-2 border-purple-300"];
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.5);
+
border;
+
border_color (blue 300);
+
rounded `Lg;
+
text_center;
+
] [
+
h3 ~styles:[
+
font_weight `Semibold;
+
text_color (blue 600);
+
margin_bottom (rem 0.5);
+
] [txt "Colored Border"];
+
p ~styles:[
+
font_size `Sm;
+
text_color (gray 600);
+
] [txt "border border-blue-300"];
];
];
];
];
];
] in
-
html_doc
+
html
let () =
-
(* Output HTML to stdout *)
-
let html_doc = create_effects_demo () in
-
let html_string = El.to_string ~doctype:true html_doc in
-
print_string html_string
+
let html = create_effects_demo () in
+
print_string (El.to_string ~doctype:true html)
+81 -109
examples/hello_tailwind_01.ml
···
(* Example 01: Hello Tailwind - Your First Tailwind OCaml Program *)
open Htmlit
-
open Tailwind
-
-
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
+
open Tailwind_html
let create_page () =
-
let hello_classes = 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 [
-
Layout.(to_class (min_height Size.screen));
-
Color.bg (Color.make `Gray ~variant:`V50 ());
-
Display.flex;
-
Flexbox.(to_class (align_items `Center));
-
Flexbox.(to_class (justify `Center));
-
Spacing.(to_class (p (Size.rem 2.0)));
-
] in
-
-
let container_classes = tw [
-
Layout.(to_class (max_width (Size.rem 42.0))); (* max-w-2xl is ~42rem *)
-
Spacing.(to_class (mx `Auto));
-
Typography.(to_class (text_align `Center));
-
] in
-
-
let paragraph_classes = tw [
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
Spacing.(to_class (mb (Size.rem 1.5)));
-
] in
-
-
let card_classes = tw [
-
Color.bg Color.white;
-
Effects.rounded_lg;
-
Effects.shadow_sm;
-
Spacing.(to_class (p (Size.rem 1.5)));
-
Typography.(to_class (text_align `Left));
-
] in
-
-
let subheading_classes = 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 [
-
Color.bg (Color.make `Gray ~variant:`V100 ());
-
Spacing.(to_class (p (Size.rem 0.75)));
-
Effects.rounded_sm;
-
Typography.(to_class (font_size `Sm));
-
Layout.(to_class (overflow `X `Auto));
-
] in
-
-
let code_classes = tw [
-
Color.text (Color.make `Blue ~variant:`V600 ());
-
] in
-
-
let section_classes = tw [
-
Spacing.(to_class (mt (Size.rem 2.0)));
-
Spacing.(to_class (gap `Y (Size.rem 1.0)));
-
] in
-
-
let list_classes = 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 [
-
Display.flex;
-
Flexbox.(to_class (align_items `Start));
-
] in
-
-
let checkmark_classes = tw [
-
Color.text (Color.make `Green ~variant:`V500 ());
-
Spacing.(to_class (mr (Size.rem 0.5)));
-
] in
let html = El.html [
El.head [
El.meta ~at:[At.charset "utf-8"] ();
El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] ();
-
El.title [El.txt "Hello Tailwind"];
+
El.title [txt "Hello Tailwind"];
El.link ~at:[At.rel "stylesheet"; At.href "hello_tailwind_01.css"] ();
];
-
El.body ~at:[classes_attr body_classes] [
-
El.div ~at:[classes_attr container_classes] [
-
El.h1 ~at:[classes_attr hello_classes] [
-
El.txt "Hello, Tailwind OCaml!"
+
El.body ~at:[classes_attr [
+
min_height screen;
+
bg_color (gray 50);
+
flex;
+
items_center;
+
justify_center;
+
padding (rem 2.0);
+
]] [
+
container [
+
h1 ~styles:[
+
font_size `Xl2;
+
font_weight `Bold;
+
text_color (blue 600);
+
margin_bottom (rem 1.0);
+
] [
+
txt "Hello, Tailwind OCaml!"
];
-
El.p ~at:[classes_attr paragraph_classes] [
-
El.txt "This is your first Tailwind OCaml program. ";
-
El.txt "The heading above uses type-safe Tailwind classes."
+
p ~styles:[
+
text_color (gray 600);
+
margin_bottom (rem 1.5);
+
] [
+
txt "This is your first Tailwind OCaml program. ";
+
txt "The heading above uses type-safe Tailwind classes."
];
-
El.div ~at:[classes_attr card_classes] [
-
El.h2 ~at:[classes_attr subheading_classes] [
-
El.txt "Generated Classes:"
+
card [
+
h2 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 800);
+
margin_bottom (rem 0.75);
+
] [
+
txt "Generated Classes:"
];
-
El.pre ~at:[classes_attr code_block_classes] [
-
El.code ~at:[classes_attr code_classes] [
-
El.txt (to_string hello_classes)
+
El.pre ~at:[classes_attr [
+
bg_color (gray 100);
+
padding (rem 0.75);
+
rounded `Sm;
+
font_size `Sm;
+
]] [
+
El.code ~at:[classes_attr [
+
text_color (blue 600);
+
]] [
+
txt "text-blue-600 text-2xl font-bold mb-4"
];
];
];
-
El.div ~at:[classes_attr section_classes] [
-
El.h3 ~at:[classes_attr subheading_classes] [
-
El.txt "What you're learning:"
+
div ~styles:[
+
margin_top (rem 2.0);
+
] [
+
h2 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [
+
txt "What you're learning:"
];
-
El.ul ~at:[classes_attr list_classes] [
-
El.li ~at:[classes_attr list_item_classes] [
-
El.span ~at:[classes_attr checkmark_classes] [El.txt "โœ“"];
-
El.txt "Using the `tw` function to compose Tailwind classes"
+
ul ~styles:[
+
text_left;
+
text_color (gray 600);
+
] [
+
li ~styles:[flex; items_start] [
+
span ~styles:[
+
text_color (green 500);
+
margin_right (rem 0.5);
+
] [txt "โœ“"];
+
txt "Using succinct combinator functions"
];
-
El.li ~at:[classes_attr list_item_classes] [
-
El.span ~at:[classes_attr checkmark_classes] [El.txt "โœ“"];
-
El.txt "Type-safe color creation with variants"
+
li ~styles:[flex; items_start] [
+
span ~styles:[
+
text_color (green 500);
+
margin_right (rem 0.5);
+
] [txt "โœ“"];
+
txt "Type-safe color creation with simple functions"
];
-
El.li ~at:[classes_attr list_item_classes] [
-
El.span ~at:[classes_attr checkmark_classes] [El.txt "โœ“"];
-
El.txt "Typography utilities for font size and weight"
+
li ~styles:[flex; items_start] [
+
span ~styles:[
+
text_color (green 500);
+
margin_right (rem 0.5);
+
] [txt "โœ“"];
+
txt "Enhanced element functions with styling parameters"
];
-
El.li ~at:[classes_attr list_item_classes] [
-
El.span ~at:[classes_attr checkmark_classes] [El.txt "โœ“"];
-
El.txt "Converting Tailwind classes to HTML attributes"
+
li ~styles:[flex; items_start] [
+
span ~styles:[
+
text_color (green 500);
+
margin_right (rem 0.5);
+
] [txt "โœ“"];
+
txt "Automatic class-to-attribute conversion"
];
];
];
···
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)
-77
examples/improved_api_demo.ml
···
-
open Tailwind
-
-
let () =
-
Printf.printf "=== Improved Tailwind OCaml API Demo ===\n\n";
-
-
(* 1. Using the new organizational structure *)
-
let button_classes = tw [
-
C.bg (Color.make `Blue ~variant:`V500 ());
-
C.text (Color.make `White ());
-
S.(to_class (px (Size.rem 1.0)));
-
S.(to_class (py (Size.rem 0.5)));
-
E.rounded_md;
-
E.shadow_sm;
-
E.transition `Colors;
-
] in
-
Printf.printf "Button with short aliases: %s\n" (to_string button_classes);
-
-
(* 2. Using patterns for common layouts *)
-
let centered_card = tw [
-
P.card;
-
P.flex_center;
-
] in
-
Printf.printf "Centered card: %s\n" (to_string centered_card);
-
-
(* 3. Reset utilities in their own module *)
-
let form_input = tw [
-
R.input;
-
C.border (Color.make `Gray ~variant:`V300 ());
-
E.rounded_sm;
-
S.(to_class (p (Size.rem 0.75)));
-
] in
-
Printf.printf "Form input with reset: %s\n" (to_string form_input);
-
-
(* 4. Animation utilities properly organized *)
-
let animated_button = tw [
-
C.bg (Color.make `Green ~variant:`V500 ());
-
C.text (Color.make `White ());
-
S.(to_class (px (Size.rem 1.5)));
-
S.(to_class (py (Size.rem 0.75)));
-
E.rounded_lg;
-
E.transition `All;
-
E.duration 200;
-
E.ease `In_out;
-
Variants.hover (C.bg (Color.make `Green ~variant:`V600 ()));
-
] in
-
Printf.printf "Animated button: %s\n" (to_string animated_button);
-
-
(* 5. Stack layout pattern *)
-
let vertical_stack = P.stack ~gap:(Size.rem 1.0) () in
-
Printf.printf "Vertical stack: %s\n" (to_string vertical_stack);
-
-
(* 6. Conditional classes *)
-
let responsive_classes = class_list [
-
(P.flex_center, true);
-
(R.button, false);
-
(E.shadow_lg, true);
-
] in
-
Printf.printf "Conditional classes: %s\n" (to_string responsive_classes);
-
-
(* 7. Focus ring utility *)
-
let accessible_button = tw [
-
C.bg (Color.make `Purple ~variant:`V500 ());
-
C.text (Color.make `White ());
-
S.(to_class (px (Size.rem 1.0)));
-
S.(to_class (py (Size.rem 0.5)));
-
E.rounded_md;
-
focus_ring ();
-
] in
-
Printf.printf "Accessible button: %s\n" (to_string accessible_button);
-
-
Printf.printf "\n=== API Improvements Summary ===\n";
-
Printf.printf "โœ… Animation utilities moved to Effects module\n";
-
Printf.printf "โœ… Reset utilities organized in Reset module\n";
-
Printf.printf "โœ… Layout patterns in Patterns module\n";
-
Printf.printf "โœ… Convenience aliases (C, S, E, T, F, G, P, R)\n";
-
Printf.printf "โœ… Consistent return types across modules\n";
-
Printf.printf "โœ… Comprehensive test coverage setup\n";
+174
examples/index_html_generator.ml
···
+
(* Generate index.html page linking to all examples *)
+
+
open Htmlit
+
open Tailwind_html
+
+
let examples = [
+
("hello_tailwind_01.html", "01. Hello Tailwind",
+
"Your first Tailwind OCaml program with GADT interface",
+
["Basic concepts"; "Type safety"; "GADT syntax"]);
+
+
("colors_and_typography_02.html", "02. Colors and Typography",
+
"Type-safe colors and typography with compile-time validation",
+
["Color variants"; "Typography scale"; "Grid layouts"]);
+
+
("layout_and_spacing_03.html", "03. Layout and Spacing",
+
"Master CSS Grid, flexbox layouts and spacing with GADT",
+
["CSS Grid"; "Flexbox"; "Gap utilities"; "Spacing system"]);
+
+
("responsive_design_04.html", "04. Responsive Design",
+
"Adaptive layouts using GADT interface",
+
["Mobile-first"; "CSS Grid"; "Responsive cards"]);
+
+
("effects_and_variants_05.html", "05. Effects and Variants",
+
"Visual effects with shadows, borders, and rounded corners",
+
["Shadow effects"; "Grid layouts"; "Interactive buttons"]);
+
+
("patterns_and_components_06.html", "06. Patterns and Components",
+
"Reusable component patterns with GADT",
+
["Card patterns"; "Button components"; "Form patterns"]);
+
+
("comprehensive_showcase_07.html", "07. Comprehensive Showcase",
+
"Full application demo with complete UI",
+
["Header/Footer"; "Hero section"; "Feature grids"]);
+
+
("button_demo.html", "Button Demo",
+
"Showcase of all button variants and sizes",
+
["Primary buttons"; "Secondary buttons"; "Outline buttons"]);
+
]
+
+
let create_index () =
+
let html = El.html [
+
El.head [
+
El.meta ~at:[At.charset "utf-8"] ();
+
El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] ();
+
El.title [txt "Tailwind OCaml Examples - GADT Interface"];
+
El.style [txt {|
+
body { font-family: system-ui, -apple-system, sans-serif; }
+
.example-card { transition: transform 0.2s, box-shadow 0.2s; }
+
.example-card:hover { transform: translateY(-2px); }
+
|}];
+
];
+
El.body ~at:[classes_attr [
+
min_height screen;
+
bg_color (gray 50);
+
padding (rem 2.0);
+
]] [
+
container [
+
(* Header *)
+
header ~styles:[
+
text_center;
+
margin_bottom (rem 3.0);
+
] [
+
h1 ~styles:[
+
font_size `Xl3;
+
font_weight `Bold;
+
text_color (gray 800);
+
margin_bottom (rem 1.0);
+
] [txt "๐ŸŽจ Tailwind OCaml Examples"];
+
+
p ~styles:[
+
font_size `Xl;
+
text_color (gray 600);
+
margin_bottom (rem 1.0);
+
] [txt "Type-safe CSS generation with GADT-based interface"];
+
+
p ~styles:[
+
font_size `Base;
+
text_color (gray 500);
+
] [txt "Explore examples showcasing the power of compile-time guaranteed styling"];
+
];
+
+
(* Examples Grid *)
+
div ~styles:[
+
grid;
+
grid_cols 1;
+
gap (rem 1.5);
+
] (List.map (fun (file, title, desc, features) ->
+
El.a ~at:[At.href file; At.style "text-decoration: none; color: inherit;"] [
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
rounded `Lg;
+
shadow `Md;
+
padding (rem 2.0);
+
margin_bottom (rem 1.5);
+
border;
+
border_color (gray 200);
+
transition;
+
] [
+
(* Title and description *)
+
div ~styles:[margin_bottom (rem 1.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 800);
+
margin_bottom (rem 0.5);
+
] [txt title];
+
+
p ~styles:[
+
text_color (gray 600);
+
margin_bottom (rem 1.0);
+
] [txt desc];
+
];
+
+
(* Feature tags *)
+
div ~styles:[
+
grid;
+
grid_cols 3;
+
gap_x (rem 0.5);
+
gap_y (rem 0.5);
+
] (List.map (fun feature ->
+
span ~styles:[
+
bg_color (blue 100);
+
text_color (blue 700);
+
padding_x (rem 0.75);
+
padding_y (rem 0.25);
+
rounded `Full;
+
font_size `Sm;
+
font_weight `Medium;
+
margin_right (rem 0.5);
+
margin_bottom (rem 0.5);
+
] [txt feature]
+
) features);
+
+
(* View link *)
+
div ~styles:[
+
margin_top (rem 1.0);
+
text_right;
+
] [
+
span ~styles:[
+
text_color (blue 600);
+
font_weight `Medium;
+
] [txt "View Example โ†’"];
+
];
+
];
+
]
+
) examples);
+
+
(* Footer *)
+
footer ~styles:[
+
text_center;
+
margin_top (rem 3.0);
+
padding_y (rem 2.0);
+
border;
+
border_color (gray 200);
+
] [
+
p ~styles:[
+
text_color (gray 500);
+
font_size `Sm;
+
margin_bottom (rem 0.5);
+
] [txt "Built with OCaml, Tailwind CSS, and GADT-based type safety"];
+
+
p ~styles:[
+
text_color (gray 400);
+
font_size `Xs;
+
] [txt "ยฉ 2024 Tailwind OCaml - Compile-time guaranteed styling"];
+
];
+
];
+
];
+
] in
+
html
+
+
let () =
+
let html = create_index () in
+
print_string (El.to_string ~doctype:true html)
+2 -3
examples/input.css
···
/* Tailwind CSS configuration for examples */
-
@tailwind base;
-
@tailwind components;
-
@tailwind utilities;
+
@import 'tailwindcss';
+
@source "./*.html";
+259 -211
examples/layout_and_spacing_03.ml
···
-
(* Example 03: Layout and Spacing - Mastering Box Model and Flexbox *)
+
(* Example 03: Layout and Spacing - GADT flexbox and spacing demo *)
open Htmlit
-
open Tailwind
-
-
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
+
open Tailwind_html
let create_layout_demo () =
-
(* Create comprehensive layout demonstration *)
-
let html_doc = El.html [
+
let html = El.html [
El.head [
El.meta ~at:[At.charset "utf-8"] ();
El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] ();
-
El.title [El.txt "Layout and Spacing"];
+
El.title [txt "Layout and Spacing"];
El.link ~at:[At.rel "stylesheet"; At.href "layout_and_spacing_03.css"] ();
];
-
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 [
-
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.body ~at:[classes_attr [
+
min_height screen;
+
bg_color (gray 50);
+
padding (rem 2.0);
+
]] [
+
container [
+
h1 ~styles:[
+
font_size `Xl2;
+
font_weight `Bold;
+
text_color (gray 800);
+
text_center;
+
margin_bottom (rem 2.0);
+
] [txt "Layout and Spacing Demo"];
-
El.p ~at:[classes_attr (tw [
-
Typography.(to_class (font_size `Lg));
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
]); At.class' "text-center mb-12"] [
-
El.txt "Master the box model, flexbox, and CSS grid with type-safe utilities."
-
];
+
p ~styles:[
+
font_size `Lg;
+
text_color (gray 600);
+
text_center;
+
margin_bottom (rem 3.0);
+
] [txt "Master flexbox layouts and spacing with GADT interface"];
(* Flexbox Examples *)
-
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (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 "Flexbox Layouts"];
+
section ~styles:[margin_bottom (rem 3.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 2.0);
+
] [txt "Flexbox Layouts"];
(* Centered content *)
-
El.div ~at:[At.class' "mb-8"] [
-
El.h3 ~at:[classes_attr (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"];
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.0);
+
] [txt "Centered Content"];
-
El.div ~at:[classes_attr (tw [
-
Display.flex;
-
Flexbox.(to_class (justify `Center));
-
Flexbox.(to_class (align_items `Center));
-
Color.bg (Color.make `Blue ~variant:`V100 ());
-
Layout.(to_class (height (Size.rem 8.0)));
-
Effects.rounded_lg;
-
])] [
-
El.div ~at:[classes_attr (tw [
-
Color.bg Color.white;
-
Spacing.(to_class (p (Size.rem 1.5)));
-
Effects.rounded_md;
-
Effects.shadow_sm;
-
])] [
-
El.txt "Perfectly Centered Content"
+
div ~styles:[
+
flex;
+
justify_center;
+
items_center;
+
bg_color (blue 100);
+
height (rem 8.0);
+
rounded `Lg;
+
margin_bottom (rem 1.5);
+
] [
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.5);
+
rounded `Md;
+
shadow `Sm;
+
] [
+
txt "Perfectly Centered Content"
];
];
];
(* Space between items *)
-
El.div ~at:[At.class' "mb-8"] [
-
El.h3 ~at:[classes_attr (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"];
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.0);
+
] [txt "Space Between"];
-
El.div ~at:[classes_attr (tw [
-
Display.flex;
-
Flexbox.(to_class (justify `Between));
-
Flexbox.(to_class (align_items `Center));
-
Color.bg (Color.make `Green ~variant:`V100 ());
-
Spacing.(to_class (p (Size.rem 1.5)));
-
Effects.rounded_lg;
-
])] [
-
El.div ~at:[classes_attr (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 [
-
Color.bg Color.white;
-
Spacing.(to_class (p (Size.rem 1.0)));
-
Effects.rounded_md;
-
])] [El.txt "Center"];
-
El.div ~at:[classes_attr (tw [
-
Color.bg Color.white;
-
Spacing.(to_class (p (Size.rem 1.0)));
-
Effects.rounded_md;
-
])] [El.txt "Right"];
-
];
-
];
-
-
(* Flex direction example *)
-
El.div [
-
El.h3 ~at:[classes_attr (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 [
-
Display.flex;
-
Flexbox.(to_class (direction `Col));
-
Spacing.(to_class (gap `All (Size.rem 1.0)));
-
Color.bg (Color.make `Purple ~variant:`V100 ());
-
Spacing.(to_class (p (Size.rem 1.5)));
-
Effects.rounded_lg;
-
])] [
-
El.div ~at:[classes_attr (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 [
-
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 [
-
Color.bg Color.white;
-
Spacing.(to_class (p (Size.rem 1.0)));
-
Effects.rounded_md;
-
]); At.class' "text-center"] [El.txt "Item 3"];
+
div ~styles:[
+
flex;
+
justify_between;
+
items_center;
+
bg_color (green 100);
+
padding (rem 1.5);
+
rounded `Lg;
+
] [
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.0);
+
rounded `Md;
+
] [txt "Left"];
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.0);
+
rounded `Md;
+
] [txt "Center"];
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.0);
+
rounded `Md;
+
] [txt "Right"];
];
];
];
-
(* Grid Examples *)
-
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (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 "CSS Grid Layouts"];
+
(* Grid Layout Examples *)
+
section ~styles:[margin_bottom (rem 3.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 2.0);
+
] [txt "CSS Grid Layouts"];
-
(* 2-column grid *)
-
El.div ~at:[At.class' "mb-8"] [
-
El.h3 ~at:[classes_attr (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"];
+
(* 3-column grid *)
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.0);
+
] [txt "Three Column Grid"];
-
El.div ~at:[classes_attr (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 [
-
Color.bg (Color.make `Red ~variant:`V100 ());
-
Spacing.(to_class (p (Size.rem 1.5)));
-
Effects.rounded_lg;
-
]); At.class' "text-center"] [
-
El.txt (Printf.sprintf "Grid Item %d" (i + 1))
-
]
-
));
+
div ~styles:[
+
grid;
+
grid_cols 3;
+
gap (rem 1.0);
+
] [
+
div ~styles:[
+
bg_color (blue 100);
+
padding (rem 1.0);
+
rounded `Md;
+
text_center;
+
] [txt "Item 1"];
+
div ~styles:[
+
bg_color (green 100);
+
padding (rem 1.0);
+
rounded `Md;
+
text_center;
+
] [txt "Item 2"];
+
div ~styles:[
+
bg_color (purple 100);
+
padding (rem 1.0);
+
rounded `Md;
+
text_center;
+
] [txt "Item 3"];
+
div ~styles:[
+
bg_color (red 100);
+
padding (rem 1.0);
+
rounded `Md;
+
text_center;
+
] [txt "Item 4"];
+
div ~styles:[
+
bg_color (yellow 100);
+
padding (rem 1.0);
+
rounded `Md;
+
text_center;
+
] [txt "Item 5"];
+
div ~styles:[
+
bg_color (indigo 100);
+
padding (rem 1.0);
+
rounded `Md;
+
text_center;
+
] [txt "Item 6"];
+
];
];
-
(* 3-column grid *)
-
El.div ~at:[At.class' "mb-8"] [
-
El.h3 ~at:[classes_attr (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"];
+
(* Grid gap examples *)
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.0);
+
] [txt "Grid Gap Variations"];
-
El.div ~at:[classes_attr (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 [
-
Color.bg (Color.make `Yellow ~variant:`V100 ());
-
Spacing.(to_class (p (Size.rem 1.5)));
-
Effects.rounded_lg;
-
]); At.class' "text-center"] [
-
El.txt (Printf.sprintf "Item %d" (i + 1))
-
]
-
));
+
div ~styles:[margin_bottom (rem 1.5)] [
+
h4 ~styles:[
+
font_size `Base;
+
font_weight `Medium;
+
text_color (gray 600);
+
margin_bottom (rem 0.5);
+
] [txt "Small Gap"];
+
div ~styles:[
+
grid;
+
grid_cols 4;
+
gap (rem 0.5);
+
] (List.init 4 (fun i ->
+
div ~styles:[
+
bg_color (blue 200);
+
padding (rem 0.5);
+
rounded `Sm;
+
text_center;
+
] [txt (string_of_int (i + 1))]
+
));
+
];
+
+
div ~styles:[margin_bottom (rem 1.5)] [
+
h4 ~styles:[
+
font_size `Base;
+
font_weight `Medium;
+
text_color (gray 600);
+
margin_bottom (rem 0.5);
+
] [txt "Large Gap"];
+
div ~styles:[
+
grid;
+
grid_cols 3;
+
gap (rem 2.0);
+
] (List.init 3 (fun i ->
+
div ~styles:[
+
bg_color (green 200);
+
padding (rem 1.0);
+
rounded `Md;
+
text_center;
+
] [txt (Printf.sprintf "Item %d" (i + 1))]
+
));
+
];
+
+
div [
+
h4 ~styles:[
+
font_size `Base;
+
font_weight `Medium;
+
text_color (gray 600);
+
margin_bottom (rem 0.5);
+
] [txt "Asymmetric Gap"];
+
div ~styles:[
+
grid;
+
grid_cols 2;
+
gap_x (rem 2.0);
+
gap_y (rem 0.5);
+
] (List.init 4 (fun i ->
+
div ~styles:[
+
bg_color (purple 200);
+
padding (rem 0.75);
+
rounded `Md;
+
text_center;
+
] [txt (Printf.sprintf "Box %d" (i + 1))]
+
));
+
];
];
];
(* Spacing Examples *)
-
El.section [
-
El.h2 ~at:[classes_attr (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"];
+
section [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 2.0);
+
] [txt "Spacing System"];
-
El.div ~at:[classes_attr (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)));
-
])] [
+
(* Using grid for spacing examples *)
+
div ~styles:[
+
grid;
+
grid_cols 2;
+
gap (rem 1.5);
+
] [
(* Padding example *)
-
El.div ~at:[classes_attr (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 [
-
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 [
-
Color.bg Color.white;
-
Spacing.(to_class (p (Size.rem 2.0)));
-
Effects.rounded_md;
-
Effects.border;
-
Color.border (Color.make `Gray ~variant:`V200 ());
-
])] [
-
El.txt "This content has p-8 (2rem padding)"
+
card [
+
h4 ~styles:[
+
font_size `Base;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 0.75);
+
] [txt "Padding Example"];
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 2.0);
+
rounded `Md;
+
border;
+
border_color (gray 200);
+
] [
+
txt "This content has padding (2rem)"
];
];
(* Margin example *)
-
El.div ~at:[classes_attr (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 [
-
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 [
-
Color.bg Color.white;
-
Spacing.(to_class (p (Size.rem 1.0)));
-
Spacing.(to_class (m (Size.rem 1.5)));
-
Effects.rounded_md;
-
Effects.border;
-
Color.border (Color.make `Gray ~variant:`V200 ());
-
])] [
-
El.txt "This box has m-6 (1.5rem margin) from its container"
+
card [
+
h4 ~styles:[
+
font_size `Base;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 0.75);
+
] [txt "Margin Example"];
+
div ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.0);
+
margin (rem 1.5);
+
rounded `Md;
+
border;
+
border_color (gray 200);
+
] [
+
txt "This box has margin (1.5rem) from its container"
];
];
];
···
];
];
] in
-
html_doc
+
html
let () =
-
(* Output HTML to stdout *)
-
let html_doc = create_layout_demo () in
-
print_string (El.to_string ~doctype:true html_doc)
+
let html = create_layout_demo () in
+
print_string (El.to_string ~doctype:true html)
-58
examples/module_usage.ml
···
-
(* Example showing how to use module aliases to access individual utilities *)
-
-
let () =
-
(* Using individual modules through Tailwind module aliases *)
-
let blue_bg = Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V500 ()) in
-
let white_text = Tailwind.Color.text Tailwind.Color.white in
-
let padding = Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.0))) in
-
let rounded = Tailwind.Effects.rounded_md in
-
let flex_display = Tailwind.Display.flex in
-
let center_items = Tailwind.Flexbox.(to_class (align_items `Center)) in
-
-
(* Combine all classes *)
-
let button_classes = Tailwind.tw [
-
blue_bg;
-
white_text;
-
padding;
-
rounded;
-
flex_display;
-
center_items;
-
] in
-
-
(* Typography example *)
-
let heading = Tailwind.Typography.(to_class (font_size `Xl2)) in
-
let bold_text = Tailwind.Typography.(to_class (font_weight `Bold)) in
-
let center_align = Tailwind.Typography.(to_class (text_align `Center)) in
-
-
let heading_classes = Tailwind.tw [
-
heading;
-
bold_text;
-
center_align;
-
] in
-
-
(* Layout example *)
-
let full_width = Tailwind.Layout.w_full in
-
let fixed_height = Tailwind.Layout.(to_class (height (Tailwind.Size.rem 10.0))) in
-
let overflow_hidden = Tailwind.Layout.(to_class (overflow `All `Hidden)) in
-
-
let container_classes = Tailwind.tw [
-
full_width;
-
fixed_height;
-
overflow_hidden;
-
Tailwind.Patterns.flex_center; (* Utility function *)
-
] in
-
-
Printf.printf "=== Module Alias Usage Examples ===\n";
-
Printf.printf "Button: %s\n" (Tailwind.to_string button_classes);
-
Printf.printf "Heading: %s\n" (Tailwind.to_string heading_classes);
-
Printf.printf "Container: %s\n" (Tailwind.to_string container_classes);
-
-
(* Show conditional classes *)
-
let is_primary = true in
-
let conditional_button = Tailwind.class_list [
-
(Tailwind.tw [padding; rounded], true);
-
(blue_bg, is_primary);
-
(Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V300 ()), not is_primary);
-
] in
-
-
Printf.printf "Conditional button: %s\n" (Tailwind.to_string conditional_button)
+165 -135
examples/patterns_and_components_06.ml
···
-
(* Example 06: Patterns and Components - Reusable Layout Patterns *)
+
(* Example 06: Patterns and Components - Reusable components with GADT *)
open Htmlit
-
open Tailwind
-
-
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
+
open Tailwind_html
let create_patterns_demo () =
-
(* Create comprehensive patterns demonstration *)
-
let html_doc = El.html [
+
let html = El.html [
El.head [
El.meta ~at:[At.charset "utf-8"] ();
El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] ();
-
El.title [El.txt "Patterns and Components"];
+
El.title [txt "Patterns and Components"];
El.link ~at:[At.rel "stylesheet"; At.href "patterns_and_components_06.css"] ();
];
-
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 [
-
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 "Patterns and Components Demo"];
+
El.body ~at:[classes_attr [
+
min_height screen;
+
bg_color (gray 50);
+
padding (rem 2.0);
+
]] [
+
container [
+
h1 ~styles:[
+
font_size `Xl2;
+
font_weight `Bold;
+
text_color (gray 800);
+
text_center;
+
margin_bottom (rem 2.0);
+
] [txt "Patterns and Components Demo"];
(* Container Pattern *)
-
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (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"];
+
section ~styles:[margin_bottom (rem 3.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [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 [
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
])] [El.txt "This content is inside a container pattern that centers content and provides responsive padding."];
+
card [
+
p ~styles:[text_color (gray 600)] [
+
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 [
-
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"];
+
section ~styles:[margin_bottom (rem 3.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "Card Patterns"];
-
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 [
-
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 [
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
])] [El.txt "This is a card using the built-in card pattern."];
+
div ~styles:[flex; flex_col] [
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 800);
+
margin_bottom (rem 1.0);
+
] [txt "Basic Card"];
+
p ~styles:[text_color (gray 600)] [
+
txt "A simple card with padding and shadow."
+
];
];
-
El.div ~at:[classes_attr (tw [Patterns.card]); At.class' "p-6"] [
-
El.h3 ~at:[classes_attr (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 [
-
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 [
-
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 [
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
])] [El.txt "A third card demonstrating consistent styling."];
+
card ~elevated:true [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 800);
+
margin_bottom (rem 1.0);
+
] [txt "Elevated Card"];
+
p ~styles:[text_color (gray 600)] [
+
txt "This card has a stronger shadow for emphasis."
+
];
];
];
];
-
(* Flex Center Pattern *)
-
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (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"];
+
(* Button Components *)
+
section ~styles:[margin_bottom (rem 3.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "Button Components"];
-
El.div ~at:[classes_attr (tw [Patterns.flex_center]); At.class' "bg-blue-50 rounded-lg h-32"] [
-
El.p ~at:[classes_attr (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"];
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 800);
+
margin_bottom (rem 1.5);
+
] [txt "Button Variants"];
+
+
div ~styles:[flex; flex_col] [
+
div ~styles:[margin_bottom (rem 1.0)] [
+
btn_primary ~size:`Sm [txt "Small Primary"];
+
btn_primary [txt "Default Primary"];
+
btn_primary ~size:`Lg [txt "Large Primary"];
+
];
+
+
div ~styles:[margin_bottom (rem 1.0)] [
+
btn_secondary ~size:`Sm [txt "Small Secondary"];
+
btn_secondary [txt "Default Secondary"];
+
btn_secondary ~size:`Lg [txt "Large Secondary"];
+
];
+
+
div [
+
btn_outline ~size:`Sm [txt "Small Outline"];
+
btn_outline [txt "Default Outline"];
+
btn_outline ~size:`Lg [txt "Large Outline"];
+
];
+
];
];
];
-
(* Stack Pattern *)
-
El.section ~at:[At.class' "mb-12"] [
-
El.h2 ~at:[classes_attr (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"];
+
(* List Pattern *)
+
section ~styles:[margin_bottom (rem 3.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "List Patterns"];
-
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 [
-
Color.bg (Color.make `Green ~variant:`V50 ());
-
Spacing.(to_class (p (Size.rem 1.0)));
-
Effects.rounded_md;
-
])] [El.txt "Stack Item 1"];
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 800);
+
margin_bottom (rem 1.0);
+
] [txt "Feature List"];
-
El.div ~at:[classes_attr (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 [
-
Color.bg (Color.make `Purple ~variant:`V50 ());
-
Spacing.(to_class (p (Size.rem 1.0)));
-
Effects.rounded_md;
-
])] [El.txt "Stack Item 3"];
+
ul ~styles:[text_color (gray 600)] [
+
li ~styles:[margin_bottom (rem 0.5)] [txt "โœ“ Type-safe styling"];
+
li ~styles:[margin_bottom (rem 0.5)] [txt "โœ“ Conflict prevention"];
+
li ~styles:[margin_bottom (rem 0.5)] [txt "โœ“ Succinct syntax"];
+
li [txt "โœ“ Reusable components"];
+
];
];
];
-
(* Inline Stack Pattern *)
-
El.section [
-
El.h2 ~at:[classes_attr (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"];
+
(* Form Pattern *)
+
section [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 1.5);
+
] [txt "Form Patterns"];
-
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 [
-
Color.bg (Color.make `Red ~variant:`V50 ());
-
Color.text (Color.make `Red ~variant:`V600 ());
-
Spacing.(to_class (px (Size.rem 0.75)));
-
Spacing.(to_class (py (Size.rem 0.5)));
-
Effects.rounded_full;
-
Typography.(to_class (font_size `Sm));
-
])] [El.txt "Tag 1"];
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 800);
+
margin_bottom (rem 1.5);
+
] [txt "Simple Form"];
-
El.span ~at:[classes_attr (tw [
-
Color.bg (Color.make `Yellow ~variant:`V50 ());
-
Color.text (Color.make `Yellow ~variant:`V600 ());
-
Spacing.(to_class (px (Size.rem 0.75)));
-
Spacing.(to_class (py (Size.rem 0.5)));
-
Effects.rounded_full;
-
Typography.(to_class (font_size `Sm));
-
])] [El.txt "Tag 2"];
-
-
El.span ~at:[classes_attr (tw [
-
Color.bg (Color.make `Indigo ~variant:`V50 ());
-
Color.text (Color.make `Indigo ~variant:`V600 ());
-
Spacing.(to_class (px (Size.rem 0.75)));
-
Spacing.(to_class (py (Size.rem 0.5)));
-
Effects.rounded_full;
-
Typography.(to_class (font_size `Sm));
-
])] [El.txt "Tag 3"];
+
div ~styles:[flex; flex_col] [
+
div ~styles:[margin_bottom (rem 1.5)] [
+
El.label ~at:[At.for' "name"; classes_attr [
+
block;
+
font_weight `Medium;
+
text_color (gray 700);
+
margin_bottom (rem 0.5);
+
]] [txt "Name"];
+
El.input ~at:[At.type' "text"; At.id "name"; classes_attr [
+
width full;
+
padding (rem 0.5);
+
border;
+
border_color (gray 300);
+
rounded `Md;
+
]] ();
+
];
+
+
div ~styles:[margin_bottom (rem 1.5)] [
+
El.label ~at:[At.for' "email"; classes_attr [
+
block;
+
font_weight `Medium;
+
text_color (gray 700);
+
margin_bottom (rem 0.5);
+
]] [txt "Email"];
+
El.input ~at:[At.type' "email"; At.id "email"; classes_attr [
+
width full;
+
padding (rem 0.5);
+
border;
+
border_color (gray 300);
+
rounded `Md;
+
]] ();
+
];
+
+
btn_primary [txt "Submit"];
+
];
];
];
];
];
] in
-
html_doc
+
html
let () =
-
(* Output HTML to stdout *)
-
let html_doc = create_patterns_demo () in
-
let html_string = El.to_string ~doctype:true html_doc in
-
print_string html_string
+
let html = create_patterns_demo () in
+
print_string (El.to_string ~doctype:true html)
+144 -159
examples/responsive_design_04.ml
···
-
(* Example 04: Responsive Design - Building Adaptive Layouts *)
+
(* Example 04: Responsive Design - GADT interface showcase *)
open Htmlit
-
open Tailwind
-
-
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
+
open Tailwind_html
let create_responsive_demo () =
-
(* Create comprehensive responsive demonstration *)
-
let html_doc = El.html [
+
let html = El.html [
El.head [
El.meta ~at:[At.charset "utf-8"] ();
El.meta ~at:[At.name "viewport"; At.content "width=device-width, initial-scale=1"] ();
-
El.title [El.txt "Responsive Design"];
+
El.title [txt "Responsive Design"];
El.link ~at:[At.rel "stylesheet"; At.href "responsive_design_04.css"] ();
];
-
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 [
-
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.body ~at:[classes_attr [
+
min_height screen;
+
bg_color (gray 50);
+
padding (rem 1.0);
+
]] [
+
container [
+
h1 ~styles:[
+
font_size `Xl2;
+
font_weight `Bold;
+
text_color (gray 800);
+
text_center;
+
margin_bottom (rem 2.0);
+
] [txt "Responsive Design Demo"];
-
El.p ~at:[classes_attr (tw [
-
Typography.(to_class (font_size `Lg));
-
Color.text (Color.make `Gray ~variant:`V600 ());
-
]); At.class' "text-center mb-8"] [
-
El.txt "Resize your browser window to see responsive changes. The indicator in the top-right shows the current breakpoint."
-
];
+
p ~styles:[
+
font_size `Lg;
+
text_color (gray 600);
+
text_center;
+
margin_bottom (rem 3.0);
+
] [txt "Adaptive layouts using GADT interface"];
-
(* Responsive Grid *)
-
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (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"];
+
(* Mobile-first card grid *)
+
section ~styles:[margin_bottom (rem 3.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 2.0);
+
] [txt "Responsive Card Grid"];
-
El.p ~at:[classes_attr (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)"
+
(* Using CSS Grid - starts as 1 column on mobile, would be 3 columns on larger screens *)
+
div ~styles:[
+
grid;
+
grid_cols 1; (* Mobile: 1 column, but ideally would be responsive *)
+
gap (rem 1.5);
+
] [
+
(* Card 1 *)
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (blue 600);
+
margin_bottom (rem 1.0);
+
] [txt "Card 1"];
+
p ~styles:[text_color (gray 600)] [
+
txt "This card stacks vertically on mobile and forms a grid on larger screens."
+
];
+
];
+
+
(* Card 2 *)
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (green 600);
+
margin_bottom (rem 1.0);
+
] [txt "Card 2"];
+
p ~styles:[text_color (gray 600)] [
+
txt "Responsive design ensures optimal viewing across all devices."
+
];
+
];
+
+
(* Card 3 *)
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (purple 600);
+
margin_bottom (rem 1.0);
+
] [txt "Card 3"];
+
p ~styles:[text_color (gray 600)] [
+
txt "Mobile-first approach with progressive enhancement."
+
];
+
];
];
-
-
El.div ~at:[classes_attr (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))))));
-
Responsive.(to_class (at_breakpoint `Xl (Grid.(to_class (template_cols (`Cols 4))))));
-
Spacing.(to_class (gap `All (Size.rem 1.0)));
-
])] (List.init 8 (fun i ->
-
let colors = [|
-
Color.make `Blue ~variant:`V100 ();
-
Color.make `Green ~variant:`V100 ();
-
Color.make `Purple ~variant:`V100 ();
-
Color.make `Red ~variant:`V100 ();
-
Color.make `Yellow ~variant:`V100 ();
-
|] in
-
El.div ~at:[classes_attr (tw [
-
Color.bg colors.(i mod (Array.length colors));
-
Spacing.(to_class (p (Size.rem 1.5)));
-
]); At.class' "rounded-lg text-center"] [
-
El.txt (Printf.sprintf "Item %d" (i + 1))
-
]
-
));
];
-
(* Responsive Typography *)
-
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (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"];
+
(* Responsive navigation *)
+
section ~styles:[margin_bottom (rem 3.0)] [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 2.0);
+
] [txt "Responsive Navigation"];
-
El.div ~at:[classes_attr (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 [
-
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)))));
-
Typography.(to_class (font_weight `Semibold));
-
Color.text (Color.make `Blue ~variant:`V600 ());
-
]); At.class' "mb-4"] [El.txt "Responsive Heading"];
-
-
El.p ~at:[classes_attr (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 ());
-
])] [
-
El.txt "This text scales: small on mobile, base on tablet, and larger on desktop. The heading above also scales responsively."
+
nav ~styles:[
+
bg_color (Tailwind.Color.white);
+
padding (rem 1.0);
+
rounded `Lg;
+
shadow `Md;
+
] [
+
div ~styles:[
+
flex;
+
flex_col;
+
] [
+
a ~styles:[
+
padding (rem 0.75);
+
text_color (gray 700);
+
font_weight `Medium;
+
] ~href:"#" [txt "Home"];
+
+
a ~styles:[
+
padding (rem 0.75);
+
text_color (gray 700);
+
font_weight `Medium;
+
] ~href:"#" [txt "About"];
+
+
a ~styles:[
+
padding (rem 0.75);
+
text_color (gray 700);
+
font_weight `Medium;
+
] ~href:"#" [txt "Services"];
+
+
a ~styles:[
+
padding (rem 0.75);
+
text_color (gray 700);
+
font_weight `Medium;
+
] ~href:"#" [txt "Contact"];
];
];
];
-
(* Show/Hide Elements *)
-
El.section ~at:[At.class' "mb-8"] [
-
El.h2 ~at:[classes_attr (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"];
+
(* Responsive text *)
+
section [
+
h2 ~styles:[
+
font_size `Xl;
+
font_weight `Semibold;
+
text_color (gray 700);
+
margin_bottom (rem 2.0);
+
] [txt "Responsive Typography"];
-
El.div ~at:[classes_attr (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 [
-
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"
-
];
+
card [
+
h3 ~styles:[
+
font_size `Lg;
+
font_weight `Semibold;
+
text_color (gray 800);
+
margin_bottom (rem 1.0);
+
] [txt "Adaptive Text Sizes"];
-
El.div ~at:[classes_attr (tw [
-
Color.bg (Color.make `Green ~variant:`V100 ());
-
Spacing.(to_class (p (Size.rem 1.5)));
-
Display.hidden;
-
Responsive.(to_class (at_breakpoint `Md Display.block));
-
]); At.class' "rounded-lg text-center"] [
-
El.txt "Hidden on mobile, visible on md+"
-
];
+
p ~styles:[
+
font_size `Base;
+
text_color (gray 600);
+
margin_bottom (rem 1.0);
+
] [txt "This text adapts its size based on the viewport width."];
-
El.div ~at:[classes_attr (tw [
-
Color.bg (Color.make `Purple ~variant:`V100 ());
-
Spacing.(to_class (p (Size.rem 1.5)));
-
Display.hidden;
-
Responsive.(to_class (at_breakpoint `Lg Display.block));
-
]); At.class' "rounded-lg text-center"] [
-
El.txt "Only visible on lg+"
-
];
-
];
-
];
-
-
(* Responsive Spacing *)
-
El.section [
-
El.h2 ~at:[classes_attr (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 [
-
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 [
-
Color.bg Color.white;
-
Spacing.(to_class (p (Size.rem 1.0)));
-
]); At.class' "rounded"] [
-
El.p [El.txt "This container has responsive padding:"];
-
El.ul [
-
El.li [El.txt "p-4 (1rem) on mobile"];
-
El.li [El.txt "md:p-6 (1.5rem) on tablet"];
-
El.li [El.txt "lg:p-8 (2rem) on desktop"];
-
];
-
];
+
p ~styles:[
+
font_size `Sm;
+
text_color (gray 500);
+
] [txt "Smaller supporting text that remains readable on all devices."];
];
];
];
];
] in
-
-
let html_string = El.to_string ~doctype:true html_doc in
-
let oc = open_out "04_responsive_design.html" in
-
output_string oc html_string;
-
close_out oc;
-
-
Printf.printf "\nโœ… Generated: 04_responsive_design.html (%d bytes)\n" (String.length html_string);
-
Printf.printf "\n๐ŸŽฏ What you learned:\n";
-
Printf.printf " โ€ข Mobile-first responsive design approach\n";
-
Printf.printf " โ€ข Breakpoint system: sm, md, lg, xl\n";
-
Printf.printf " โ€ข Responsive utilities with at_breakpoint function\n";
-
Printf.printf " โ€ข Show/hide elements at different screen sizes\n";
-
Printf.printf " โ€ข Responsive typography and spacing\n";
-
Printf.printf " โ€ข Grid columns that adapt to screen size\n"
+
html
-
let () = create_responsive_demo ()
+
let () =
+
let html = create_responsive_demo () in
+
print_string (El.to_string ~doctype:true html)
-95
examples/simple_html_example.ml
···
-
(* Simple HTML generation example using Tailwind classes *)
-
-
open Htmlit
-
-
let classes_attr tailwind_classes =
-
At.class' (Tailwind.to_string tailwind_classes)
-
-
let () =
-
Printf.printf "=== Simple Tailwind HTML Example ===\n";
-
-
(* Create a simple card *)
-
let card_classes = Tailwind.tw [
-
Tailwind.Effects.rounded_lg;
-
Tailwind.Effects.shadow_md;
-
Tailwind.Color.bg Tailwind.Color.white;
-
Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.5)));
-
Tailwind.Layout.(to_class (max_width (Tailwind.Size.rem 20.0)));
-
] in
-
-
let card = El.div ~at:[classes_attr card_classes] [
-
El.h2 ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Typography.(to_class (font_size `Xl));
-
Tailwind.Typography.(to_class (font_weight `Bold));
-
Tailwind.Spacing.(to_class (mb (Tailwind.Size.rem 1.0)));
-
])] [El.txt "Welcome Card"];
-
-
El.p ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V600 ());
-
Tailwind.Spacing.(to_class (mb (Tailwind.Size.rem 1.5)));
-
])] [El.txt "This is a simple card component built with Tailwind CSS classes."];
-
-
El.button ~at:[
-
classes_attr (Tailwind.tw [
-
Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V600 ());
-
Tailwind.Color.text Tailwind.Color.white;
-
Tailwind.Spacing.(to_class (px (Tailwind.Size.rem 1.0)));
-
Tailwind.Spacing.(to_class (py (Tailwind.Size.rem 0.5)));
-
Tailwind.Effects.rounded_md;
-
Tailwind.Variants.hover (Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V700 ()));
-
]);
-
] [El.txt "Click Me"];
-
] in
-
-
(* Create a simple layout *)
-
let page = El.div ~at:[classes_attr (Tailwind.tw [
-
Tailwind.Layout.(to_class (min_height (Tailwind.Size.screen)));
-
Tailwind.Color.bg (Tailwind.Color.make `Gray ~variant:`V50 ());
-
Tailwind.Display.flex;
-
Tailwind.Flexbox.(to_class (align_items `Center));
-
Tailwind.Flexbox.(to_class (justify `Center));
-
Tailwind.Spacing.(to_class (p (Tailwind.Size.rem 1.0)));
-
])] [card] in
-
-
(* Generate HTML *)
-
let html_doc = El.html [
-
El.head [
-
El.title [El.txt "Tailwind HTML Example"];
-
El.script ~at:[At.src "https://cdn.tailwindcss.com"] [];
-
];
-
El.body [page];
-
] in
-
-
let html_string = El.to_string ~doctype:true html_doc in
-
-
Printf.printf "Generated HTML document (%d characters)\n" (String.length html_string);
-
Printf.printf "HTML preview:\n%s\n" (String.sub html_string 0 (min 500 (String.length html_string)));
-
-
(* Show individual class generation *)
-
Printf.printf "\n=== Individual Class Examples ===\n";
-
Printf.printf "Primary button: %s\n" (Tailwind.to_string (Tailwind.tw [
-
Tailwind.Color.bg (Tailwind.Color.make `Blue ~variant:`V600 ());
-
Tailwind.Color.text Tailwind.Color.white;
-
Tailwind.Effects.rounded_md;
-
]));
-
-
Printf.printf "Card container: %s\n" (Tailwind.to_string (Tailwind.tw [
-
Tailwind.Effects.rounded_lg;
-
Tailwind.Effects.shadow_md;
-
Tailwind.Color.bg Tailwind.Color.white;
-
]));
-
-
Printf.printf "Flex center: %s\n" (Tailwind.to_string (Tailwind.tw [
-
Tailwind.Display.flex;
-
Tailwind.Flexbox.(to_class (align_items `Center));
-
Tailwind.Flexbox.(to_class (justify `Center));
-
]));
-
-
Printf.printf "Responsive grid: %s\n" (Tailwind.to_string (Tailwind.tw [
-
Tailwind.Display.grid;
-
Tailwind.Grid.(to_class (template_cols (`Cols 1)));
-
Tailwind.Responsive.(to_class (at_breakpoint `Md (Tailwind.Grid.(to_class (template_cols (`Cols 2))))));
-
Tailwind.Responsive.(to_class (at_breakpoint `Lg (Tailwind.Grid.(to_class (template_cols (`Cols 3))))));
-
]));
-
-
Printf.printf "\nTailwind HTML library working successfully!\n"
-18
examples/tailwind_html_example.ml
···
-
(* Tailwind HTML Components Example - Placeholder *)
-
-
let () =
-
Printf.printf "Tailwind HTML Components Example\n";
-
Printf.printf "=================================\n\n";
-
Printf.printf "This example demonstrates how HTML components will work\n";
-
Printf.printf "once the tailwind-html library is fully implemented.\n\n";
-
-
Printf.printf "The tailwind-html library will provide:\n";
-
Printf.printf " - Pre-built button components\n";
-
Printf.printf " - Card layouts\n";
-
Printf.printf " - Form components\n";
-
Printf.printf " - Navigation patterns\n";
-
Printf.printf " - Modal dialogs\n";
-
Printf.printf " - And more!\n\n";
-
-
Printf.printf "For now, you can build these components manually using\n";
-
Printf.printf "the core Tailwind library as shown in the other examples.\n"
+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
+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
}
+32 -9
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);
···
El.input ~at:(At.type' "checkbox" :: all_attrs) ()
in
-
(* Wrap in label if provided *)
-
match field.label with
+
let label_element = match field.label with
| Some label_text ->
El.label [
El.txt label_text;
input_element;
]
| None -> input_element
+
in
+
+
(* Add helper and error text if provided *)
+
let help_elements = List.filter_map (fun x -> x) [
+
Option.map (fun text ->
+
El.p ~at:[classes_attr (Tailwind.Css.tw [
+
Tailwind.Typography.(to_class (font_size `Sm));
+
Tailwind.Color.text (Tailwind.Color.make `Gray ~variant:`V600 ());
+
Tailwind.Spacing.(to_class (mt (Tailwind.Size.rem 0.25)));
+
])] [El.txt text]
+
) field.helper_text;
+
Option.map (fun text ->
+
El.p ~at:[classes_attr (Tailwind.Css.tw [
+
Tailwind.Typography.(to_class (font_size `Sm));
+
Tailwind.Color.text (Tailwind.Color.make `Red ~variant:`V600 ());
+
Tailwind.Spacing.(to_class (mt (Tailwind.Size.rem 0.25)));
+
])] [El.txt text]
+
) field.error_text;
+
] in
+
+
(* Wrap everything in a container *)
+
match help_elements with
+
| [] -> label_element
+
| _ -> El.div ([label_element] @ help_elements)
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] []
+416 -58
lib/tailwind-html/tailwind_html.ml
···
-
(* Main module for Tailwind HTML library *)
+
(* GADT-based Tailwind HTML library with heterogeneous lists *)
+
+
(* Color utilities *)
+
let blue variant = Tailwind.Color.make `Blue ~variant:(match variant with
+
| 50 -> `V50 | 100 -> `V100 | 200 -> `V200 | 300 -> `V300 | 400 -> `V400
+
| 500 -> `V500 | 600 -> `V600 | 700 -> `V700 | 800 -> `V800 | 900 -> `V900
+
| _ -> `V600) ()
+
+
let gray variant = Tailwind.Color.make `Gray ~variant:(match variant with
+
| 50 -> `V50 | 100 -> `V100 | 200 -> `V200 | 300 -> `V300 | 400 -> `V400
+
| 500 -> `V500 | 600 -> `V600 | 700 -> `V700 | 800 -> `V800 | 900 -> `V900
+
| _ -> `V600) ()
+
+
let red variant = Tailwind.Color.make `Red ~variant:(match variant with
+
| 50 -> `V50 | 100 -> `V100 | 200 -> `V200 | 300 -> `V300 | 400 -> `V400
+
| 500 -> `V500 | 600 -> `V600 | 700 -> `V700 | 800 -> `V800 | 900 -> `V900
+
| _ -> `V600) ()
+
+
let green variant = Tailwind.Color.make `Green ~variant:(match variant with
+
| 50 -> `V50 | 100 -> `V100 | 200 -> `V200 | 300 -> `V300 | 400 -> `V400
+
| 500 -> `V500 | 600 -> `V600 | 700 -> `V700 | 800 -> `V800 | 900 -> `V900
+
| _ -> `V600) ()
+
+
let yellow variant = Tailwind.Color.make `Yellow ~variant:(match variant with
+
| 50 -> `V50 | 100 -> `V100 | 200 -> `V200 | 300 -> `V300 | 400 -> `V400
+
| 500 -> `V500 | 600 -> `V600 | 700 -> `V700 | 800 -> `V800 | 900 -> `V900
+
| _ -> `V600) ()
+
+
let indigo variant = Tailwind.Color.make `Indigo ~variant:(match variant with
+
| 50 -> `V50 | 100 -> `V100 | 200 -> `V200 | 300 -> `V300 | 400 -> `V400
+
| 500 -> `V500 | 600 -> `V600 | 700 -> `V700 | 800 -> `V800 | 900 -> `V900
+
| _ -> `V600) ()
+
+
let purple variant = Tailwind.Color.make `Purple ~variant:(match variant with
+
| 50 -> `V50 | 100 -> `V100 | 200 -> `V200 | 300 -> `V300 | 400 -> `V400
+
| 500 -> `V500 | 600 -> `V600 | 700 -> `V700 | 800 -> `V800 | 900 -> `V900
+
| _ -> `V600) ()
+
+
let pink variant = Tailwind.Color.make `Pink ~variant:(match variant with
+
| 50 -> `V50 | 100 -> `V100 | 200 -> `V200 | 300 -> `V300 | 400 -> `V400
+
| 500 -> `V500 | 600 -> `V600 | 700 -> `V700 | 800 -> `V800 | 900 -> `V900
+
| _ -> `V600) ()
+
+
let rem f = Tailwind.Size.rem f
+
let px = Tailwind.Size.px
+
let zero = Tailwind.Size.zero
+
let auto = Tailwind.Size.auto
+
let full = Tailwind.Size.full
+
let screen = Tailwind.Size.screen
+
let txt s = Htmlit.El.txt s
+
+
(* GADT for Tailwind properties with types indicating their category *)
+
type _ tw_prop =
+
| Text_color : Tailwind.Color.t -> [`Text_color] tw_prop
+
| Bg_color : Tailwind.Color.t -> [`Bg_color] tw_prop
+
| Font_size : Tailwind.Typography.font_size -> [`Font_size] tw_prop
+
| Font_weight : Tailwind.Typography.font_weight -> [`Font_weight] tw_prop
+
| Margin : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_x : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_y : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_top : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_bottom : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_left : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_right : Tailwind.Size.t -> [`Margin] tw_prop
+
| Padding : Tailwind.Size.t -> [`Padding] tw_prop
+
| Padding_x : Tailwind.Size.t -> [`Padding] tw_prop
+
| Padding_y : Tailwind.Size.t -> [`Padding] tw_prop
+
| Width : Tailwind.Size.t -> [`Width] tw_prop
+
| Height : Tailwind.Size.t -> [`Height] tw_prop
+
| Max_width : Tailwind.Size.t -> [`Width] tw_prop
+
| Min_height : Tailwind.Size.t -> [`Height] tw_prop
+
| Display_flex : [`Layout] tw_prop
+
| Display_grid : [`Layout] tw_prop
+
| Display_block : [`Layout] tw_prop
+
| Display_inline : [`Layout] tw_prop
+
| Display_inline_block : [`Layout] tw_prop
+
| Grid_cols : int -> [`Grid] tw_prop
+
| Grid_rows : int -> [`Grid] tw_prop
+
| Gap : Tailwind.Size.t -> [`Grid] tw_prop
+
| Gap_x : Tailwind.Size.t -> [`Grid] tw_prop
+
| Gap_y : Tailwind.Size.t -> [`Grid] tw_prop
+
| Items_center : [`Layout] tw_prop
+
| Items_start : [`Layout] tw_prop
+
| Items_end : [`Layout] tw_prop
+
| Justify_center : [`Layout] tw_prop
+
| Justify_between : [`Layout] tw_prop
+
| Justify_start : [`Layout] tw_prop
+
| Justify_end : [`Layout] tw_prop
+
| Flex_col : [`Layout] tw_prop
+
| Flex_row : [`Layout] tw_prop
+
| Text_center : [`Layout] tw_prop
+
| Text_left : [`Layout] tw_prop
+
| Text_right : [`Layout] tw_prop
+
| Rounded : [< `Sm | `Md | `Lg | `Full ] -> [`Effects] tw_prop
+
| Shadow : [< `Sm | `Md | `Lg ] -> [`Effects] tw_prop
+
| Border : [`Effects] tw_prop
+
| Border_color : Tailwind.Color.t -> [`Effects] tw_prop
+
| Transition : [`Effects] tw_prop
+
+
(* Heterogeneous list *)
+
type tw_list = tw_list_item list
+
and tw_list_item = Any : 'a tw_prop -> tw_list_item
-
(* Re-export all submodules *)
-
module Component = Component
-
module Button = Button
-
module Card = Card
-
module Form = Form
-
module Layout = Layout
-
module Cli = Cli
+
(* Convert GADT properties to Tailwind classes *)
+
let to_tailwind_classes (props : tw_list) : Tailwind.t list =
+
let convert_prop : type a. a tw_prop -> Tailwind.t = function
+
| Text_color color -> Tailwind.Color.text color
+
| Bg_color color -> Tailwind.Color.bg color
+
| Font_size size -> Tailwind.Typography.(to_class (font_size size))
+
| Font_weight weight -> Tailwind.Typography.(to_class (font_weight weight))
+
| Margin size -> Tailwind.Spacing.(to_class (m size))
+
| Margin_x size -> Tailwind.Spacing.(to_class (mx size))
+
| Margin_y size -> Tailwind.Spacing.(to_class (my size))
+
| Margin_top size -> Tailwind.Spacing.(to_class (mt size))
+
| Margin_bottom size -> Tailwind.Spacing.(to_class (mb size))
+
| Margin_left size -> Tailwind.Spacing.(to_class (ml size))
+
| Margin_right size -> Tailwind.Spacing.(to_class (mr size))
+
| Padding size -> Tailwind.Spacing.(to_class (p size))
+
| Padding_x size -> Tailwind.Spacing.(to_class (px size))
+
| Padding_y size -> Tailwind.Spacing.(to_class (py size))
+
| Width size -> Tailwind.Layout.(to_class (width size))
+
| Height size -> Tailwind.Layout.(to_class (height size))
+
| Max_width size -> Tailwind.Layout.(to_class (max_width size))
+
| Min_height size -> Tailwind.Layout.(to_class (min_height size))
+
| Display_flex -> Tailwind.Display.flex
+
| Display_grid -> Tailwind.Display.grid
+
| Display_block -> Tailwind.Display.block
+
| Display_inline -> Tailwind.Display.inline
+
| Display_inline_block -> Tailwind.Display.inline_block
+
| Grid_cols n -> Tailwind.Grid.(to_class (template_cols (`Cols n)))
+
| Grid_rows n -> Tailwind.Grid.(to_class (template_rows (`Rows n)))
+
| Gap size -> Tailwind.Spacing.(to_class (gap `All size))
+
| Gap_x size -> Tailwind.Spacing.(to_class (gap `X size))
+
| Gap_y size -> Tailwind.Spacing.(to_class (gap `Y size))
+
| Items_center -> Tailwind.Flexbox.(to_class (align_items `Center))
+
| Items_start -> Tailwind.Flexbox.(to_class (align_items `Start))
+
| Items_end -> Tailwind.Flexbox.(to_class (align_items `End))
+
| Justify_center -> Tailwind.Flexbox.(to_class (justify `Center))
+
| Justify_between -> Tailwind.Flexbox.(to_class (justify `Between))
+
| Justify_start -> Tailwind.Flexbox.(to_class (justify `Start))
+
| Justify_end -> Tailwind.Flexbox.(to_class (justify `End))
+
| Flex_col -> Tailwind.Flexbox.(to_class (direction `Col))
+
| Flex_row -> Tailwind.Flexbox.(to_class (direction `Row))
+
| Text_center -> Tailwind.Typography.(to_class (text_align `Center))
+
| Text_left -> Tailwind.Typography.(to_class (text_align `Left))
+
| Text_right -> Tailwind.Typography.(to_class (text_align `Right))
+
| Rounded radius ->
+
(match radius with
+
| `Sm -> Tailwind.Effects.rounded_sm
+
| `Md -> Tailwind.Effects.rounded_md
+
| `Lg -> Tailwind.Effects.rounded_lg
+
| `Full -> Tailwind.Effects.rounded_full)
+
| Shadow size ->
+
(match size with
+
| `Sm -> Tailwind.Effects.shadow_sm
+
| `Md -> Tailwind.Effects.shadow_md
+
| `Lg -> Tailwind.Effects.shadow_lg)
+
| Border -> Tailwind.Effects.border
+
| Border_color color -> Tailwind.Color.border color
+
| Transition -> Tailwind.Effects.transition `All
+
in
+
List.map (fun (Any prop) -> convert_prop prop) props
-
(* Common utility for converting Tailwind classes to HTML class attribute *)
-
let classes_attr tailwind_classes =
-
Htmlit.At.class' (Tailwind.to_string tailwind_classes)
+
(* Convert heterogeneous list to Tailwind.t *)
+
let styles props =
+
Tailwind.Css.tw (to_tailwind_classes props)
-
(* Apply Tailwind classes to an existing HTML element by wrapping it *)
-
let with_classes classes element =
-
let open Htmlit in
-
El.span ~at:[classes_attr classes] [element]
+
(* Helper for HTML class attribute *)
+
let classes_attr props =
+
Htmlit.At.class' (Tailwind.to_string (styles props))
-
(* Conditionally apply Tailwind classes *)
-
let with_classes_if condition classes element =
-
if condition then with_classes classes element else element
+
(* Helper constructors for convenient usage *)
+
let text_color c = Any (Text_color c)
+
let bg_color c = Any (Bg_color c)
+
let font_size s = Any (Font_size s)
+
let font_weight w = Any (Font_weight w)
+
let margin s = Any (Margin s)
+
let margin_x s = Any (Margin_x s)
+
let margin_y s = Any (Margin_y s)
+
let margin_top s = Any (Margin_top s)
+
let margin_bottom s = Any (Margin_bottom s)
+
let margin_left s = Any (Margin_left s)
+
let margin_right s = Any (Margin_right s)
+
let padding s = Any (Padding s)
+
let padding_x s = Any (Padding_x s)
+
let padding_y s = Any (Padding_y s)
+
let width s = Any (Width s)
+
let height s = Any (Height s)
+
let max_width s = Any (Max_width s)
+
let min_height s = Any (Min_height s)
+
let flex = Any Display_flex
+
let grid = Any Display_grid
+
let block = Any Display_block
+
let inline = Any Display_inline
+
let inline_block = Any Display_inline_block
+
let grid_cols n = Any (Grid_cols n)
+
let grid_rows n = Any (Grid_rows n)
+
let gap s = Any (Gap s)
+
let gap_x s = Any (Gap_x s)
+
let gap_y s = Any (Gap_y s)
+
let items_center = Any Items_center
+
let items_start = Any Items_start
+
let items_end = Any Items_end
+
let justify_center = Any Justify_center
+
let justify_between = Any Justify_between
+
let justify_start = Any Justify_start
+
let justify_end = Any Justify_end
+
let flex_col = Any Flex_col
+
let flex_row = Any Flex_row
+
let text_center = Any Text_center
+
let text_left = Any Text_left
+
let text_right = Any Text_right
+
let rounded r = Any (Rounded r)
+
let shadow s = Any (Shadow s)
+
let border = Any Border
+
let border_color c = Any (Border_color c)
+
let transition = Any Transition
-
(* Create an element with Tailwind classes and optional attributes *)
-
let el tag ?classes ?attributes children =
-
let open Htmlit in
-
let base_attrs = match classes with
-
| Some c -> [classes_attr c]
+
(* GADT-based element functions *)
+
let h1 ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
| None -> []
in
-
let custom_attrs = match attributes with
-
| Some attrs -> List.map (fun (k, v) -> At.v k v) attrs
+
Htmlit.El.h1 ~at:attrs children
+
+
let h2 ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.h2 ~at:attrs children
+
+
let h3 ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.h3 ~at:attrs children
+
+
let h4 ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.h4 ~at:attrs children
+
+
let h5 ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.h5 ~at:attrs children
+
+
let h6 ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.h6 ~at:attrs children
+
+
let p ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.p ~at:attrs children
+
+
let div ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.div ~at:attrs children
+
+
let span ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.span ~at:attrs children
+
+
let button ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.button ~at:attrs children
+
+
let a ?styles ~href children =
+
let attrs = [Htmlit.At.href href] @ (match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
) in
+
Htmlit.El.a ~at:attrs children
+
+
let img ?styles ~src ~alt () =
+
let attrs = [Htmlit.At.src src; Htmlit.At.alt alt] @ (match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
) in
+
Htmlit.El.img ~at:attrs ()
+
+
let ul ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.ul ~at:attrs children
+
+
let ol ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.ol ~at:attrs children
+
+
let li ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.li ~at:attrs children
+
+
let section ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.section ~at:attrs children
+
+
let article ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.article ~at:attrs children
+
+
let nav ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
| None -> []
in
-
let all_attrs = base_attrs @ custom_attrs in
-
El.v tag ~at:all_attrs children
+
Htmlit.El.nav ~at:attrs children
-
(* Common HTML elements with Tailwind class support *)
-
let div ?classes ?attributes children = el "div" ?classes ?attributes children
-
let span ?classes ?attributes children = el "span" ?classes ?attributes children
-
let p ?classes ?attributes children = el "p" ?classes ?attributes children
-
let a ?classes ?attributes ~href children =
-
let attrs = match attributes with Some a -> a | None -> [] in
-
el "a" ?classes ~attributes:(("href", href) :: attrs) children
-
let img ?classes ?attributes ~src ~alt () =
-
let attrs = match attributes with Some a -> a | None -> [] in
-
el "img" ?classes ~attributes:(("src", src) :: ("alt", alt) :: attrs) []
-
let h1 ?classes ?attributes children = el "h1" ?classes ?attributes children
-
let h2 ?classes ?attributes children = el "h2" ?classes ?attributes children
-
let h3 ?classes ?attributes children = el "h3" ?classes ?attributes children
-
let h4 ?classes ?attributes children = el "h4" ?classes ?attributes children
-
let h5 ?classes ?attributes children = el "h5" ?classes ?attributes children
-
let h6 ?classes ?attributes children = el "h6" ?classes ?attributes children
-
let ul ?classes ?attributes children = el "ul" ?classes ?attributes children
-
let ol ?classes ?attributes children = el "ol" ?classes ?attributes children
-
let li ?classes ?attributes children = el "li" ?classes ?attributes children
+
let header ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.header ~at:attrs children
+
+
let footer ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
+
in
+
Htmlit.El.footer ~at:attrs children
-
(* Text element with built-in typography utilities *)
-
let text ?size ?weight ?color ?align ?classes text_content =
-
let base_styles = [] in
-
let size_styles = match size with Some s -> [Tailwind.Typography.(to_class (font_size s))] | None -> [] in
-
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 final_classes = match classes with
-
| Some c -> Tailwind.tw [text_classes; c]
-
| None -> text_classes
+
let main ?styles children =
+
let attrs = match styles with
+
| Some s -> [classes_attr s]
+
| None -> []
in
-
span ~classes:final_classes [Htmlit.El.txt text_content]
+
Htmlit.El.main ~at:attrs children
+
+
(* Pre-built component helpers *)
+
let container children =
+
div ~styles:[
+
max_width (Tailwind.Size.rem 80.0);
+
margin_x auto;
+
padding_x (rem 1.0);
+
] children
+
+
let flex_center children =
+
div ~styles:[flex; items_center; justify_center] children
+
+
let card ?elevated children =
+
let shadow_style = if elevated = Some true then [shadow `Lg] else [shadow `Md] in
+
div ~styles:([
+
bg_color (Tailwind.Color.white);
+
rounded `Lg;
+
padding (rem 1.5);
+
] @ shadow_style) children
+
+
let btn_primary ?size children =
+
let size_styles = match size with
+
| Some `Sm -> [padding_x (rem 0.75); padding_y (rem 0.375); font_size `Sm]
+
| Some `Lg -> [padding_x (rem 2.0); padding_y (rem 0.75); font_size `Base]
+
| _ -> [padding_x (rem 1.0); padding_y (rem 0.5); font_size `Sm]
+
in
+
button ~styles:([
+
bg_color (blue 600);
+
text_color (Tailwind.Color.white);
+
font_weight `Medium;
+
rounded `Md;
+
transition;
+
] @ size_styles) children
+
+
let btn_secondary ?size children =
+
let size_styles = match size with
+
| Some `Sm -> [padding_x (rem 0.75); padding_y (rem 0.375); font_size `Sm]
+
| Some `Lg -> [padding_x (rem 2.0); padding_y (rem 0.75); font_size `Base]
+
| _ -> [padding_x (rem 1.0); padding_y (rem 0.5); font_size `Sm]
+
in
+
button ~styles:([
+
bg_color (gray 200);
+
text_color (gray 900);
+
font_weight `Medium;
+
rounded `Md;
+
transition;
+
] @ size_styles) children
+
+
let btn_outline ?size children =
+
let size_styles = match size with
+
| Some `Sm -> [padding_x (rem 0.75); padding_y (rem 0.375); font_size `Sm]
+
| Some `Lg -> [padding_x (rem 2.0); padding_y (rem 0.75); font_size `Base]
+
| _ -> [padding_x (rem 1.0); padding_y (rem 0.5); font_size `Sm]
+
in
+
button ~styles:([
+
bg_color (Tailwind.Color.transparent);
+
text_color (gray 700);
+
font_weight `Medium;
+
rounded `Md;
+
border;
+
border_color (gray 300);
+
transition;
+
] @ size_styles) children
+151 -45
lib/tailwind-html/tailwind_html.mli
···
-
(** Main Tailwind-HTML integration module *)
+
(** GADT-based Tailwind HTML library with heterogeneous lists *)
-
(** Re-exported submodules *)
-
module Button : module type of Button
-
module Card : module type of Card
-
module Component : module type of Component
-
module Form : module type of Form
-
module Layout : module type of Layout
-
module Cli : module type of Cli
+
(** Color utilities *)
+
val blue : int -> Tailwind.Color.t
+
val gray : int -> Tailwind.Color.t
+
val red : int -> Tailwind.Color.t
+
val green : int -> Tailwind.Color.t
+
val yellow : int -> Tailwind.Color.t
+
val indigo : int -> Tailwind.Color.t
+
val purple : int -> Tailwind.Color.t
+
val pink : int -> Tailwind.Color.t
-
(** Convert Tailwind classes to HTML class attribute *)
-
val classes_attr : Tailwind.t -> Htmlit.At.t
+
(** Size utilities *)
+
val rem : float -> Tailwind.Size.t
+
val px : Tailwind.Size.t
+
val zero : Tailwind.Size.t
+
val auto : Tailwind.Size.t
+
val full : Tailwind.Size.t
+
val screen : Tailwind.Size.t
-
(** Apply Tailwind classes to an Htmlit element *)
-
val with_classes : Tailwind.t -> Htmlit.El.html -> Htmlit.El.html
+
(** Text utility *)
+
val txt : string -> Htmlit.El.html
-
(** Apply Tailwind classes conditionally *)
-
val with_classes_if : bool -> Tailwind.t -> Htmlit.El.html -> Htmlit.El.html
+
(** GADT for Tailwind properties with category types *)
+
type _ tw_prop =
+
| Text_color : Tailwind.Color.t -> [`Text_color] tw_prop
+
| Bg_color : Tailwind.Color.t -> [`Bg_color] tw_prop
+
| Font_size : Tailwind.Typography.font_size -> [`Font_size] tw_prop
+
| Font_weight : Tailwind.Typography.font_weight -> [`Font_weight] tw_prop
+
| Margin : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_x : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_y : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_top : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_bottom : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_left : Tailwind.Size.t -> [`Margin] tw_prop
+
| Margin_right : Tailwind.Size.t -> [`Margin] tw_prop
+
| Padding : Tailwind.Size.t -> [`Padding] tw_prop
+
| Padding_x : Tailwind.Size.t -> [`Padding] tw_prop
+
| Padding_y : Tailwind.Size.t -> [`Padding] tw_prop
+
| Width : Tailwind.Size.t -> [`Width] tw_prop
+
| Height : Tailwind.Size.t -> [`Height] tw_prop
+
| Max_width : Tailwind.Size.t -> [`Width] tw_prop
+
| Min_height : Tailwind.Size.t -> [`Height] tw_prop
+
| Display_flex : [`Layout] tw_prop
+
| Display_grid : [`Layout] tw_prop
+
| Display_block : [`Layout] tw_prop
+
| Display_inline : [`Layout] tw_prop
+
| Display_inline_block : [`Layout] tw_prop
+
| Grid_cols : int -> [`Grid] tw_prop
+
| Grid_rows : int -> [`Grid] tw_prop
+
| Gap : Tailwind.Size.t -> [`Grid] tw_prop
+
| Gap_x : Tailwind.Size.t -> [`Grid] tw_prop
+
| Gap_y : Tailwind.Size.t -> [`Grid] tw_prop
+
| Items_center : [`Layout] tw_prop
+
| Items_start : [`Layout] tw_prop
+
| Items_end : [`Layout] tw_prop
+
| Justify_center : [`Layout] tw_prop
+
| Justify_between : [`Layout] tw_prop
+
| Justify_start : [`Layout] tw_prop
+
| Justify_end : [`Layout] tw_prop
+
| Flex_col : [`Layout] tw_prop
+
| Flex_row : [`Layout] tw_prop
+
| Text_center : [`Layout] tw_prop
+
| Text_left : [`Layout] tw_prop
+
| Text_right : [`Layout] tw_prop
+
| Rounded : [< `Sm | `Md | `Lg | `Full ] -> [`Effects] tw_prop
+
| Shadow : [< `Sm | `Md | `Lg ] -> [`Effects] tw_prop
+
| Border : [`Effects] tw_prop
+
| Border_color : Tailwind.Color.t -> [`Effects] tw_prop
+
| Transition : [`Effects] tw_prop
-
(** Create an element with Tailwind classes *)
-
val el :
-
string -> (* tag name *)
-
?classes:Tailwind.t ->
-
?attributes:(string * string) list ->
-
Htmlit.El.html list -> (* children *)
-
Htmlit.El.html
+
(** Heterogeneous list *)
+
type tw_list = tw_list_item list
+
and tw_list_item = Any : 'a tw_prop -> tw_list_item
-
(** Common HTML elements with Tailwind support *)
-
val div : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val span : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val p : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val a : ?classes:Tailwind.t -> ?attributes:(string * string) list -> href:string -> Htmlit.El.html list -> Htmlit.El.html
-
val img : ?classes:Tailwind.t -> ?attributes:(string * string) list -> src:string -> alt:string -> unit -> Htmlit.El.html
-
val h1 : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val h2 : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val h3 : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val h4 : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val h5 : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val h6 : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val ul : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val ol : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
-
val li : ?classes:Tailwind.t -> ?attributes:(string * string) list -> Htmlit.El.html list -> Htmlit.El.html
+
(** Convert heterogeneous list to Tailwind classes *)
+
val styles : tw_list -> Tailwind.t
+
+
(** Helper for HTML class attribute *)
+
val classes_attr : tw_list -> Htmlit.At.t
-
(** Text element with typography utilities *)
-
val text :
-
?size:Tailwind.Typography.font_size ->
-
?weight:Tailwind.Typography.font_weight ->
-
?color:Tailwind.Color.t ->
-
?align:Tailwind.Typography.text_align ->
-
?classes:Tailwind.t ->
-
string -> (* text content *)
-
Htmlit.El.html
+
(** Helper constructors for convenient usage *)
+
val text_color : Tailwind.Color.t -> tw_list_item
+
val bg_color : Tailwind.Color.t -> tw_list_item
+
val font_size : Tailwind.Typography.font_size -> tw_list_item
+
val font_weight : Tailwind.Typography.font_weight -> tw_list_item
+
val margin : Tailwind.Size.t -> tw_list_item
+
val margin_x : Tailwind.Size.t -> tw_list_item
+
val margin_y : Tailwind.Size.t -> tw_list_item
+
val margin_top : Tailwind.Size.t -> tw_list_item
+
val margin_bottom : Tailwind.Size.t -> tw_list_item
+
val margin_left : Tailwind.Size.t -> tw_list_item
+
val margin_right : Tailwind.Size.t -> tw_list_item
+
val padding : Tailwind.Size.t -> tw_list_item
+
val padding_x : Tailwind.Size.t -> tw_list_item
+
val padding_y : Tailwind.Size.t -> tw_list_item
+
val width : Tailwind.Size.t -> tw_list_item
+
val height : Tailwind.Size.t -> tw_list_item
+
val max_width : Tailwind.Size.t -> tw_list_item
+
val min_height : Tailwind.Size.t -> tw_list_item
+
val flex : tw_list_item
+
val grid : tw_list_item
+
val block : tw_list_item
+
val inline : tw_list_item
+
val inline_block : tw_list_item
+
val grid_cols : int -> tw_list_item
+
val grid_rows : int -> tw_list_item
+
val gap : Tailwind.Size.t -> tw_list_item
+
val gap_x : Tailwind.Size.t -> tw_list_item
+
val gap_y : Tailwind.Size.t -> tw_list_item
+
val items_center : tw_list_item
+
val items_start : tw_list_item
+
val items_end : tw_list_item
+
val justify_center : tw_list_item
+
val justify_between : tw_list_item
+
val justify_start : tw_list_item
+
val justify_end : tw_list_item
+
val flex_col : tw_list_item
+
val flex_row : tw_list_item
+
val text_center : tw_list_item
+
val text_left : tw_list_item
+
val text_right : tw_list_item
+
val rounded : [< `Sm | `Md | `Lg | `Full ] -> tw_list_item
+
val shadow : [< `Sm | `Md | `Lg ] -> tw_list_item
+
val border : tw_list_item
+
val border_color : Tailwind.Color.t -> tw_list_item
+
val transition : tw_list_item
+
+
(** HTML element functions with GADT styling *)
+
val h1 : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val h2 : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val h3 : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val h4 : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val h5 : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val h6 : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val p : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val div : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val span : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val button : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val a : ?styles:tw_list -> href:string -> Htmlit.El.html list -> Htmlit.El.html
+
val img : ?styles:tw_list -> src:string -> alt:string -> unit -> Htmlit.El.html
+
val ul : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val ol : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val li : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val section : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val article : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val nav : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val header : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val footer : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
val main : ?styles:tw_list -> Htmlit.El.html list -> Htmlit.El.html
+
+
(** Pre-built component helpers *)
+
val container : Htmlit.El.html list -> Htmlit.El.html
+
val flex_center : Htmlit.El.html list -> Htmlit.El.html
+
val card : ?elevated:bool -> Htmlit.El.html list -> Htmlit.El.html
+
val btn_primary : ?size:[`Sm | `Md | `Lg] -> Htmlit.El.html list -> Htmlit.El.html
+
val btn_secondary : ?size:[`Sm | `Md | `Lg] -> Htmlit.El.html list -> Htmlit.El.html
+
val btn_outline : ?size:[`Sm | `Md | `Lg] -> Htmlit.El.html list -> Htmlit.El.html
+6 -9
tailwind-html.opam
···
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "Tailwind CSS integration with Htmlit"
-
description: "High-level component library using Tailwind CSS with Htmlit"
-
maintainer: ["Your Name"]
-
authors: ["Your Name"]
-
license: "MIT"
-
homepage: "https://github.com/yourusername/tailwind-ocaml"
-
doc: "https://yourusername.github.io/tailwind-ocaml/"
-
bug-reports: "https://github.com/yourusername/tailwind-ocaml/issues"
+
description: "Html combinators for Tailwind CSS"
+
maintainer: ["Anil Madhavapeddy"]
+
authors: ["Anil Madhavapeddy"]
+
license: "ISC"
depends: [
+
"dune" {>= "3.18"}
"ocaml"
-
"dune" {>= "3.0" & >= "3.0"}
"tailwind"
"htmlit" {>= "0.1.0"}
"alcotest" {with-test}
···
"@doc" {with-doc}
]
]
-
dev-repo: "git+https://github.com/yourusername/tailwind-ocaml.git"
+
x-maintenance-intent: ["(latest)"]
-1422
tailwind-llms.txt
···
-
# Tailwind CSS v4 LLM Development Guidelines
-
-
You are an expert web developer specializing in Tailwind CSS v4. Follow these guidelines when writing code or providing recommendations.
-
-
## Core Principles
-
-
Tailwind CSS v4 is a complete rewrite with a new high-performance Oxide engine, CSS-first configuration, and modern web platform features. It requires modern browsers (Safari 16.4+, Chrome 111+, Firefox 128+) and is NOT compatible with older browsers.
-
-
## Installation & Setup
-
-
### Basic Setup
-
```css
-
/* styles.css */
-
@import "tailwindcss";
-
```
-
-
### With Vite
-
```js
-
// vite.config.js
-
import { defineConfig } from 'vite'
-
import tailwindcss from '@tailwindcss/vite'
-
-
export default defineConfig({
-
plugins: [tailwindcss()]
-
})
-
```
-
-
### Package Installation
-
```bash
-
npm install tailwindcss@next @tailwindcss/vite@next
-
```
-
-
## Configuration (CSS-First)
-
-
**IMPORTANT**: v4 uses CSS-first configuration, NOT JavaScript config files. Use the `@theme` directive in your CSS file:
-
-
```css
-
@import "tailwindcss";
-
-
@theme {
-
/* Colors (use OKLCH for wider gamut) */
-
--color-brand-50: oklch(0.98 0.01 142.12);
-
--color-brand-500: oklch(0.64 0.15 142.12);
-
--color-brand-900: oklch(0.25 0.08 142.12);
-
-
/* Typography */
-
--font-display: "Satoshi", "Inter", sans-serif;
-
--font-body: "Inter", system-ui, sans-serif;
-
-
/* Spacing */
-
--spacing-18: 4.5rem;
-
--spacing-72: 18rem;
-
-
/* Breakpoints */
-
--breakpoint-3xl: 1920px;
-
--breakpoint-4xl: 2560px;
-
-
/* Shadows */
-
--shadow-brutal: 8px 8px 0px 0px #000;
-
-
/* Animation */
-
--animate-wiggle: wiggle 1s ease-in-out infinite;
-
}
-
-
/* Define keyframes for animations */
-
@keyframes wiggle {
-
0%, 100% { transform: rotate(-3deg); }
-
50% { transform: rotate(3deg); }
-
}
-
```
-
-
### Legacy Config Support (if needed)
-
```css
-
@import "tailwindcss";
-
@config "./tailwind.config.js";
-
```
-
-
## Breaking Changes from v3
-
-
### Import Changes
-
- โŒ `@tailwind base; @tailwind components; @tailwind utilities;`
-
- โœ… `@import "tailwindcss";`
-
-
### Removed Utilities
-
- `text-opacity-*` โ†’ Use `text-{color}/{opacity}` instead
-
- `bg-opacity-*` โ†’ Use `bg-{color}/{opacity}` instead
-
- `border-opacity-*` โ†’ Use `border-{color}/{opacity}` instead
-
- `flex-grow-*` โ†’ Use `grow-*`
-
- `flex-shrink-*` โ†’ Use `shrink-*`
-
- `decoration-slice` โ†’ Use `box-decoration-slice`
-
-
### Renamed Utilities
-
- `shadow-sm` โ†’ `shadow-xs`
-
- `rounded-sm` โ†’ `rounded-xs`
-
- `blur-sm` โ†’ `blur-xs`
-
- `bg-gradient-*` โ†’ `bg-linear-*`
-
-
### Default Behavior Changes
-
- **Border**: No longer defaults to gray-200, uses `currentColor`
-
- **Ring**: Changed from 3px blue to 1px `currentColor`
-
- **Outline**: Now 1px by default for consistency
-
-
## Custom Utilities
-
-
Use the `@utility` directive instead of `@layer utilities`:
-
-
```css
-
@utility btn {
-
padding: 0.5rem 1rem;
-
border-radius: 0.375rem;
-
font-weight: 500;
-
transition: all 0.2s;
-
}
-
-
@utility btn-primary {
-
background: var(--color-blue-600);
-
color: white;
-
-
&:hover {
-
background: var(--color-blue-700);
-
}
-
}
-
-
/* Functional utilities with parameters */
-
@utility margin-auto {
-
margin: auto;
-
}
-
-
@utility flex-center {
-
display: flex;
-
justify-content: center;
-
align-items: center;
-
}
-
```
-
-
## Custom Variants
-
-
```css
-
@custom-variant theme-dark {
-
&:where([data-theme="dark"] *) {
-
@slot;
-
}
-
}
-
-
@custom-variant any-hover {
-
@media (any-hover: hover) {
-
&:hover {
-
@slot;
-
}
-
}
-
}
-
```
-
-
## New Features in v4
-
-
### Container Queries (Built-in)
-
```html
-
<div class="@container">
-
<div class="grid grid-cols-1 @sm:grid-cols-2 @lg:grid-cols-3">
-
<div class="@min-w-64:text-lg @max-w-96:bg-blue-100">
-
Responsive to container size
-
</div>
-
</div>
-
</div>
-
```
-
-
### 3D Transforms
-
```html
-
<div class="perspective-1000">
-
<div class="rotate-x-45 rotate-y-12 scale-z-110 translate-z-24 transform-3d">
-
3D transformed element
-
</div>
-
</div>
-
```
-
-
### Enhanced Gradients
-
```html
-
<!-- Linear gradients with angles -->
-
<div class="bg-linear-45 from-blue-500 to-purple-500"></div>
-
-
<!-- Radial gradients -->
-
<div class="bg-radial from-red-500 via-yellow-500 to-orange-500"></div>
-
-
<!-- Conic gradients -->
-
<div class="bg-conic from-pink-500 via-blue-500 to-green-500"></div>
-
```
-
-
### Text Shadows
-
```html
-
<h1 class="text-shadow-lg text-shadow-blue-500/50">
-
Text with colored shadow
-
</h1>
-
```
-
-
### Mask Utilities
-
```html
-
<div class="mask-radial mask-cover">
-
<img src="image.jpg" alt="Masked image" />
-
</div>
-
```
-
-
### New Variants
-
-
#### @starting-style (for animations)
-
```html
-
<div class="opacity-100 @starting-style:opacity-0 transition-opacity">
-
Animates in on mount
-
</div>
-
```
-
-
#### not-* variant
-
```html
-
<div class="bg-blue-500 not-hover:bg-gray-500">
-
Blue except when hovering
-
</div>
-
```
-
-
#### nth-* variants
-
```html
-
<div class="nth-2:bg-red-500 nth-odd:bg-blue-500">
-
Nth child styling
-
</div>
-
```
-
-
#### inert variant
-
```html
-
<div class="inert:opacity-50 inert:pointer-events-none">
-
Styled when inert
-
</div>
-
```
-
-
#### in-* variant (like group-* but without group class)
-
```html
-
<article>
-
<h2 class="in-article:text-lg">Styled when inside article</h2>
-
</article>
-
```
-
-
### Modern Color System
-
v4 uses OKLCH color space for wider gamut support:
-
-
```css
-
@theme {
-
--color-brand-primary: oklch(0.7 0.15 180);
-
--color-brand-accent: oklch(0.8 0.2 45);
-
}
-
```
-
-
## Multi-Theme Strategy
-
-
```css
-
@import "tailwindcss";
-
-
@theme {
-
--color-primary: oklch(0.5 0.2 240);
-
--color-background: oklch(0.98 0.01 240);
-
}
-
-
@layer base {
-
[data-theme='dark'] {
-
--color-primary: oklch(0.7 0.2 240);
-
--color-background: oklch(0.15 0.02 240);
-
}
-
-
[data-theme='high-contrast'] {
-
--color-primary: oklch(0.0 0 0);
-
--color-background: oklch(1.0 0 0);
-
}
-
}
-
```
-
-
## Best Practices
-
-
### 1. Use CSS Variables for Dynamic Values
-
```html
-
<div class="bg-[var(--dynamic-color)] text-[var(--dynamic-size)]">
-
Dynamic styling
-
</div>
-
```
-
-
### 2. Leverage the New Color System
-
```html
-
<!-- Better contrast and vibrancy with OKLCH -->
-
<div class="bg-blue-500 text-white">
-
Vivid colors on modern displays
-
</div>
-
```
-
-
### 3. Container Queries for True Responsive Design
-
```html
-
<div class="@container">
-
<div class="p-4 @lg:p-8 @xl:p-12">
-
Responds to container, not viewport
-
</div>
-
</div>
-
```
-
-
### 4. Modern CSS Features
-
```html
-
<!-- Native cascade layers -->
-
<div class="layer-[utilities]:z-10">
-
Proper layer management
-
</div>
-
-
<!-- Color mixing -->
-
<div class="bg-blue-500/50">
-
Uses color-mix() under the hood
-
</div>
-
```
-
-
## Performance Optimizations
-
-
v4's Oxide engine provides:
-
- 5x faster full builds
-
- 100x faster incremental builds
-
- Automatic content detection
-
- Built-in import handling
-
- Native vendor prefixing
-
-
## File Organization
-
-
```
-
src/
-
โ”œโ”€โ”€ styles/
-
โ”‚ โ”œโ”€โ”€ main.css # @import "tailwindcss" + @theme
-
โ”‚ โ”œโ”€โ”€ components.css # @utility definitions
-
โ”‚ โ””โ”€โ”€ utilities.css # Additional @utility definitions
-
โ””โ”€โ”€ components/
-
โ””โ”€โ”€ *.vue/jsx/html # Your components
-
```
-
-
## Common Patterns
-
-
### Theme-aware Components
-
```css
-
@utility card {
-
background: var(--color-background);
-
border: 1px solid var(--color-border);
-
border-radius: 0.5rem;
-
padding: 1.5rem;
-
box-shadow: var(--shadow-sm);
-
}
-
```
-
-
### Responsive Typography
-
```html
-
<h1 class="text-2xl @sm:text-3xl @lg:text-4xl @xl:text-5xl">
-
Container-responsive heading
-
</h1>
-
```
-
-
### Animation with @starting-style
-
```html
-
<div class="translate-y-0 @starting-style:translate-y-full transition-transform duration-500">
-
Slides up on mount
-
</div>
-
```
-
-
## Debugging Tips
-
-
1. **Use browser dev tools** to inspect CSS variables
-
2. **Check cascade layers** in dev tools
-
3. **Verify modern browser support** for OKLCH colors
-
4. **Use @reference** for CSS modules/component styles
-
5. **Restart dev server** after major theme changes
-
-
## Migration from v3
-
-
1. Replace `@tailwind` directives with `@import "tailwindcss"`
-
2. Move config from JS to CSS using `@theme`
-
3. Update deprecated utility classes
-
4. Replace `@layer utilities` with `@utility`
-
5. Test in modern browsers only
-
6. Use the official upgrade tool: `npx @tailwindcss/upgrade@next`
-
-
## Complete Utility Class Reference
-
-
### Layout
-
-
#### Display
-
```
-
block, inline-block, inline, flex, inline-flex, table, inline-table, table-caption, table-cell, table-column, table-column-group, table-footer-group, table-header-group, table-row-group, table-row, flow-root, grid, inline-grid, contents, list-item, hidden
-
```
-
-
#### Position
-
```
-
static, fixed, absolute, relative, sticky
-
```
-
-
#### Top/Right/Bottom/Left
-
```
-
inset-0, inset-x-0, inset-y-0, start-0, end-0, top-0, right-0, bottom-0, left-0
-
inset-px, inset-x-px, inset-y-px, start-px, end-px, top-px, right-px, bottom-px, left-px
-
inset-0.5, inset-1, inset-1.5, inset-2, inset-2.5, inset-3, inset-3.5, inset-4, inset-5, inset-6, inset-7, inset-8, inset-9, inset-10, inset-11, inset-12, inset-14, inset-16, inset-20, inset-24, inset-28, inset-32, inset-36, inset-40, inset-44, inset-48, inset-52, inset-56, inset-60, inset-64, inset-72, inset-80, inset-96
-
inset-auto, inset-1/2, inset-1/3, inset-2/3, inset-1/4, inset-2/4, inset-3/4, inset-full
-
```
-
-
#### Visibility & Z-Index
-
```
-
visible, invisible, collapse
-
z-0, z-10, z-20, z-30, z-40, z-50, z-auto
-
```
-
-
#### Overflow
-
```
-
overflow-auto, overflow-hidden, overflow-clip, overflow-visible, overflow-scroll
-
overflow-x-auto, overflow-x-hidden, overflow-x-clip, overflow-x-visible, overflow-x-scroll
-
overflow-y-auto, overflow-y-hidden, overflow-y-clip, overflow-y-visible, overflow-y-scroll
-
```
-
-
### Flexbox & Grid
-
-
#### Flex Direction
-
```
-
flex-row, flex-row-reverse, flex-col, flex-col-reverse
-
```
-
-
#### Flex Wrap
-
```
-
flex-wrap, flex-wrap-reverse, flex-nowrap
-
```
-
-
#### Flex
-
```
-
flex-1, flex-auto, flex-initial, flex-none
-
```
-
-
#### Grow & Shrink
-
```
-
grow, grow-0, shrink, shrink-0
-
```
-
-
#### Order
-
```
-
order-1, order-2, order-3, order-4, order-5, order-6, order-7, order-8, order-9, order-10, order-11, order-12, order-first, order-last, order-none
-
```
-
-
#### Grid Template Columns
-
```
-
grid-cols-1, grid-cols-2, grid-cols-3, grid-cols-4, grid-cols-5, grid-cols-6, grid-cols-7, grid-cols-8, grid-cols-9, grid-cols-10, grid-cols-11, grid-cols-12, grid-cols-none, grid-cols-subgrid
-
```
-
-
#### Grid Column Start/End
-
```
-
col-auto, col-span-1, col-span-2, col-span-3, col-span-4, col-span-5, col-span-6, col-span-7, col-span-8, col-span-9, col-span-10, col-span-11, col-span-12, col-span-full
-
col-start-1, col-start-2, col-start-3, col-start-4, col-start-5, col-start-6, col-start-7, col-start-8, col-start-9, col-start-10, col-start-11, col-start-12, col-start-13, col-start-auto
-
col-end-1, col-end-2, col-end-3, col-end-4, col-end-5, col-end-6, col-end-7, col-end-8, col-end-9, col-end-10, col-end-11, col-end-12, col-end-13, col-end-auto
-
```
-
-
#### Grid Template Rows
-
```
-
grid-rows-1, grid-rows-2, grid-rows-3, grid-rows-4, grid-rows-5, grid-rows-6, grid-rows-7, grid-rows-8, grid-rows-9, grid-rows-10, grid-rows-11, grid-rows-12, grid-rows-none, grid-rows-subgrid
-
```
-
-
#### Grid Row Start/End
-
```
-
row-auto, row-span-1, row-span-2, row-span-3, row-span-4, row-span-5, row-span-6, row-span-7, row-span-8, row-span-9, row-span-10, row-span-11, row-span-12, row-span-full
-
row-start-1, row-start-2, row-start-3, row-start-4, row-start-5, row-start-6, row-start-7, row-start-8, row-start-9, row-start-10, row-start-11, row-start-12, row-start-13, row-start-auto
-
row-end-1, row-end-2, row-end-3, row-end-4, row-end-5, row-end-6, row-end-7, row-end-8, row-end-9, row-end-10, row-end-11, row-end-12, row-end-13, row-end-auto
-
```
-
-
#### Gap
-
```
-
gap-0, gap-x-0, gap-y-0, gap-px, gap-x-px, gap-y-px
-
gap-0.5, gap-1, gap-1.5, gap-2, gap-2.5, gap-3, gap-3.5, gap-4, gap-5, gap-6, gap-7, gap-8, gap-9, gap-10, gap-11, gap-12, gap-14, gap-16, gap-20, gap-24, gap-28, gap-32, gap-36, gap-40, gap-44, gap-48, gap-52, gap-56, gap-60, gap-64, gap-72, gap-80, gap-96
-
```
-
-
#### Justify & Align
-
```
-
justify-normal, justify-start, justify-end, justify-center, justify-between, justify-around, justify-evenly, justify-stretch
-
justify-items-start, justify-items-end, justify-items-center, justify-items-stretch
-
justify-self-auto, justify-self-start, justify-self-end, justify-self-center, justify-self-stretch
-
align-items-start, align-items-end, align-items-center, align-items-baseline, align-items-stretch
-
align-content-normal, align-content-center, align-content-start, align-content-end, align-content-between, align-content-around, align-content-evenly, align-content-baseline, align-content-stretch
-
align-self-auto, align-self-start, align-self-end, align-self-center, align-self-stretch, align-self-baseline
-
place-content-center, place-content-start, place-content-end, place-content-between, place-content-around, place-content-evenly, place-content-baseline, place-content-stretch
-
place-items-start, place-items-end, place-items-center, place-items-baseline, place-items-stretch
-
place-self-auto, place-self-start, place-self-end, place-self-center, place-self-stretch
-
```
-
-
### Spacing
-
-
#### Padding
-
```
-
p-0, p-px, p-0.5, p-1, p-1.5, p-2, p-2.5, p-3, p-3.5, p-4, p-5, p-6, p-7, p-8, p-9, p-10, p-11, p-12, p-14, p-16, p-20, p-24, p-28, p-32, p-36, p-40, p-44, p-48, p-52, p-56, p-60, p-64, p-72, p-80, p-96
-
px-0, py-0, pl-0, pr-0, pt-0, pb-0, ps-0, pe-0
-
```
-
-
#### Margin
-
```
-
m-0, m-px, m-0.5, m-1, m-1.5, m-2, m-2.5, m-3, m-3.5, m-4, m-5, m-6, m-7, m-8, m-9, m-10, m-11, m-12, m-14, m-16, m-20, m-24, m-28, m-32, m-36, m-40, m-44, m-48, m-52, m-56, m-60, m-64, m-72, m-80, m-96, m-auto
-
mx-0, my-0, ml-0, mr-0, mt-0, mb-0, ms-0, me-0
-
-m-0, -m-px, -m-0.5, -m-1, -m-1.5, -m-2, -m-2.5, -m-3, -m-3.5, -m-4, -m-5, -m-6, -m-7, -m-8, -m-9, -m-10, -m-11, -m-12, -m-14, -m-16, -m-20, -m-24, -m-28, -m-32, -m-36, -m-40, -m-44, -m-48, -m-52, -m-56, -m-60, -m-64, -m-72, -m-80, -m-96
-
```
-
-
#### Space Between
-
```
-
space-x-0, space-x-px, space-x-0.5, space-x-1, space-x-1.5, space-x-2, space-x-2.5, space-x-3, space-x-3.5, space-x-4, space-x-5, space-x-6, space-x-7, space-x-8, space-x-9, space-x-10, space-x-11, space-x-12, space-x-14, space-x-16, space-x-20, space-x-24, space-x-28, space-x-32, space-x-36, space-x-40, space-x-44, space-x-48, space-x-52, space-x-56, space-x-60, space-x-64, space-x-72, space-x-80, space-x-96, space-x-reverse
-
space-y-0, space-y-px, space-y-0.5, space-y-1, space-y-1.5, space-y-2, space-y-2.5, space-y-3, space-y-3.5, space-y-4, space-y-5, space-y-6, space-y-7, space-y-8, space-y-9, space-y-10, space-y-11, space-y-12, space-y-14, space-y-16, space-y-20, space-y-24, space-y-28, space-y-32, space-y-36, space-y-40, space-y-44, space-y-48, space-y-52, space-y-56, space-y-60, space-y-64, space-y-72, space-y-80, space-y-96, space-y-reverse
-
```
-
-
### Sizing
-
-
#### Width
-
```
-
w-0, w-px, w-0.5, w-1, w-1.5, w-2, w-2.5, w-3, w-3.5, w-4, w-5, w-6, w-7, w-8, w-9, w-10, w-11, w-12, w-14, w-16, w-20, w-24, w-28, w-32, w-36, w-40, w-44, w-48, w-52, w-56, w-60, w-64, w-72, w-80, w-96, w-auto, w-1/2, w-1/3, w-2/3, w-1/4, w-2/4, w-3/4, w-1/5, w-2/5, w-3/5, w-4/5, w-1/6, w-2/6, w-3/6, w-4/6, w-5/6, w-1/12, w-2/12, w-3/12, w-4/12, w-5/12, w-6/12, w-7/12, w-8/12, w-9/12, w-10/12, w-11/12, w-full, w-screen, w-svw, w-lvw, w-dvw, w-min, w-max, w-fit
-
```
-
-
#### Height
-
```
-
h-0, h-px, h-0.5, h-1, h-1.5, h-2, h-2.5, h-3, h-3.5, h-4, h-5, h-6, h-7, h-8, h-9, h-10, h-11, h-12, h-14, h-16, h-20, h-24, h-28, h-32, h-36, h-40, h-44, h-48, h-52, h-56, h-60, h-64, h-72, h-80, h-96, h-auto, h-1/2, h-1/3, h-2/3, h-1/4, h-2/4, h-3/4, h-1/5, h-2/5, h-3/5, h-4/5, h-1/6, h-2/6, h-3/6, h-4/6, h-5/6, h-full, h-screen, h-svh, h-lvh, h-dvh, h-min, h-max, h-fit
-
```
-
-
#### Size (Width + Height)
-
```
-
size-0, size-px, size-0.5, size-1, size-1.5, size-2, size-2.5, size-3, size-3.5, size-4, size-5, size-6, size-7, size-8, size-9, size-10, size-11, size-12, size-14, size-16, size-20, size-24, size-28, size-32, size-36, size-40, size-44, size-48, size-52, size-56, size-60, size-64, size-72, size-80, size-96, size-auto, size-1/2, size-1/3, size-2/3, size-1/4, size-2/4, size-3/4, size-1/5, size-2/5, size-3/5, size-4/5, size-1/6, size-2/6, size-3/6, size-4/6, size-5/6, size-1/12, size-2/12, size-3/12, size-4/12, size-5/12, size-6/12, size-7/12, size-8/12, size-9/12, size-10/12, size-11/12, size-full, size-min, size-max, size-fit
-
```
-
-
#### Min/Max Width
-
```
-
min-w-0, min-w-full, min-w-min, min-w-max, min-w-fit
-
max-w-0, max-w-xs, max-w-sm, max-w-md, max-w-lg, max-w-xl, max-w-2xl, max-w-3xl, max-w-4xl, max-w-5xl, max-w-6xl, max-w-7xl, max-w-full, max-w-min, max-w-max, max-w-fit, max-w-prose, max-w-screen-sm, max-w-screen-md, max-w-screen-lg, max-w-screen-xl, max-w-screen-2xl
-
```
-
-
#### Min/Max Height
-
```
-
min-h-0, min-h-full, min-h-screen, min-h-svh, min-h-lvh, min-h-dvh, min-h-min, min-h-max, min-h-fit
-
max-h-0, max-h-px, max-h-0.5, max-h-1, max-h-1.5, max-h-2, max-h-2.5, max-h-3, max-h-3.5, max-h-4, max-h-5, max-h-6, max-h-7, max-h-8, max-h-9, max-h-10, max-h-11, max-h-12, max-h-14, max-h-16, max-h-20, max-h-24, max-h-28, max-h-32, max-h-36, max-h-40, max-h-44, max-h-48, max-h-52, max-h-56, max-h-60, max-h-64, max-h-72, max-h-80, max-h-96, max-h-full, max-h-screen, max-h-svh, max-h-lvh, max-h-dvh, max-h-min, max-h-max, max-h-fit
-
```
-
-
### Typography
-
-
#### Font Family
-
```
-
font-sans, font-serif, font-mono
-
```
-
-
#### Font Size
-
```
-
text-xs, text-sm, text-base, text-lg, text-xl, text-2xl, text-3xl, text-4xl, text-5xl, text-6xl, text-7xl, text-8xl, text-9xl
-
```
-
-
#### Font Weight
-
```
-
font-thin, font-extralight, font-light, font-normal, font-medium, font-semibold, font-bold, font-extrabold, font-black
-
```
-
-
#### Font Style
-
```
-
italic, not-italic
-
```
-
-
#### Font Variant Numeric
-
```
-
normal-nums, ordinal, slashed-zero, lining-nums, oldstyle-nums, proportional-nums, tabular-nums, diagonal-fractions, stacked-fractions
-
```
-
-
#### Font Stretch (NEW in v4)
-
```
-
font-stretch-ultra-condensed, font-stretch-extra-condensed, font-stretch-condensed, font-stretch-semi-condensed, font-stretch-normal, font-stretch-semi-expanded, font-stretch-expanded, font-stretch-extra-expanded, font-stretch-ultra-expanded
-
```
-
-
#### Letter Spacing
-
```
-
tracking-tighter, tracking-tight, tracking-normal, tracking-wide, tracking-wider, tracking-widest
-
```
-
-
#### Line Clamp
-
```
-
line-clamp-1, line-clamp-2, line-clamp-3, line-clamp-4, line-clamp-5, line-clamp-6, line-clamp-none
-
```
-
-
#### Line Height
-
```
-
leading-3, leading-4, leading-5, leading-6, leading-7, leading-8, leading-9, leading-10, leading-none, leading-tight, leading-snug, leading-normal, leading-relaxed, leading-loose
-
```
-
-
#### List Style
-
```
-
list-none, list-disc, list-decimal, list-inside, list-outside
-
```
-
-
#### Text Align
-
```
-
text-left, text-center, text-right, text-justify, text-start, text-end
-
```
-
-
#### Text Color
-
```
-
text-inherit, text-current, text-transparent, text-black, text-white
-
text-slate-50, text-slate-100, text-slate-200, text-slate-300, text-slate-400, text-slate-500, text-slate-600, text-slate-700, text-slate-800, text-slate-900, text-slate-950
-
text-gray-50, text-gray-100, text-gray-200, text-gray-300, text-gray-400, text-gray-500, text-gray-600, text-gray-700, text-gray-800, text-gray-900, text-gray-950
-
text-zinc-50, text-zinc-100, text-zinc-200, text-zinc-300, text-zinc-400, text-zinc-500, text-zinc-600, text-zinc-700, text-zinc-800, text-zinc-900, text-zinc-950
-
text-neutral-50, text-neutral-100, text-neutral-200, text-neutral-300, text-neutral-400, text-neutral-500, text-neutral-600, text-neutral-700, text-neutral-800, text-neutral-900, text-neutral-950
-
text-stone-50, text-stone-100, text-stone-200, text-stone-300, text-stone-400, text-stone-500, text-stone-600, text-stone-700, text-stone-800, text-stone-900, text-stone-950
-
text-red-50, text-red-100, text-red-200, text-red-300, text-red-400, text-red-500, text-red-600, text-red-700, text-red-800, text-red-900, text-red-950
-
text-orange-50, text-orange-100, text-orange-200, text-orange-300, text-orange-400, text-orange-500, text-orange-600, text-orange-700, text-orange-800, text-orange-900, text-orange-950
-
text-amber-50, text-amber-100, text-amber-200, text-amber-300, text-amber-400, text-amber-500, text-amber-600, text-amber-700, text-amber-800, text-amber-900, text-amber-950
-
text-yellow-50, text-yellow-100, text-yellow-200, text-yellow-300, text-yellow-400, text-yellow-500, text-yellow-600, text-yellow-700, text-yellow-800, text-yellow-900, text-yellow-950
-
text-lime-50, text-lime-100, text-lime-200, text-lime-300, text-lime-400, text-lime-500, text-lime-600, text-lime-700, text-lime-800, text-lime-900, text-lime-950
-
text-green-50, text-green-100, text-green-200, text-green-300, text-green-400, text-green-500, text-green-600, text-green-700, text-green-800, text-green-900, text-green-950
-
text-emerald-50, text-emerald-100, text-emerald-200, text-emerald-300, text-emerald-400, text-emerald-500, text-emerald-600, text-emerald-700, text-emerald-800, text-emerald-900, text-emerald-950
-
text-teal-50, text-teal-100, text-teal-200, text-teal-300, text-teal-400, text-teal-500, text-teal-600, text-teal-700, text-teal-800, text-teal-900, text-teal-950
-
text-cyan-50, text-cyan-100, text-cyan-200, text-cyan-300, text-cyan-400, text-cyan-500, text-cyan-600, text-cyan-700, text-cyan-800, text-cyan-900, text-cyan-950
-
text-sky-50, text-sky-100, text-sky-200, text-sky-300, text-sky-400, text-sky-500, text-sky-600, text-sky-700, text-sky-800, text-sky-900, text-sky-950
-
text-blue-50, text-blue-100, text-blue-200, text-blue-300, text-blue-400, text-blue-500, text-blue-600, text-blue-700, text-blue-800, text-blue-900, text-blue-950
-
text-indigo-50, text-indigo-100, text-indigo-200, text-indigo-300, text-indigo-400, text-indigo-500, text-indigo-600, text-indigo-700, text-indigo-800, text-indigo-900, text-indigo-950
-
text-violet-50, text-violet-100, text-violet-200, text-violet-300, text-violet-400, text-violet-500, text-violet-600, text-violet-700, text-violet-800, text-violet-900, text-violet-950
-
text-purple-50, text-purple-100, text-purple-200, text-purple-300, text-purple-400, text-purple-500, text-purple-600, text-purple-700, text-purple-800, text-purple-900, text-purple-950
-
text-fuchsia-50, text-fuchsia-100, text-fuchsia-200, text-fuchsia-300, text-fuchsia-400, text-fuchsia-500, text-fuchsia-600, text-fuchsia-700, text-fuchsia-800, text-fuchsia-900, text-fuchsia-950
-
text-pink-50, text-pink-100, text-pink-200, text-pink-300, text-pink-400, text-pink-500, text-pink-600, text-pink-700, text-pink-800, text-pink-900, text-pink-950
-
text-rose-50, text-rose-100, text-rose-200, text-rose-300, text-rose-400, text-rose-500, text-rose-600, text-rose-700, text-rose-800, text-rose-900, text-rose-950
-
```
-
-
#### Text Decoration
-
```
-
underline, overline, line-through, no-underline
-
decoration-solid, decoration-double, decoration-dotted, decoration-dashed, decoration-wavy
-
decoration-auto, decoration-from-font, decoration-0, decoration-1, decoration-2, decoration-4, decoration-8
-
underline-offset-auto, underline-offset-0, underline-offset-1, underline-offset-2, underline-offset-4, underline-offset-8
-
```
-
-
#### Text Transform
-
```
-
uppercase, lowercase, capitalize, normal-case
-
```
-
-
#### Text Overflow
-
```
-
truncate, text-ellipsis, text-clip
-
```
-
-
#### Text Shadow (NEW in v4)
-
```
-
text-shadow-sm, text-shadow, text-shadow-lg, text-shadow-xl, text-shadow-none
-
```
-
-
#### Overflow Wrap (NEW in v4)
-
```
-
overflow-wrap-normal, overflow-wrap-break-word, overflow-wrap-anywhere
-
```
-
-
#### Vertical Align
-
```
-
align-baseline, align-top, align-middle, align-bottom, align-text-top, align-text-bottom, align-sub, align-super
-
```
-
-
#### Whitespace
-
```
-
whitespace-normal, whitespace-nowrap, whitespace-pre, whitespace-pre-line, whitespace-pre-wrap, whitespace-break-spaces
-
```
-
-
#### Word Break
-
```
-
break-normal, break-words, break-all, break-keep
-
```
-
-
#### Hyphens
-
```
-
hyphens-none, hyphens-manual, hyphens-auto
-
```
-
-
#### Content
-
```
-
content-none
-
```
-
-
### Backgrounds
-
-
#### Background Attachment
-
```
-
bg-fixed, bg-local, bg-scroll
-
```
-
-
#### Background Clip
-
```
-
bg-clip-border, bg-clip-padding, bg-clip-content, bg-clip-text
-
```
-
-
#### Background Color
-
All color utilities work with `bg-` prefix (same as text colors above)
-
-
#### Background Origin
-
```
-
bg-origin-border, bg-origin-padding, bg-origin-content
-
```
-
-
#### Background Position
-
```
-
bg-bottom, bg-center, bg-left, bg-left-bottom, bg-left-top, bg-right, bg-right-bottom, bg-right-top, bg-top
-
```
-
-
#### Background Repeat
-
```
-
bg-repeat, bg-no-repeat, bg-repeat-x, bg-repeat-y, bg-repeat-round, bg-repeat-space
-
```
-
-
#### Background Size
-
```
-
bg-auto, bg-cover, bg-contain
-
```
-
-
#### Background Image
-
```
-
bg-none
-
bg-linear-to-t, bg-linear-to-tr, bg-linear-to-r, bg-linear-to-br, bg-linear-to-b, bg-linear-to-bl, bg-linear-to-l, bg-linear-to-tl
-
```
-
-
#### Enhanced Gradients (NEW in v4)
-
```
-
bg-linear-0, bg-linear-45, bg-linear-90, bg-linear-135, bg-linear-180, bg-linear-225, bg-linear-270, bg-linear-315
-
bg-radial, bg-radial-at-t, bg-radial-at-tr, bg-radial-at-r, bg-radial-at-br, bg-radial-at-b, bg-radial-at-bl, bg-radial-at-l, bg-radial-at-tl, bg-radial-at-c
-
bg-conic, bg-conic-at-t, bg-conic-at-tr, bg-conic-at-r, bg-conic-at-br, bg-conic-at-b, bg-conic-at-bl, bg-conic-at-l, bg-conic-at-tl, bg-conic-at-c
-
```
-
-
#### Gradient Color Stops
-
```
-
from-inherit, from-current, from-transparent, from-black, from-white, from-{color}
-
via-inherit, via-current, via-transparent, via-black, via-white, via-{color}
-
to-inherit, to-current, to-transparent, to-black, to-white, to-{color}
-
```
-
-
### Borders
-
-
#### Border Radius
-
```
-
rounded-none, rounded-xs, rounded-sm, rounded, rounded-md, rounded-lg, rounded-xl, rounded-2xl, rounded-3xl, rounded-full
-
rounded-s-none, rounded-s-xs, rounded-s-sm, rounded-s, rounded-s-md, rounded-s-lg, rounded-s-xl, rounded-s-2xl, rounded-s-3xl
-
rounded-e-none, rounded-e-xs, rounded-e-sm, rounded-e, rounded-e-md, rounded-e-lg, rounded-e-xl, rounded-e-2xl, rounded-e-3xl
-
rounded-t-none, rounded-t-xs, rounded-t-sm, rounded-t, rounded-t-md, rounded-t-lg, rounded-t-xl, rounded-t-2xl, rounded-t-3xl
-
rounded-r-none, rounded-r-xs, rounded-r-sm, rounded-r, rounded-r-md, rounded-r-lg, rounded-r-xl, rounded-r-2xl, rounded-r-3xl
-
rounded-b-none, rounded-b-xs, rounded-b-sm, rounded-b, rounded-b-md, rounded-b-lg, rounded-b-xl, rounded-b-2xl, rounded-b-3xl
-
rounded-l-none, rounded-l-xs, rounded-l-sm, rounded-l, rounded-l-md, rounded-l-lg, rounded-l-xl, rounded-l-2xl, rounded-l-3xl
-
rounded-ss-none, rounded-ss-xs, rounded-ss-sm, rounded-ss, rounded-ss-md, rounded-ss-lg, rounded-ss-xl, rounded-ss-2xl, rounded-ss-3xl
-
rounded-se-none, rounded-se-xs, rounded-se-sm, rounded-se, rounded-se-md, rounded-se-lg, rounded-se-xl, rounded-se-2xl, rounded-se-3xl
-
rounded-ee-none, rounded-ee-xs, rounded-ee-sm, rounded-ee, rounded-ee-md, rounded-ee-lg, rounded-ee-xl, rounded-ee-2xl, rounded-ee-3xl
-
rounded-es-none, rounded-es-xs, rounded-es-sm, rounded-es, rounded-es-md, rounded-es-lg, rounded-es-xl, rounded-es-2xl, rounded-es-3xl
-
rounded-tl-none, rounded-tl-xs, rounded-tl-sm, rounded-tl, rounded-tl-md, rounded-tl-lg, rounded-tl-xl, rounded-tl-2xl, rounded-tl-3xl
-
rounded-tr-none, rounded-tr-xs, rounded-tr-sm, rounded-tr, rounded-tr-md, rounded-tr-lg, rounded-tr-xl, rounded-tr-2xl, rounded-tr-3xl
-
rounded-br-none, rounded-br-xs, rounded-br-sm, rounded-br, rounded-br-md, rounded-br-lg, rounded-br-xl, rounded-br-2xl, rounded-br-3xl
-
rounded-bl-none, rounded-bl-xs, rounded-bl-sm, rounded-bl, rounded-bl-md, rounded-bl-lg, rounded-bl-xl, rounded-bl-2xl, rounded-bl-3xl
-
```
-
-
#### Border Width
-
```
-
border-0, border-2, border-4, border-8, border, border-x, border-y, border-s, border-e, border-t, border-r, border-b, border-l
-
```
-
-
#### Border Color
-
All color utilities work with `border-` prefix (same as text/bg colors)
-
-
#### Border Style
-
```
-
border-solid, border-dashed, border-dotted, border-double, border-hidden, border-none
-
```
-
-
#### Divide Width
-
```
-
divide-x-0, divide-x-2, divide-x-4, divide-x-8, divide-x, divide-y-0, divide-y-2, divide-y-4, divide-y-8, divide-y, divide-x-reverse, divide-y-reverse
-
```
-
-
#### Divide Color
-
All color utilities work with `divide-` prefix
-
-
#### Divide Style
-
```
-
divide-solid, divide-dashed, divide-dotted, divide-double, divide-none
-
```
-
-
#### Outline Width
-
```
-
outline-0, outline-1, outline-2, outline-4, outline-8
-
```
-
-
#### Outline Color
-
All color utilities work with `outline-` prefix
-
-
#### Outline Style
-
```
-
outline-none, outline, outline-dashed, outline-dotted, outline-double
-
```
-
-
#### Outline Offset
-
```
-
outline-offset-0, outline-offset-1, outline-offset-2, outline-offset-4, outline-offset-8
-
```
-
-
#### Ring Width
-
```
-
ring-0, ring-1, ring-2, ring, ring-4, ring-8, ring-inset
-
```
-
-
#### Ring Color
-
All color utilities work with `ring-` prefix
-
-
#### Ring Offset Width
-
```
-
ring-offset-0, ring-offset-1, ring-offset-2, ring-offset-4, ring-offset-8
-
```
-
-
#### Ring Offset Color
-
All color utilities work with `ring-offset-` prefix
-
-
### Effects
-
-
#### Box Shadow
-
```
-
shadow-xs, shadow-sm, shadow, shadow-md, shadow-lg, shadow-xl, shadow-2xl, shadow-inner, shadow-none
-
```
-
-
#### Box Shadow Color
-
All color utilities work with `shadow-` prefix
-
-
#### Drop Shadow (NEW colored support in v4)
-
```
-
drop-shadow-sm, drop-shadow, drop-shadow-md, drop-shadow-lg, drop-shadow-xl, drop-shadow-2xl, drop-shadow-none
-
```
-
-
#### Opacity
-
```
-
opacity-0, opacity-5, opacity-10, opacity-15, opacity-20, opacity-25, opacity-30, opacity-35, opacity-40, opacity-45, opacity-50, opacity-55, opacity-60, opacity-65, opacity-70, opacity-75, opacity-80, opacity-85, opacity-90, opacity-95, opacity-100
-
```
-
-
#### Mix Blend Mode
-
```
-
mix-blend-normal, mix-blend-multiply, mix-blend-screen, mix-blend-overlay, mix-blend-darken, mix-blend-lighten, mix-blend-color-dodge, mix-blend-color-burn, mix-blend-hard-light, mix-blend-soft-light, mix-blend-difference, mix-blend-exclusion, mix-blend-hue, mix-blend-saturation, mix-blend-color, mix-blend-luminosity, mix-blend-plus-darker, mix-blend-plus-lighter
-
```
-
-
#### Background Blend Mode
-
```
-
bg-blend-normal, bg-blend-multiply, bg-blend-screen, bg-blend-overlay, bg-blend-darken, bg-blend-lighten, bg-blend-color-dodge, bg-blend-color-burn, bg-blend-hard-light, bg-blend-soft-light, bg-blend-difference, bg-blend-exclusion, bg-blend-hue, bg-blend-saturation, bg-blend-color, bg-blend-luminosity
-
```
-
-
### Filters
-
-
#### Blur
-
```
-
blur-none, blur-xs, blur-sm, blur, blur-md, blur-lg, blur-xl, blur-2xl, blur-3xl
-
```
-
-
#### Brightness
-
```
-
brightness-0, brightness-50, brightness-75, brightness-90, brightness-95, brightness-100, brightness-105, brightness-110, brightness-125, brightness-150, brightness-200
-
```
-
-
#### Contrast
-
```
-
contrast-0, contrast-50, contrast-75, contrast-100, contrast-125, contrast-150, contrast-200
-
```
-
-
#### Grayscale
-
```
-
grayscale-0, grayscale
-
```
-
-
#### Hue Rotate
-
```
-
hue-rotate-0, hue-rotate-15, hue-rotate-30, hue-rotate-60, hue-rotate-90, hue-rotate-180, -hue-rotate-180, -hue-rotate-90, -hue-rotate-60, -hue-rotate-30, -hue-rotate-15
-
```
-
-
#### Invert
-
```
-
invert-0, invert
-
```
-
-
#### Saturate
-
```
-
saturate-0, saturate-50, saturate-100, saturate-150, saturate-200
-
```
-
-
#### Sepia
-
```
-
sepia-0, sepia
-
```
-
-
#### Backdrop Blur
-
```
-
backdrop-blur-none, backdrop-blur-xs, backdrop-blur-sm, backdrop-blur, backdrop-blur-md, backdrop-blur-lg, backdrop-blur-xl, backdrop-blur-2xl, backdrop-blur-3xl
-
```
-
-
#### Backdrop Brightness
-
```
-
backdrop-brightness-0, backdrop-brightness-50, backdrop-brightness-75, backdrop-brightness-90, backdrop-brightness-95, backdrop-brightness-100, backdrop-brightness-105, backdrop-brightness-110, backdrop-brightness-125, backdrop-brightness-150, backdrop-brightness-200
-
```
-
-
#### Backdrop Contrast
-
```
-
backdrop-contrast-0, backdrop-contrast-50, backdrop-contrast-75, backdrop-contrast-100, backdrop-contrast-125, backdrop-contrast-150, backdrop-contrast-200
-
```
-
-
#### Backdrop Grayscale
-
```
-
backdrop-grayscale-0, backdrop-grayscale
-
```
-
-
#### Backdrop Hue Rotate
-
```
-
backdrop-hue-rotate-0, backdrop-hue-rotate-15, backdrop-hue-rotate-30, backdrop-hue-rotate-60, backdrop-hue-rotate-90, backdrop-hue-rotate-180, -backdrop-hue-rotate-180, -backdrop-hue-rotate-90, -backdrop-hue-rotate-60, -backdrop-hue-rotate-30, -backdrop-hue-rotate-15
-
```
-
-
#### Backdrop Invert
-
```
-
backdrop-invert-0, backdrop-invert
-
```
-
-
#### Backdrop Saturate
-
```
-
backdrop-saturate-0, backdrop-saturate-50, backdrop-saturate-100, backdrop-saturate-150, backdrop-saturate-200
-
```
-
-
#### Backdrop Sepia
-
```
-
backdrop-sepia-0, backdrop-sepia
-
```
-
-
### Masks (NEW in v4)
-
-
#### Mask Image
-
```
-
mask-none
-
```
-
-
#### Mask Size
-
```
-
mask-auto, mask-cover, mask-contain
-
```
-
-
#### Mask Repeat
-
```
-
mask-repeat, mask-no-repeat, mask-repeat-x, mask-repeat-y, mask-repeat-round, mask-repeat-space
-
```
-
-
#### Mask Position
-
```
-
mask-bottom, mask-center, mask-left, mask-left-bottom, mask-left-top, mask-right, mask-right-bottom, mask-right-top, mask-top
-
```
-
-
#### Mask Origin
-
```
-
mask-origin-border, mask-origin-padding, mask-origin-content
-
```
-
-
#### Mask Clip
-
```
-
mask-clip-border, mask-clip-padding, mask-clip-content
-
```
-
-
#### Mask Composite
-
```
-
mask-composite-add, mask-composite-subtract, mask-composite-intersect, mask-composite-exclude
-
```
-
-
#### Mask Mode
-
```
-
mask-mode-match-source, mask-mode-luminance, mask-mode-alpha
-
```
-
-
#### Mask Type
-
```
-
mask-type-luminance, mask-type-alpha
-
```
-
-
### Tables
-
-
#### Border Collapse
-
```
-
border-collapse, border-separate
-
```
-
-
#### Border Spacing
-
```
-
border-spacing-0, border-spacing-px, border-spacing-0.5, border-spacing-1, border-spacing-1.5, border-spacing-2, border-spacing-2.5, border-spacing-3, border-spacing-3.5, border-spacing-4, border-spacing-5, border-spacing-6, border-spacing-7, border-spacing-8, border-spacing-9, border-spacing-10, border-spacing-11, border-spacing-12, border-spacing-14, border-spacing-16, border-spacing-20, border-spacing-24, border-spacing-28, border-spacing-32, border-spacing-36, border-spacing-40, border-spacing-44, border-spacing-48, border-spacing-52, border-spacing-56, border-spacing-60, border-spacing-64, border-spacing-72, border-spacing-80, border-spacing-96
-
border-spacing-x-0, border-spacing-y-0 (and all other spacing values)
-
```
-
-
#### Table Layout
-
```
-
table-auto, table-fixed
-
```
-
-
#### Caption Side
-
```
-
caption-top, caption-bottom
-
```
-
-
### Transforms
-
-
#### Scale
-
```
-
scale-0, scale-50, scale-75, scale-90, scale-95, scale-100, scale-105, scale-110, scale-125, scale-150
-
scale-x-0, scale-x-50, scale-x-75, scale-x-90, scale-x-95, scale-x-100, scale-x-105, scale-x-110, scale-x-125, scale-x-150
-
scale-y-0, scale-y-50, scale-y-75, scale-y-90, scale-y-95, scale-y-100, scale-y-105, scale-y-110, scale-y-125, scale-y-150
-
```
-
-
#### Scale Z (NEW in v4)
-
```
-
scale-z-0, scale-z-50, scale-z-75, scale-z-90, scale-z-95, scale-z-100, scale-z-105, scale-z-110, scale-z-125, scale-z-150
-
```
-
-
#### Rotate
-
```
-
rotate-0, rotate-1, rotate-2, rotate-3, rotate-6, rotate-12, rotate-45, rotate-90, rotate-180, -rotate-180, -rotate-90, -rotate-45, -rotate-12, -rotate-6, -rotate-3, -rotate-2, -rotate-1
-
```
-
-
#### Rotate X/Y (NEW in v4)
-
```
-
rotate-x-0, rotate-x-1, rotate-x-2, rotate-x-3, rotate-x-6, rotate-x-12, rotate-x-45, rotate-x-90, rotate-x-180, -rotate-x-180, -rotate-x-90, -rotate-x-45, -rotate-x-12, -rotate-x-6, -rotate-x-3, -rotate-x-2, -rotate-x-1
-
rotate-y-0, rotate-y-1, rotate-y-2, rotate-y-3, rotate-y-6, rotate-y-12, rotate-y-45, rotate-y-90, rotate-y-180, -rotate-y-180, -rotate-y-90, -rotate-y-45, -rotate-y-12, -rotate-y-6, -rotate-y-3, -rotate-y-2, -rotate-y-1
-
```
-
-
#### Translate
-
```
-
translate-x-0, translate-x-px, translate-x-0.5, translate-x-1, translate-x-1.5, translate-x-2, translate-x-2.5, translate-x-3, translate-x-3.5, translate-x-4, translate-x-5, translate-x-6, translate-x-7, translate-x-8, translate-x-9, translate-x-10, translate-x-11, translate-x-12, translate-x-14, translate-x-16, translate-x-20, translate-x-24, translate-x-28, translate-x-32, translate-x-36, translate-x-40, translate-x-44, translate-x-48, translate-x-52, translate-x-56, translate-x-60, translate-x-64, translate-x-72, translate-x-80, translate-x-96, translate-x-1/2, translate-x-1/3, translate-x-2/3, translate-x-1/4, translate-x-2/4, translate-x-3/4, translate-x-full
-
translate-y-0, translate-y-px, translate-y-0.5, translate-y-1, translate-y-1.5, translate-y-2, translate-y-2.5, translate-y-3, translate-y-3.5, translate-y-4, translate-y-5, translate-y-6, translate-y-7, translate-y-8, translate-y-9, translate-y-10, translate-y-11, translate-y-12, translate-y-14, translate-y-16, translate-y-20, translate-y-24, translate-y-28, translate-y-32, translate-y-36, translate-y-40, translate-y-44, translate-y-48, translate-y-52, translate-y-56, translate-y-60, translate-y-64, translate-y-72, translate-y-80, translate-y-96, translate-y-1/2, translate-y-1/3, translate-y-2/3, translate-y-1/4, translate-y-2/4, translate-y-3/4, translate-y-full
-
```
-
-
#### Translate Z (NEW in v4)
-
```
-
translate-z-0, translate-z-px, translate-z-0.5, translate-z-1, translate-z-1.5, translate-z-2, translate-z-2.5, translate-z-3, translate-z-3.5, translate-z-4, translate-z-5, translate-z-6, translate-z-7, translate-z-8, translate-z-9, translate-z-10, translate-z-11, translate-z-12, translate-z-14, translate-z-16, translate-z-20, translate-z-24, translate-z-28, translate-z-32, translate-z-36, translate-z-40, translate-z-44, translate-z-48, translate-z-52, translate-z-56, translate-z-60, translate-z-64, translate-z-72, translate-z-80, translate-z-96
-
```
-
-
#### Skew
-
```
-
skew-x-0, skew-x-1, skew-x-2, skew-x-3, skew-x-6, skew-x-12, -skew-x-12, -skew-x-6, -skew-x-3, -skew-x-2, -skew-x-1
-
skew-y-0, skew-y-1, skew-y-2, skew-y-3, skew-y-6, skew-y-12, -skew-y-12, -skew-y-6, -skew-y-3, -skew-y-2, -skew-y-1
-
```
-
-
#### Transform Origin
-
```
-
origin-center, origin-top, origin-top-right, origin-right, origin-bottom-right, origin-bottom, origin-bottom-left, origin-left, origin-top-left
-
```
-
-
#### Transform Style (NEW in v4)
-
```
-
transform-style-flat, transform-style-preserve-3d
-
```
-
-
#### Perspective (NEW in v4)
-
```
-
perspective-none, perspective-250, perspective-500, perspective-750, perspective-1000, perspective-distant
-
```
-
-
#### Perspective Origin (NEW in v4)
-
```
-
perspective-origin-center, perspective-origin-top, perspective-origin-top-right, perspective-origin-right, perspective-origin-bottom-right, perspective-origin-bottom, perspective-origin-bottom-left, perspective-origin-left, perspective-origin-top-left
-
```
-
-
### Interactivity
-
-
#### Accent Color
-
```
-
accent-auto, accent-inherit, accent-current, accent-transparent, accent-black, accent-white
-
accent-{color} (all color utilities work with accent- prefix)
-
```
-
-
#### Appearance
-
```
-
appearance-none, appearance-auto
-
```
-
-
#### Cursor
-
```
-
cursor-auto, cursor-default, cursor-pointer, cursor-wait, cursor-text, cursor-move, cursor-help, cursor-not-allowed, cursor-none, cursor-context-menu, cursor-progress, cursor-cell, cursor-crosshair, cursor-vertical-text, cursor-alias, cursor-copy, cursor-no-drop, cursor-grab, cursor-grabbing, cursor-all-scroll, cursor-col-resize, cursor-row-resize, cursor-n-resize, cursor-e-resize, cursor-s-resize, cursor-w-resize, cursor-ne-resize, cursor-nw-resize, cursor-se-resize, cursor-sw-resize, cursor-ew-resize, cursor-ns-resize, cursor-nesw-resize, cursor-nwse-resize, cursor-zoom-in, cursor-zoom-out
-
```
-
-
#### Caret Color
-
All color utilities work with `caret-` prefix
-
-
#### Pointer Events
-
```
-
pointer-events-none, pointer-events-auto
-
```
-
-
#### Resize
-
```
-
resize-none, resize, resize-y, resize-x
-
```
-
-
#### Scroll Behavior
-
```
-
scroll-auto, scroll-smooth
-
```
-
-
#### Scroll Margin
-
```
-
scroll-m-0, scroll-m-px, scroll-m-0.5, scroll-m-1, scroll-m-1.5, scroll-m-2, scroll-m-2.5, scroll-m-3, scroll-m-3.5, scroll-m-4, scroll-m-5, scroll-m-6, scroll-m-7, scroll-m-8, scroll-m-9, scroll-m-10, scroll-m-11, scroll-m-12, scroll-m-14, scroll-m-16, scroll-m-20, scroll-m-24, scroll-m-28, scroll-m-32, scroll-m-36, scroll-m-40, scroll-m-44, scroll-m-48, scroll-m-52, scroll-m-56, scroll-m-60, scroll-m-64, scroll-m-72, scroll-m-80, scroll-m-96
-
scroll-mx-0, scroll-my-0, scroll-ms-0, scroll-me-0, scroll-mt-0, scroll-mr-0, scroll-mb-0, scroll-ml-0 (and all spacing values)
-
```
-
-
#### Scroll Padding
-
```
-
scroll-p-0, scroll-p-px, scroll-p-0.5, scroll-p-1, scroll-p-1.5, scroll-p-2, scroll-p-2.5, scroll-p-3, scroll-p-3.5, scroll-p-4, scroll-p-5, scroll-p-6, scroll-p-7, scroll-p-8, scroll-p-9, scroll-p-10, scroll-p-11, scroll-p-12, scroll-p-14, scroll-p-16, scroll-p-20, scroll-p-24, scroll-p-28, scroll-p-32, scroll-p-36, scroll-p-40, scroll-p-44, scroll-p-48, scroll-p-52, scroll-p-56, scroll-p-60, scroll-p-64, scroll-p-72, scroll-p-80, scroll-p-96
-
scroll-px-0, scroll-py-0, scroll-ps-0, scroll-pe-0, scroll-pt-0, scroll-pr-0, scroll-pb-0, scroll-pl-0 (and all spacing values)
-
```
-
-
#### Scroll Snap Align
-
```
-
snap-start, snap-end, snap-center, snap-align-none
-
```
-
-
#### Scroll Snap Stop
-
```
-
snap-normal, snap-always
-
```
-
-
#### Scroll Snap Type
-
```
-
snap-none, snap-x, snap-y, snap-both, snap-mandatory, snap-proximity
-
```
-
-
#### Touch Action
-
```
-
touch-auto, touch-none, touch-pan-x, touch-pan-left, touch-pan-right, touch-pan-y, touch-pan-up, touch-pan-down, touch-pinch-zoom, touch-manipulation
-
```
-
-
#### User Select
-
```
-
select-none, select-text, select-all, select-auto
-
```
-
-
#### Will Change
-
```
-
will-change-auto, will-change-scroll, will-change-contents, will-change-transform
-
```
-
-
### SVG
-
-
#### Fill
-
```
-
fill-none, fill-inherit, fill-current, fill-transparent, fill-black, fill-white
-
fill-{color} (all color utilities work with fill- prefix)
-
```
-
-
#### Stroke
-
```
-
stroke-none, stroke-inherit, stroke-current, stroke-transparent, stroke-black, stroke-white
-
stroke-{color} (all color utilities work with stroke- prefix)
-
```
-
-
#### Stroke Width
-
```
-
stroke-0, stroke-1, stroke-2
-
```
-
-
### Accessibility
-
-
#### Screen Readers
-
```
-
sr-only, not-sr-only
-
```
-
-
#### Forced Color Adjust
-
```
-
forced-color-adjust-auto, forced-color-adjust-none
-
```
-
-
### Container Queries (NEW in v4)
-
-
#### Container Type
-
```
-
@container, @container-normal, @container-size, @container-inline-size
-
```
-
-
#### Container Query Variants
-
```
-
@xs:, @sm:, @md:, @lg:, @xl:, @2xl:, @3xl:, @4xl:, @5xl:, @6xl:, @7xl:
-
@min-w-0:, @min-w-xs:, @min-w-sm:, @min-w-md:, @min-w-lg:, @min-w-xl:, @min-w-2xl:, @min-w-3xl:, @min-w-4xl:, @min-w-5xl:, @min-w-6xl:, @min-w-7xl:
-
@max-w-xs:, @max-w-sm:, @max-w-md:, @max-w-lg:, @max-w-xl:, @max-w-2xl:, @max-w-3xl:, @max-w-4xl:, @max-w-5xl:, @max-w-6xl:, @max-w-7xl:
-
@min-h-0:, @min-h-xs:, @min-h-sm:, @min-h-md:, @min-h-lg:, @min-h-xl:, @min-h-2xl:, @min-h-3xl:, @min-h-4xl:, @min-h-5xl:, @min-h-6xl:, @min-h-7xl:
-
@max-h-xs:, @max-h-sm:, @max-h-md:, @max-h-lg:, @max-h-xl:, @max-h-2xl:, @max-h-3xl:, @max-h-4xl:, @max-h-5xl:, @max-h-6xl:, @max-h-7xl:
-
```
-
-
### Responsive Design
-
-
#### Breakpoint Variants
-
```
-
sm:, md:, lg:, xl:, 2xl:
-
max-sm:, max-md:, max-lg:, max-xl:, max-2xl:
-
```
-
-
### State Variants
-
-
#### Hover, Focus, etc.
-
```
-
hover:, focus:, focus-within:, focus-visible:, active:, visited:, target:, disabled:, enabled:, checked:, indeterminate:, default:, required:, valid:, invalid:, in-range:, out-of-range:, placeholder-shown:, autofill:, read-only:
-
```
-
-
#### Group States
-
```
-
group-hover:, group-focus:, group-focus-within:, group-focus-visible:, group-active:, group-visited:, group-target:, group-disabled:, group-enabled:, group-checked:, group-indeterminate:, group-default:, group-required:, group-valid:, group-invalid:, group-in-range:, group-out-of-range:, group-placeholder-shown:, group-autofill:, group-read-only:
-
```
-
-
#### Peer States
-
```
-
peer-hover:, peer-focus:, peer-focus-within:, peer-focus-visible:, peer-active:, peer-visited:, peer-target:, peer-disabled:, peer-enabled:, peer-checked:, peer-indeterminate:, peer-default:, peer-required:, peer-valid:, peer-invalid:, peer-in-range:, peer-out-of-range:, peer-placeholder-shown:, peer-autofill:, peer-read-only:
-
```
-
-
#### NEW Variants in v4
-
```
-
@starting-style:, not-*, nth-*, in-*, inert:, open: (for popovers)
-
```
-
-
### Media Queries
-
-
#### Dark Mode
-
```
-
dark:
-
```
-
-
#### Motion
-
```
-
motion-safe:, motion-reduce:
-
```
-
-
#### Contrast
-
```
-
contrast-more:, contrast-less:
-
```
-
-
#### Print
-
```
-
print:
-
```
-
-
#### Orientation
-
```
-
portrait:, landscape:
-
```
-
-
### Content
-
```
-
content-none, content-['text']
-
```
-
-
### Arbitrary Values
-
You can use arbitrary values with square brackets for any property:
-
```
-
w-[123px], h-[456px], text-[#bada55], bg-[url('...')], top-[117px], left-[344px]
-
m-[12px], p-[24px], grid-cols-[200px_minmax(900px,_1fr)_100px]
-
```
-
-
### Arbitrary Properties
-
```
-
[mask-type:luminance], [tab-size:4], [@supports(backdrop-filter:blur(0))]:bg-white/75
-
```
-
-
### Arbitrary Variants
-
```
-
[&:nth-child(3)]:, [&:hover]:, [&_p]:, [@media(min-width:600px)]:
-
[@supports(backdrop-filter:blur(0))]:, [data-theme="dark"]:
-
```
-
-
## Common v4 Pitfalls to Avoid
-
-
### Don't Use These Deprecated Patterns
-
- โŒ `@tailwind base; @tailwind components; @tailwind utilities;`
-
- โŒ `text-opacity-50` โ†’ Use `text-white/50` instead
-
- โŒ `bg-opacity-25` โ†’ Use `bg-blue-500/25` instead
-
- โŒ `border` without color (now uses currentColor, not gray-200)
-
- โŒ `ring` without explicit width (now 1px, was 3px)
-
- โŒ `@layer utilities` โ†’ Use `@utility` instead
-
- โŒ JavaScript config for new projects โ†’ Use CSS `@theme`
-
-
### Modern v4 Alternatives
-
- โœ… `@import "tailwindcss";`
-
- โœ… `text-white/50` for semi-transparent text
-
- โœ… `bg-blue-500/25` for semi-transparent backgrounds
-
- โœ… `border border-gray-200` for explicit border color
-
- โœ… `ring-3` for 3px ring width
-
- โœ… `@utility` for custom utilities
-
- โœ… `@theme` for configuration
-
-
## Performance Best Practices
-
-
### Leverage v4's Performance Features
-
- Use automatic content detection (no manual `content` config needed)
-
- Prefer container queries over viewport queries for true component responsiveness
-
- Use CSS variables from `@theme` for dynamic styling
-
- Leverage the new OKLCH color system for better color consistency
-
-
### Efficient Class Usage
-
```html
-
<!-- Good: Use size-* for square elements -->
-
<div class="size-12"></div>
-
-
<!-- Instead of: -->
-
<div class="w-12 h-12"></div>
-
-
<!-- Good: Use container queries for component responsiveness -->
-
<div class="@container">
-
<div class="p-4 @lg:p-8">Content</div>
-
</div>
-
-
<!-- Good: Use CSS variables for dynamic values -->
-
<div class="bg-[var(--theme-primary)] text-[var(--theme-on-primary)]">
-
Dynamic theming
-
</div>
-
```
-
-
## Framework Integration
-
-
### Svelte 5
-
```svelte
-
<script>
-
let { variant = "primary", children } = $props();
-
-
const buttonClasses = $derived(() => [
-
'px-4 py-2 rounded-md font-medium transition-colors',
-
variant === 'primary'
-
? 'bg-brand text-white hover:bg-brand/90'
-
: 'bg-gray-100 text-gray-900 hover:bg-gray-200'
-
].join(' '));
-
</script>
-
-
<button class={buttonClasses}>
-
{@render children()}
-
</button>
-
-
<style>
-
@import "tailwindcss";
-
-
@theme {
-
--color-brand: oklch(0.5 0.2 240);
-
}
-
</style>
-
```
-
-
## Debugging & Development
-
-
### Browser DevTools Tips
-
1. **Inspect CSS Variables**: Check `:root` in DevTools to see all theme variables
-
2. **Check Cascade Layers**: Use the Layers panel to understand style precedence
-
3. **Verify OKLCH Support**: Test colors in modern browsers vs fallbacks
-
4. **Container Query Debugging**: Use the @container panel in DevTools
-
-
### Common Debug Commands
-
```bash
-
# Check if utilities are being generated
-
npx tailwindcss --watch --content "./src/**/*.{html,js,jsx,ts,tsx}"
-
-
# Verify v4 installation
-
npm list tailwindcss
-
-
# Check for conflicting PostCSS plugins
-
npm list | grep postcss
-
```
-
-
### VS Code Extensions
-
- Tailwind CSS IntelliSense (updated for v4)
-
- PostCSS Language Support
-
-
## v3 to v4 Migration Checklist
-
-
### Pre-Migration
-
- [ ] Backup your project
-
- [ ] Ensure Node.js 20+ is installed
-
- [ ] Check browser support requirements (Safari 16.4+, Chrome 111+, Firefox 128+)
-
-
### Automated Migration
-
```bash
-
npx @tailwindcss/upgrade@next
-
```
-
-
### Manual Verification
-
- [ ] Replace `@tailwind` directives with `@import "tailwindcss"`
-
- [ ] Move `tailwind.config.js` content to CSS `@theme`
-
- [ ] Update deprecated utility classes
-
- [ ] Test container queries functionality
-
- [ ] Verify custom component styles
-
- [ ] Check 3D transform support
-
- [ ] Test mask utilities if used
-
- [ ] Validate color consistency (OKLCH vs RGB)
-
-
### Testing
-
- [ ] Test in all target browsers
-
- [ ] Verify responsive design still works
-
- [ ] Check dark mode functionality
-
- [ ] Test custom animations
-
- [ ] Validate accessibility features
-
-
## Production-Ready Component Patterns
-
-
### Modern Card Component
-
```html
-
<div class="@container group">
-
<article class="
-
bg-white dark:bg-gray-900
-
rounded-xl shadow-sm border border-gray-200 dark:border-gray-800
-
overflow-hidden transition-all duration-200
-
hover:shadow-md hover:-translate-y-0.5
-
@sm:flex @sm:items-center
-
">
-
<div class="@sm:flex-shrink-0">
-
<img class="h-48 w-full object-cover @sm:h-full @sm:w-48" src="..." alt="...">
-
</div>
-
<div class="p-6 @sm:p-8">
-
<h3 class="text-lg font-semibold text-gray-900 dark:text-white @lg:text-xl">
-
Card Title
-
</h3>
-
<p class="mt-2 text-gray-600 dark:text-gray-300 @lg:text-lg">
-
Card description that adapts to container size.
-
</p>
-
</div>
-
</article>
-
</div>
-
```
-
-
### 3D Interactive Button
-
```html
-
<button class="
-
relative px-6 py-3 bg-blue-600 text-white font-medium rounded-lg
-
transform-3d perspective-1000
-
transition-all duration-200
-
hover:rotate-x-12 hover:scale-105 hover:shadow-xl
-
active:scale-95 active:rotate-x-6
-
focus:outline-none focus:ring-2 focus:ring-blue-500/50
-
">
-
3D Button
-
</button>
-
```
-
-
Remember: Tailwind CSS v4 is designed for modern browsers and modern development workflows. Embrace the new CSS-first approach and leverage the powerful new features for better performance and developer experience.
+6 -10
tailwind.opam
···
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "Type-safe Tailwind CSS generation for OCaml"
-
description:
-
"A comprehensive OCaml library for generating Tailwind CSS classes with full type safety"
-
maintainer: ["Your Name"]
-
authors: ["Your Name"]
-
license: "MIT"
-
homepage: "https://github.com/yourusername/tailwind-ocaml"
-
doc: "https://yourusername.github.io/tailwind-ocaml/"
-
bug-reports: "https://github.com/yourusername/tailwind-ocaml/issues"
+
description: "Library for generating Tailwind CSS classes"
+
maintainer: ["Anil Madhavapeddy"]
+
authors: ["Anil Madhavapeddy"]
+
license: "ISC"
depends: [
+
"dune" {>= "3.18"}
"ocaml"
-
"dune" {>= "3.0" & >= "3.0"}
"alcotest" {with-test}
"qcheck" {with-test}
"odoc" {with-doc}
···
"@doc" {with-doc}
]
]
-
dev-repo: "git+https://github.com/yourusername/tailwind-ocaml.git"
+
x-maintenance-intent: ["(latest)"]
+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)));