Skip to content

Commit 25a5ef5

Browse files
committed
docs: update fuz-stack patterns
1 parent 301e363 commit 25a5ef5

File tree

10 files changed

+315
-104
lines changed

10 files changed

+315
-104
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"@fuzdev/fuz_code": "^0.45.1",
2626
"@fuzdev/fuz_css": "^0.58.0",
2727
"@fuzdev/fuz_ui": "^0.191.4",
28-
"@fuzdev/fuz_util": "^0.55.0",
28+
"@fuzdev/fuz_util": "^0.56.0",
2929
"@fuzdev/gro": "^0.197.3",
3030
"@jridgewell/trace-mapping": "^0.3.31",
3131
"@ryanatkn/eslint-config": "^0.10.1",

skills/fuz-stack/SKILL.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,8 @@ file's location on disk.
388388
Tests live in `src/test/` (NOT co-located). Use `assert` from vitest —
389389
choose methods for TypeScript type narrowing, not semantic precision.
390390
`assert(x instanceof Error)` narrows the type;
391-
`expect(x).toBeInstanceOf(Error)` does not. Some repos have legacy `expect`
392-
usage — prefer `assert` in new code and migrate opportunistically. Name
393-
custom assertion helpers `assert_*` (not `expect_*`).
391+
`expect(x).toBeInstanceOf(Error)` does not. Name custom assertion helpers
392+
`assert_*` (not `expect_*`).
394393

395394
Use `describe` blocks to organize tests — one or two levels deep is typical.
396395
Use `test()` (not `it()`).
@@ -428,6 +427,15 @@ TaskContext, error handling, override patterns, and task composition.
428427
See ./references/css-patterns.md for setup, variables, composites, modifiers,
429428
extraction, and dynamic theming.
430429

430+
**Minimal component styles**: Components should have minimal or zero custom CSS,
431+
delegating to fuz_css utilities and design tokens. Use `box`/`row`/`column`
432+
for layout, token classes for spacing/colors, and `<style>` only for
433+
component-specific logic (positioning, pseudo-states, responsive breakpoints).
434+
See css-patterns.md §Component Styling Philosophy for the full guide.
435+
436+
**Class naming**: fuz_css tokens use `snake_case` (`p_md`, `gap_lg`).
437+
Component-local classes use `kebab-case` (`site-header`, `nav-links`).
438+
431439
### 3-Layer Architecture
432440

433441
| Layer | File | Purpose |
@@ -449,13 +457,13 @@ extraction, and dynamic theming.
449457

450458
### When to Use Classes vs Styles
451459

452-
| Need | Style tag | Utility class | Inline style |
453-
| ---------------------- | --------- | ------------- | ------------ |
454-
| Style own elements | **Best** | OK | OK |
455-
| Style child components | No | **Yes** | Limited |
456-
| Hover/focus/responsive | Yes | **Yes** | No |
457-
| Runtime dynamic values | No | No | **Yes** |
458-
| IDE autocomplete | **Yes** | No | Partial |
460+
| Need | Utility class | Style tag | Inline style |
461+
| ---------------------- | ------------- | --------- | ------------ |
462+
| Style own elements | **Preferred** | Complex cases | OK |
463+
| Style child components | **Yes** | No | Limited |
464+
| Hover/focus/responsive | **Yes** | Yes | No |
465+
| Runtime dynamic values | No | No | **Yes** |
466+
| IDE autocomplete | No | **Yes** | Partial |
459467

460468
## Dependency Injection
461469

skills/fuz-stack/references/css-patterns.md

Lines changed: 152 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -433,15 +433,156 @@ are arrays of `StyleVariable` overrides. Theme CSS rendered via
433433
`render_theme_style()` with higher specificity (default `:root:root`) to
434434
override bundled theme variables regardless of CSS insertion order.
435435

436+
## Component Styling Philosophy
437+
438+
The fuz stack's core styling principle: **components should have minimal custom
439+
CSS, delegating styling to fuz_css**. Most components need zero or near-zero
440+
lines in their `<style>` block. The design system exists so components don't
441+
reinvent layout, spacing, color, or typography.
442+
443+
### What "Minimal Styles" Looks Like
444+
445+
Well-designed fuz components (fuz_ui, zzz, fuz_code, fuz_gitops) share these
446+
traits:
447+
448+
- **Many components have no `<style>` block at all** — all styling comes from
449+
utility classes and semantic HTML
450+
- **When `<style>` exists, it's 5-30 lines** — only component-specific layout
451+
logic (positioning, complex pseudo-states, responsive breakpoints)
452+
- **All colors, spacing, typography come from design tokens** — never hardcoded
453+
values
454+
- **Layout uses composites and utilities**`box`, `row`, `column`, `panel`,
455+
`p_md`, `gap_lg` instead of manual flex declarations
456+
457+
```svelte
458+
<!-- GOOD: No <style> block needed — utility classes handle everything -->
459+
<div class="column gap_md p_lg">
460+
<header class="row gap_sm">
461+
<h2>{title}</h2>
462+
<small class="text_50">{subtitle}</small>
463+
</header>
464+
<div class="panel p_md">{@render children()}</div>
465+
</div>
466+
```
467+
468+
### Anti-Patterns
469+
470+
These patterns indicate a component is doing too much styling work:
471+
472+
#### Writing flex layout in `<style>` instead of using composites
473+
474+
```svelte
475+
<!-- BAD: manual flex in <style> -->
476+
<div class="container">...</div>
477+
<div class="header">...</div>
478+
<style>
479+
.container { display: flex; flex-direction: column; gap: var(--space_md); }
480+
.header { display: flex; align-items: center; }
481+
</style>
482+
483+
<!-- GOOD: utility classes -->
484+
<div class="column gap_md">...</div>
485+
<div class="row">...</div>
486+
```
487+
488+
#### Referencing design tokens in `<style>` when a utility class exists
489+
490+
```svelte
491+
<!-- BAD: token reference in <style> for something a class does -->
492+
<span class="subtitle">...</span>
493+
<style>
494+
.subtitle { color: var(--text_70); font-size: var(--font_size_sm); }
495+
</style>
496+
497+
<!-- GOOD: utility classes (or semantic HTML) -->
498+
<small class="text_70">...</small>
499+
```
500+
501+
#### Repeating the same layout patterns across components
502+
503+
If multiple components each define their own `.sidebar`, `.header`,
504+
`.content` classes with the same flex/padding/border patterns, those
505+
should be utility classes, project `style.css` classes, or composites.
506+
507+
#### Hardcoding pixel values
508+
509+
```svelte
510+
<!-- BAD: hardcoded pixels -->
511+
<style>
512+
.sidebar { width: 220px; padding-top: 40px; }
513+
</style>
514+
515+
<!-- GOOD: design tokens or CSS custom properties -->
516+
<style>
517+
.sidebar { width: var(--sidebar_width); padding-top: var(--space_xl2); }
518+
</style>
519+
```
520+
521+
### When Custom CSS IS Justified
522+
523+
Custom `<style>` blocks are appropriate for:
524+
525+
- **Complex interactive states** — multi-property hover/active/selected
526+
combinations, especially with `color-mix` shadows or parent-child selectors
527+
like `.parent:hover .child`. Examples: tab shadow state machines,
528+
hover-to-reveal controls.
529+
- **Structural behavior**`flex-direction: column-reverse` for bottom-up
530+
scrolling, `position: sticky/absolute/fixed` with calculated offsets
531+
- **Responsive layouts**`@media` queries for structural layout changes
532+
- **Animations/transitions**`@keyframes`, `transition` definitions
533+
- **Rendering contexts** — canvas, 3D, or other surfaces with inherently
534+
custom layout
535+
536+
Even justified custom CSS should use design tokens (`var(--space_md)`,
537+
`var(--border_color)`) rather than hardcoded values.
538+
539+
### Project `style.css` for Shared App Patterns
540+
541+
When a pattern recurs across multiple components in one app but isn't
542+
general enough for fuz_css, put it in the project's `style.css` (e.g.,
543+
`src/routes/style.css`). This is the right place for app-scoped shared
544+
classes — button variants, layout columns, drag indicators, scroll
545+
shadows, etc.
546+
547+
Mark patterns with `// TODO upstream` if they might belong in fuz_css.
548+
This keeps component `<style>` blocks focused on truly component-specific
549+
logic while avoiding premature generalization into the design system.
550+
551+
### Class Naming Conventions
552+
553+
Two naming systems coexist:
554+
555+
- **fuz_css design tokens**: `snake_case``p_md`, `color_a_50`, `gap_lg`,
556+
`font_size_sm`. These are the global vocabulary.
557+
- **Component-local classes**: `kebab-case``nav-separator`, `edit-sidebar`,
558+
`character-entry`. Distinguishes component-scoped styles from design
559+
system classes at a glance.
560+
561+
```svelte
562+
<!-- snake_case = fuz_css utility, kebab-case = component-local -->
563+
<div class="column gap_md site-header">
564+
<nav class="row gap_sm nav-links">...</nav>
565+
</div>
566+
567+
<style>
568+
.site-header { position: sticky; top: 0; z-index: 10; }
569+
.nav-links { border-bottom: var(--border_width_1) var(--border_style) var(--border_color); }
570+
</style>
571+
```
572+
573+
This convention is aspirational — existing components use `snake_case` for
574+
component-local classes too. A cross-repo audit will migrate to kebab-case
575+
over time.
576+
436577
## When to Use Classes vs Styles
437578

438-
| Need | Style tag | Utility class | Inline style |
439-
| ---------------------- | --------- | ------------- | ------------ |
440-
| Style own elements | **Best** | OK | OK |
441-
| Style child components | No | **Yes** | Limited |
442-
| Hover/focus/responsive | Yes | **Yes** | No |
443-
| Runtime dynamic values | No | No | **Yes** |
444-
| IDE autocomplete | **Yes** | No | Partial |
579+
| Need | Utility class | Style tag | Inline style |
580+
| ---------------------- | ------------- | --------- | ------------ |
581+
| Style own elements | **Preferred** | Complex cases | OK |
582+
| Style child components | **Yes** | No | Limited |
583+
| Hover/focus/responsive | **Yes** | Yes | No |
584+
| Runtime dynamic values | No | No | **Yes** |
585+
| IDE autocomplete | No | **Yes** | Partial |
445586

446587
### Rules of Thumb
447588

@@ -453,8 +594,10 @@ override bundled theme variables regardless of CSS insertion order.
453594
and colors (`color_a_50`) maintain consistency; avoid hardcoded values
454595
- **Inline `style:prop` for runtime values** — dynamic widths, computed
455596
colors, CSS variable overrides
456-
- **Keep class strings manageable** — if a `<div>` accumulates 5+ utility
457-
classes, consider a `<style>` rule
597+
- **Utility class strings are fine at length** — 6-12 classes per element is
598+
common and works well. Only move to `<style>` when readability suffers
599+
(complex responsive logic, multi-property pseudo-elements) not just because
600+
the class list is long
458601
- **`<style>` for responsive layouts**`@media` queries in component styles
459602
are conventional; reserve responsive modifiers for simple one-off overrides
460603

skills/fuz-stack/references/rust-patterns.md

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Rust Patterns for the Fuz Ecosystem
22

33
**Applies to**: `fuz` (daemon + CLI), `tsv` (parser/formatter), `blake3` (WASM
4-
bindings). All projects use **Rust edition 2024**, resolver 2.
4+
bindings), `zzz_server` (axum web server). All projects use **Rust edition
5+
2024**, resolver 2.
56

67
Each project's `CLAUDE.md` is authoritative for project-specific conventions.
78
This covers shared patterns.
@@ -355,23 +356,31 @@ without explicit request.
355356

356357
### Shared
357358

358-
| Crate | Purpose | Used by |
359-
| --------------------- | ---------------- | ---------------------------------- |
360-
| `serde`, `serde_json` | Serialization | fuz, tsv (blake3 bench crate only) |
361-
| `thiserror` | Error derivation | fuz, tsv |
359+
| Crate | Purpose | Used by |
360+
| ---------------------------------- | ------------------ | ---------------------------------- |
361+
| `serde`, `serde_json` | Serialization | fuz, tsv, zzz_server (blake3 bench crate only) |
362+
| `thiserror` | Error derivation | fuz, tsv, zzz_server |
363+
| `tracing`, `tracing-subscriber` | Structured logging | fuz, zzz_server |
362364

363365
### Domain-specific
364366

365-
**Async / networking** (fuz):
367+
**Async / networking** (fuz, zzz_server):
366368

367369
| Crate | Purpose |
368370
| ------------- | ------------------------------ |
369371
| `tokio` | Async runtime |
370372
| `axum` | HTTP server (built on hyper) |
371-
| `reqwest` | HTTP client |
373+
| `reqwest` | HTTP client (fuz only) |
372374
| `tokio-util` | CancellationToken, TaskTracker |
373375
| `parking_lot` | Faster mutex (no poisoning) |
374376

377+
**Database** (zzz_server):
378+
379+
| Crate | Purpose |
380+
| -------------------- | ------------------------------ |
381+
| `tokio-postgres` | Async PostgreSQL client |
382+
| `deadpool-postgres` | Connection pooling |
383+
375384
**Parsing** (tsv):
376385

377386
| Crate | Purpose |
@@ -447,10 +456,14 @@ O(log n) binary search on span positions.
447456
- **Secure file permissions**: `0o600` for files, `0o700` for directories
448457
- **Environment isolation**: Strip sensitive env vars before spawning sidecars
449458

450-
### Logging (fuz)
459+
### Logging
460+
461+
**Servers** (zzz_server): `tracing` with `tracing-subscriber` for structured
462+
logging. axum integrates with `tracing` natively. Use `tracing::info!`,
463+
`tracing::error!`, etc.
451464

452-
No tracing framework — `eprintln!` for daemon and CLI. Batched request logging
453-
for performance. `--json` for machine-readable output.
465+
**CLIs / daemons** (fuz, tsv): `eprintln!` — simple, no framework. Batched
466+
request logging for performance. `--json` for machine-readable output.
454467

455468
## Documentation
456469

skills/fuz-stack/references/svelte-patterns.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,19 @@ Avoid destructuring if you need to mutate the item (e.g.,
11411141

11421142
## CSS in Components
11431143

1144+
**Goal: minimal `<style>` blocks.** Components should delegate styling to
1145+
fuz_css utility classes and design tokens. Many well-designed components
1146+
have no `<style>` block at all. See `css-patterns.md` §Component Styling
1147+
Philosophy for the full rationale, anti-patterns, and examples.
1148+
1149+
When a `<style>` block is needed, keep it focused on component-specific
1150+
layout logic (positioning, complex pseudo-states, responsive breakpoints).
1151+
All values should reference design tokens, not hardcoded pixels or colors.
1152+
1153+
**Class naming**: fuz_css utilities use `snake_case` (`p_md`, `gap_lg`).
1154+
Component-local classes use `kebab-case` (`site-header`, `nav-links`) to
1155+
distinguish them visually.
1156+
11441157
### JS Variables in CSS
11451158

11461159
Use `style:` directive to pass JS values as CSS custom properties:

0 commit comments

Comments
 (0)