Atomic CSS
============
[][hackage]
Type-safe, composable CSS utility functions. Inspired by Tailwindcss and Elm-UI
### Write Haskell instead of CSS
Style your html with composable CSS utility functions:
```haskell
el ~ bold . pad 8 $ "Hello World"
```
This renders as the following HTML with embedded CSS utility classes:
```html
Hello World
```
Instead of relying on the fickle cascade, factor and compose styles with the full power of Haskell functions!
```haskell
header = bold
h1 = header . fontSize 32
h2 = header . fontSize 24
page = flexCol . gap 10 . pad 10
example = el ~ page $ do
el ~ h1 $ "My Page"
el ~ h2 $ "Introduction"
el "lorem ipsum..."
```
This approach is inspired by Tailwindcss' [Utility Classes](https://tailwindcss.com/docs/styling-with-utility-classes)
### Intuitive Flexbox Layouts
Create complex layouts with `row`, `col`, `grow`, and `space`
```haskell
holygrail = do
col ~ grow $ do
row "Top Bar"
row ~ grow $ do
col "Left Sidebar"
col ~ grow $ "Main Content"
col "Right Sidebar"
row "Bottom Bar"
```
### Stateful Styles
We can apply utilities when certain states apply. For example, to change the background on hover:
```haskell
button ~ bg Primary . hover (bg PrimaryLight) $ "Hover Me"
```
Media states allow us to create responsive designs
```haskell
el ~ width 100 . media (MinWidth 800) (width 400) $ do
"Big if window > 800"
```
### Embedded CSS
Only the utilities used in a given html fragment are rendered:
>>> renderText $ el ~ bold $ "Hello"
Hello
### Try Example Project with Nix
If you want to get a feel for atomic-css without cloning the project run `nix run github:seanhess/atomic-css` to run the example webserver locally
Import Flake
------------
You can import this flake's overlay to add `atomic-css` to `overriddenHaskellPackages` and which provides a ghc966 and ghc982 package set that satisfy `atomic-css`'s dependencies.
```nix
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
atomic-css.url = "github:seanhess/atomic-css"; # or "path:/path/to/cloned/atomic-css";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, atomic-css, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ atomic-css.overlays.default ];
};
haskellPackagesOverride = pkgs.overriddenHaskellPackages.ghc966.override (old: {
overrides = pkgs.lib.composeExtensions (old.overrides or (_: _: { })) (hfinal: hprev: {
# your overrides here
});
});
in
{
devShells.default = haskellPackagesOverride.shellFor {
packages = p: [ p.atomic-css ];
};
}
);
}
```
Local Development
-----------------
### Recommended ghcid command
If you want to work on both the atomic-css library and example code, this `ghcid` command will run and reload the examples server as you change any non-testing code.
```
ghcid --command="cabal repl exe:example lib:atomic-css" --run=Main.main --warnings --reload=./embed/preflight.css
```
If you want to work on the test suite, this will run the tests each time any library code is changed.
```
ghcid --command="cabal repl test lib:atomic-css" --run=Main.main --warnings --reload=./embed/preflight.css
```
### Nix
- `nix flake check` will build the library, example executable and devShell with ghc-9.8.2 and ghc-9.6.6
- This is what the CI on GitHub runs
- `nix run` or `nix run .#ghc982-example` to start the example project with GHC 9.8.2
- `nix run .#ghc966-example` to start the example project with GHC 9.6.6
- `nix develop` or `nix develop .#ghc982-shell` to get a shell with all dependencies installed for GHC 9.8.2.
- `nix develop .#ghc966-shell` to get a shell with all dependencies installed for GHC 9.6.6.
- `nix build`, `nix build .#ghc982-atomic-css` and `nix build .#ghc966-atomic-css` builds the library with the `overriddenHaskellPackages`
- If you want to import this flake, use the overlay
- `nix flake update nixpkgs` will update the Haskell package sets and development tools
### Common Nix Issues
#### Not Allowed to Refer to GHC
If you get an error like:
```
error: output '/nix/store/64k8iw0ryz76qpijsnl9v87fb26v28z8-my-haskell-package-1.0.0.0' is not allowed to refer to the following paths:
/nix/store/5q5s4a07gaz50h04zpfbda8xjs8wrnhg-ghc-9.6.3
```
Follow these [instructions](https://nixos.org/manual/nixpkgs/unstable/#haskell-packaging-helpers)
#### Dependencies Incorrect
You will need to update the overlay, look for where it says `"${packageName}" = hfinal.callCabal2nix packageName src { };` and add a line like `Diff = hfinal.callHackage "Diff" "0.5" { };` with the package and version you need.
#### Missing Files
Check the `include` inside the `nix-filter.lib` to see if all files needed by cabal are there.
Learn More
----------
View Documentation on [Hackage][hackage]
* https://hackage.haskell.org/package/atomic-css
View on Github
* https://github.com/seanhess/atomic-css
View [Examples](https://github.com/seanhess/atomic-css/blob/latest/example/app/Main.hs)
[hackage]: https://hackage.haskell.org/package/atomic-css
Contributors
------------
* [Sean Hess](https://github.com/seanhess)
* [Kamil Figiela](https://github.com/kfigiela)
* [Pfalzgraf Martin](https://github.com/Skyfold)