Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
9b4abd2
wip
ryanatkn Jan 7, 2026
73b6f72
wip
ryanatkn Jan 7, 2026
fc67e19
wip
ryanatkn Jan 7, 2026
95a7988
wip
ryanatkn Jan 7, 2026
f4d51f2
wip
ryanatkn Jan 7, 2026
b9b10c6
wip
ryanatkn Jan 7, 2026
9b38dbc
wip
ryanatkn Jan 7, 2026
e86095b
wip
ryanatkn Jan 7, 2026
40024e4
wip
ryanatkn Jan 7, 2026
1057f8d
wip
ryanatkn Jan 7, 2026
4b6e511
wip
ryanatkn Jan 7, 2026
9f23206
wip
ryanatkn Jan 8, 2026
49e3e3d
wip
ryanatkn Jan 8, 2026
2053e35
wip
ryanatkn Jan 8, 2026
0444dc5
wip
ryanatkn Jan 8, 2026
eb535dc
wip
ryanatkn Jan 8, 2026
c892ae1
wip
ryanatkn Jan 9, 2026
c6819bc
wip
ryanatkn Jan 9, 2026
31b64f4
wip
ryanatkn Jan 9, 2026
8204ccc
wip
ryanatkn Jan 10, 2026
2f78568
wip
ryanatkn Jan 10, 2026
c4fbc10
wip
ryanatkn Jan 10, 2026
48ffaf1
wip
ryanatkn Jan 10, 2026
0c420b5
wip
ryanatkn Jan 10, 2026
1a71c7c
wip
ryanatkn Jan 10, 2026
980454b
wip
ryanatkn Jan 10, 2026
a896b66
wip
ryanatkn Jan 10, 2026
6419521
wip
ryanatkn Jan 10, 2026
97894a4
wip
ryanatkn Jan 10, 2026
29d14e4
wip
ryanatkn Jan 10, 2026
341b327
wip
ryanatkn Jan 11, 2026
cb87983
wip
ryanatkn Jan 11, 2026
1c252d6
wip
ryanatkn Jan 11, 2026
7b787e6
wip
ryanatkn Jan 11, 2026
1816167
wip
ryanatkn Jan 11, 2026
4d9043b
wip
ryanatkn Jan 11, 2026
a5ecec9
wip
ryanatkn Jan 11, 2026
6cf44c5
wip
ryanatkn Jan 11, 2026
cb5d026
wip
ryanatkn Jan 11, 2026
4d84f7c
wip
ryanatkn Jan 11, 2026
f54017a
wip
ryanatkn Jan 11, 2026
5258449
wip
ryanatkn Jan 11, 2026
34f9d6b
wip
ryanatkn Jan 11, 2026
2010177
wip
ryanatkn Jan 11, 2026
5134a8e
wip
ryanatkn Jan 11, 2026
3bab96b
wip
ryanatkn Jan 11, 2026
5d841ce
wip
ryanatkn Jan 11, 2026
22e7db1
wip
ryanatkn Jan 11, 2026
ee73a34
wip
ryanatkn Jan 12, 2026
00c85b1
wip
ryanatkn Jan 12, 2026
329a2e9
wip
ryanatkn Jan 12, 2026
1ebfd01
wip
ryanatkn Jan 12, 2026
df411d9
wip
ryanatkn Jan 12, 2026
73ab8c5
wip
ryanatkn Jan 12, 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
5 changes: 5 additions & 0 deletions .changeset/empty-knives-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fuzdev/fuz_css': minor
---

implement CSS literal classes
17 changes: 9 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# Deps
node_modules
node_modules/

# Output
/.svelte-kit
/build
/dist
/dist_*
/target
/.gro
/.zzz
.svelte-kit/
build/
dist/
dist_*/
target/
.gro/
.fuz/
.zzz/

# Env
.env*
Expand Down
53 changes: 46 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
# Fuz CSS framework and design system

CSS framework and design system built around **semantic styles** and **style variables** (design tokens as CSS custom properties). Early alpha with breaking changes ahead.
CSS framework and design system built on **semantic styles** and **style variables** (design tokens as CSS custom properties). Early alpha with breaking changes ahead.

For code style, see the `fuz-stack` skill. For UI components (themes, color scheme controls), see `@fuzdev/fuz_ui`.

## Gro commands

```bash
gro check # typecheck, test, lint, format check (run before committing)
gro typecheck # typecheck only (faster iteration)
gro test # run tests with vitest
gro gen # regenerate theme.css and other .gen files
gro build # build the package for production
```

## Design decisions

### Two core concepts
Expand All @@ -26,7 +36,24 @@ For code style, see the `fuz-stack` skill. For UI components (themes, color sche

### Smart utility class generation

[gen_fuz_css.ts](src/lib/gen_fuz_css.ts) scans source files with regex extractors, collects class names, and outputs only CSS for classes actually used. Dynamic [interpreters](src/lib/css_class_interpreters.ts) handle pattern-based classes like `opacity_50`, `font_weight_700`, `z_index_100`.
[gen_fuz_css.ts](src/lib/gen_fuz_css.ts) scans source files with AST-based extraction ([css_class_extractor.ts](src/lib/css_class_extractor.ts)), collects class names, and outputs only CSS for classes actually used. Supports Svelte 5.16+ class syntax (`class={[...]}`, `class={{...}}`), clsx/cn calls, and `// @fuz-classes` comment hints.

### Three class types

- **Token classes** - Map to style variables: `p_md`, `color_a_5`, `gap_lg`
- **Composite classes** - Multi-property shortcuts: `box`, `row`, `ellipsis`
- **Literal classes** - CSS `property:value` syntax: `display:flex`, `opacity:50%`

All class types support modifiers: responsive (`md:`), state (`hover:`), color-scheme (`dark:`), pseudo-element (`before:`).

### CSS-literal syntax

Literal classes use `property:value` syntax that maps 1:1 to CSS:
- `display:flex` → `display: flex;`
- `hover:opacity:80%` → `:hover { opacity: 80%; }`
- `md:dark:hover:opacity:80%` → nested media/ancestor/state wrappers

Space encoding uses `~` for multi-value properties (`margin:0~auto`). Arbitrary breakpoints via `min-width(800px):` and `max-width(600px):`.

## Variable naming

Expand Down Expand Up @@ -62,14 +89,22 @@ Import [style.css](src/lib/style.css) + [theme.css](src/lib/theme.css) for base
- [theme.ts](src/lib/theme.ts) - Theme rendering, `ColorScheme` type, `render_theme_style()`
- [themes.ts](src/lib/themes.ts) - Theme definitions (base, low/high contrast)

**CSS extraction:**

- [css_class_extractor.ts](src/lib/css_class_extractor.ts) - AST-based class extraction from Svelte/TS files, `SourceLocation`, `ExtractionResult`

**CSS generation:**

- [gen_fuz_css.ts](src/lib/gen_fuz_css.ts) - Main generator API for Gro
- [css_classes.ts](src/lib/css_classes.ts) - All static class definitions (~1000+)
- [gen_fuz_css.ts](src/lib/gen_fuz_css.ts) - Main generator API for Gro, includes per-file caching with content hash validation
- [css_cache.ts](src/lib/css_cache.ts) - Cache infrastructure for incremental extraction (`.fuz/cache/css/`)
- [css_class_generation.ts](src/lib/css_class_generation.ts) - `CssClasses` collection, `generate_classes_css()`, `CssClassInterpreterContext`, CSS escaping
- [css_classes.ts](src/lib/css_classes.ts) - Token class definitions (spacing, sizing, colors, typography, borders, shadows)
- [css_class_generators.ts](src/lib/css_class_generators.ts) - Class template generation functions
- [css_class_composites.ts](src/lib/css_class_composites.ts) - Composite classes (`.box`, `.row`, `.column`, `.ellipsis`)
- [css_class_interpreters.ts](src/lib/css_class_interpreters.ts) - Dynamic interpreters for opacity, font-weight, z-index, border-radius
- [css_class_helpers.ts](src/lib/css_class_helpers.ts) - CSS class extraction, `CssClasses` collection, `generate_classes_css()`
- [css_class_interpreters.ts](src/lib/css_class_interpreters.ts) - Two interpreters: `modified_class_interpreter` (handles `hover:box`, `md:p_lg`) and `css_literal_interpreter` (handles `display:flex`)
- [css_literal.ts](src/lib/css_literal.ts) - CSS-literal parser, validator, `extract_and_validate_modifiers()`
- [css_ruleset_parser.ts](src/lib/css_ruleset_parser.ts) - CSS ruleset parsing via Svelte's parser, selector modification for modifiers
- [modifiers.ts](src/lib/modifiers.ts) - Declarative modifier definitions (breakpoints, states, pseudo-elements)

**Stylesheets:**

Expand All @@ -86,4 +121,8 @@ Import [style.css](src/lib/style.css) + [theme.css](src/lib/theme.css) for base
### Tests - [src/test/](src/test/)

- [variables.test.ts](src/test/variables.test.ts) - Variable consistency (no duplicates, valid names)
- [css_class_helpers.test.ts](src/test/css_class_helpers.test.ts) - CSS extraction from Svelte/JS patterns
- [css_cache.test.ts](src/test/css_cache.test.ts) - Cache save/load, version invalidation, atomic writes
- [css_class_generation.test.ts](src/test/css_class_generation.test.ts) - CSS escaping, generation, interpreters, CssClasses
- [css_class_extractor.test.ts](src/test/css_class_extractor.test.ts) - AST extraction, location tracking
- [css_literal.test.ts](src/test/css_literal.test.ts) - CSS-literal parsing, validation, modifiers
- [css_ruleset_parser.test.ts](src/test/css_ruleset_parser.test.ts) - Ruleset parsing, selector modification
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

[<img src="/static/logo.svg" alt="a fuzzy tuft of green moss" align="right" width="192" height="192">](https://css.fuz.dev/)

> CSS framework and design system 🌿 magical organic stylesheets
> CSS framework and design system 🌿 CSS with more utility

Fuz CSS is a CSS framework and design system built around semantic styles and style variables.
It's in early alpha with breaking changes ahead.

- view the [docs](https://css.fuz.dev/docs) at [css.fuz.dev](https://css.fuz.dev/)
- help with feedback and design in the [issues](https://github.com/fuzdev/fuz_css/issues)
and [discussions](https://github.com/fuzdev/fuz_css/discussions)
- more about the stack at [fuz.dev](https://www.fuz.dev/)
View the [docs](https://css.fuz.dev/docs) at [css.fuz.dev](https://css.fuz.dev/).
More about the stack at [fuz.dev](https://www.fuz.dev/)

Interested in helping? We welcome feedback and design input in
the [issues](https://github.com/fuzdev/fuz_css/issues)
and [discussions](https://github.com/fuzdev/fuz_css/discussions).

## License [🐦](https://wikipedia.org/wiki/Free_and_open-source_software)

Expand Down
95 changes: 74 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 25 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@fuzdev/fuz_css",
"version": "0.43.0",
"description": "CSS framework and design system",
"motto": "magical organic stylesheets",
"motto": "CSS with more utility",
"glyph": "🌿",
"logo": "logo.svg",
"logo_alt": "a fuzzy tuft of green moss",
Expand Down Expand Up @@ -30,25 +30,44 @@
"node": ">=22.15"
},
"peerDependencies": {
"@fuzdev/fuz_util": ">=0.42.0"
"@fuzdev/fuz_util": ">=0.42.0",
"@sveltejs/acorn-typescript": "^1",
"@webref/css": "^8",
"acorn-jsx": "^5",
"zimmerframe": "^1"
},
"peerDependenciesMeta": {
"@fuzdev/fuz_util": {
"optional": true
},
"@sveltejs/acorn-typescript": {
"optional": true
},
"@webref/css": {
"optional": true
},
"acorn-jsx": {
"optional": true
},
"zimmerframe": {
"optional": true
}
},
"devDependencies": {
"@changesets/changelog-git": "^0.2.1",
"@fuzdev/fuz_code": "^0.38.0",
"@fuzdev/fuz_code": "^0.39.0",
"@fuzdev/fuz_ui": "^0.177.0",
"@fuzdev/fuz_util": "^0.45.1",
"@fuzdev/fuz_util": "^0.45.3",
"@ryanatkn/eslint-config": "^0.9.0",
"@ryanatkn/gro": "^0.184.0",
"@ryanatkn/gro": "^0.185.0",
"@sveltejs/acorn-typescript": "^1.0.8",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.49.1",
"@sveltejs/package": "^2.5.7",
"@sveltejs/vite-plugin-svelte": "^6.2.1",
"@types/node": "^24.10.1",
"@webref/css": "^8.1.3",
"acorn-jsx": "^5.3.2",
"eslint": "^9.39.1",
"eslint-plugin-svelte": "^3.13.1",
"prettier": "^3.7.4",
Expand All @@ -59,6 +78,7 @@
"typescript": "^5.9.3",
"typescript-eslint": "^8.48.1",
"vitest": "^4.0.15",
"zimmerframe": "^1.1.4",
"zod": "^4.1.13"
},
"prettier": {
Expand Down
Loading
Loading