Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f1cb1bf
feat: add WithTransition type for per-value CSS transitions
augyg Feb 19, 2026
59d7918
feat: update BoxConfig background properties to use WithTransition
augyg Feb 19, 2026
d5ae5b2
feat: update border properties to use WithTransition
augyg Feb 19, 2026
f76e8a0
feat: update spacing properties to use WithTransition
augyg Feb 19, 2026
bcbc21b
feat: update sizing properties to use WithTransition
augyg Feb 19, 2026
8afdabb
feat: update ring properties to use WithTransition
augyg Feb 19, 2026
91a388b
feat: add AutoWrap support to setter operators for backwards compatib…
augyg Feb 19, 2026
a48193c
feat: update shorthand type signatures for WithTransition
augyg Feb 19, 2026
2c92acc
chore: expose WithTransition module in cabal file
augyg Feb 19, 2026
67f3410
test: add WithTransition functionality tests
augyg Feb 19, 2026
664ae67
refactor: remove unused AutoWrap typeclass
augyg Feb 19, 2026
e3d3833
feat: use typeclasses for proper type inference in setters
augyg Feb 19, 2026
1d5e406
feat: implement per-attribute transitions with arbitrary Tailwind syntax
augyg Feb 20, 2026
85a6908
test: add comprehensive transition test suite
augyg Feb 20, 2026
300eecf
chore: ignore generated test HTML files
augyg Feb 20, 2026
c6b9bda
fix: remove Chrome auto-open from HTML test
augyg Feb 20, 2026
e6bedab
feat: add complete transform support following Tailwind v3
augyg Feb 20, 2026
38fd541
turn off -Wall for now
augyg Feb 20, 2026
9cdff28
docs: improve README and add documentation guides
augyg Feb 22, 2026
4bd8e19
feat: add type-safe gradient support for bgColor
augyg Feb 22, 2026
54c76a0
test: update existing tests for GradientColor API
augyg Feb 22, 2026
848c0b1
feat: add ColorWithOpacity type for Tailwind /opacity syntax
augyg Feb 23, 2026
cd18dcf
feat: add opacity support to gradients and solid colors
augyg Feb 23, 2026
1b4418a
Refactor ColorWithOpacity as core color type
augyg Feb 23, 2026
896047f
Simplify Gradient types to use ColorWithOpacity
augyg Feb 23, 2026
952d8a5
Propagate ColorWithOpacity to border, text, and ring
augyg Feb 23, 2026
b30ced0
Add opacity tests and update tests for ColorWithOpacity API
augyg Feb 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ cabal.project.local~
db*
*.DS_Store
static.out

# Generated test files
test-output.html
test-transition.html
66 changes: 64 additions & 2 deletions ClasshSS.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ extra-doc-files: CHANGELOG.md
-- extra-source-files:

common warnings
ghc-options: -Wall
ghc-options: -Wall

library
import: warnings
exposed-modules: Classh
Classh.Box
Classh.Box.Border
Classh.Box.DivInt
Classh.Box.Gradient
Classh.Box.Margin
Classh.Box.Padding
Classh.Box.Placement
Expand Down Expand Up @@ -93,7 +94,8 @@ library
Classh.TextPosition.WhiteSpace
Classh.TextPosition.WordBreak
Classh.TextPosition.Wrap

Classh.WithTransition


default-extensions:
OverloadedStrings
Expand All @@ -115,3 +117,63 @@ library
hs-source-dirs: src
ghc-options: -Wall -Werror -O -threaded -fno-show-valid-hole-fits
default-language: Haskell2010

test-suite transition-test
import: warnings
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: TransitionTest.hs
build-depends: base
, ClasshSS
, data-default
, lens
, text
default-language: Haskell2010

test-suite comprehensive-test
import: warnings
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: ComprehensiveTest.hs
build-depends: base
, ClasshSS
, data-default
, lens
, text
default-language: Haskell2010

test-suite generate-html-test
import: warnings
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: GenerateHTMLTest.hs
build-depends: base
, ClasshSS
, data-default
, lens
, text
default-language: Haskell2010

test-suite transform-test
import: warnings
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: TransformTest.hs
build-depends: base
, ClasshSS
, data-default
, lens
, text
default-language: Haskell2010

test-suite gradient-test
import: warnings
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: GradientTest.hs
build-depends: base
, ClasshSS
, data-default
, lens
, text
default-language: Haskell2010
113 changes: 110 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,111 @@
# ClashSS
typify CSS so that Style or Class tags do not overlap in obvious but easy to miss ways
# ClasshSS

Note: use Scrappy for bundled files and fetched files to further detect clashes
Type-safe CSS-in-Haskell built on Tailwind CSS. Generates class strings with compile-time validation.

## Overview

ClasshSS is a library that generates Tailwind CSS class strings in Haskell with compile-time type safety. It provides two main configuration types:

- `BoxConfig` - Element styling (layout, colors, borders, shadows, spacing)
- `TextConfigTW` - Text styling (font, size, weight, color)

The library generates `Text` values containing Tailwind classes. These work with any DOM library (Reflex.Dom, Lucid, Blaze, IHP, etc.).

## Installation

Add to your `.cabal` file:
```cabal
build-depends:
classhss
```

Or with Stack, add to `stack.yaml`:
```yaml
extra-deps:
- classhss-0.1.0.0
```

## Quick Start

```haskell
{-# LANGUAGE TemplateHaskell #-}

import Classh
import Reflex.Dom.Core

-- Simple styled div
myDiv :: DomBuilder t m => m ()
myDiv = elClass "div" $(classh'
[ bgColor .~~ Blue C500
, p .~~ TWSize 4
, br .~~ R_Md
]) $ text "Hello, ClasshSS!"
```

### Four Operators

- `.~~` - Constant value (no responsive, no states)
- `.|~` - Responsive values (mobile-first breakpoints)
- `.~^` - State-based values (hover, focus, active) with transitions
- `.~` - Direct setter (mainly for `custom` field)

## Complete Example

See **[docs/EXAMPLE.md](docs/EXAMPLE.md)** for a comprehensive example showing:
- BoxConfig applied to elements via `classh'`
- TextConfigTW for text styling (via `textS` from reflex-classh)
- TextPosition for text positioning (via `textPosition` from reflex-classh)
- Responsive design with `.|~`
- State-based transitions with `.~^`
- Grid positioning
- Transform composition

## Migrating from Tailwind

If you're familiar with Tailwind CSS, see **[docs/MIGRATION_FROM_TAILWIND.md](docs/MIGRATION_FROM_TAILWIND.md)** for:
- Class name mappings (e.g., `bg-blue-500` → `bgColor .~~ Blue C500`)
- How to translate responsive patterns
- How to translate hover/focus states
- Common migration patterns

## API Documentation

For complete API reference:
- Run `cabal haddock` to generate documentation
- See Haddock comments in source files (especially `src/Classh.hs`)
- The main module Haddock includes the comprehensive example

## Why ClasshSS?

- **Type safety** - Invalid CSS won't compile
- **No conflicts** - Can't accidentally set overlapping properties
- **Responsive by default** - Easy mobile-first design
- **Transitions built-in** - Type-safe hover/focus states
- **Tailwind familiar** - If you know Tailwind, you know ClasshSS

## Important Notes

### Type Separation

You cannot mix `BoxConfig` and `TextConfigTW` in the same `classh'` call. This is enforced by the type system:

```haskell
-- ERROR: Won't compile!
$(classh' [ bgColor .~~ Blue C500, text_color .~~ White ])

-- CORRECT: Separate configs, nested elements
elClass "div" $(classh' [bgColor .~~ Blue C500]) $
textS $(classhText [text_color .~~ White]) "Text"
```

### Avoid Flexbox

ClasshSS recommends using CSS Grid instead of flexbox due to flexbox's non-deterministic sizing behavior. Use the `custom` field only as a last resort.

### The `custom` Field

The `custom` field bypasses type safety and can override type-safe properties. Only use it when absolutely necessary, and place it **first** in your config list so type-safe properties take precedence.

## License

BSD-style
Loading