|
|
---
|
|
|
title: RFC — Eidos structural systems (space · density · scale)
|
|
|
type: rfc
|
|
|
audience: human + agent
|
|
|
status: implemented — the space builder (`buildSpaceScale`/`applySpacing`) landed, and the `applyTheme(seed)` capstone composes it (status corrected 2026-07-07, theming audit C)
|
|
|
source: migrated from src/uix/eidos/STRUCTURE_ENGINE_RFC.md (2026-07-02, docs-book F7.4)
|
|
|
---
|
|
|
|
|
|
# RFC — Eidos structural systems (space · density · scale)
|
|
|
|
|
|
> Sibling of [`rfc-color-engine.md`](./rfc-color-engine.md),
|
|
|
> [`rfc-typography.md`](./rfc-typography.md), [`rfc-depth.md`](./rfc-depth.md) and
|
|
|
> [`rfc-shape.md`](./rfc-shape.md). Takes the **structural** systems to
|
|
|
> reference-grade. Unlike the **expressive** channels (the book's 8), the
|
|
|
> structural is **state-only** — the stage, not the happening. So the novelty
|
|
|
> here is **not eventful**: it is **rhythm**, **fluidity** and **axis
|
|
|
> composition**, under the open cage.
|
|
|
|
|
|
## 0. Thesis
|
|
|
|
|
|
> **Space is not a lookup table of arbitrary pixels; it is a _rhythm_ — derived
|
|
|
> from a base unit, _fluid_ (it breathes with the viewport) and _composed_ with
|
|
|
> density and zoom from a minimal seed.**
|
|
|
|
|
|
Everybody ships a **flat** space scale (`4 · 8 · 12 · 16 · 24…`), **arbitrary**,
|
|
|
**static** and detached from typography. Eidos already has the other two
|
|
|
structural axes —**density** (compactness) and **scaling** (zoom)— above the
|
|
|
average; what's missing is for **space itself** to be rhythm: modular, fluid and
|
|
|
with a runtime builder, as typography already did.
|
|
|
|
|
|
## 1. The survey — how the references do it and where they stop
|
|
|
|
|
|
| Framework | Space | Limit |
|
|
|
|---|---|---|
|
|
|
| **Tailwind** | fixed scale (`0.25rem` × N) | flat, arbitrary, **static** |
|
|
|
| **Material** | `8dp` grid | multiples of 8, static, no fluidity |
|
|
|
| **Radix / Chakra / Mantine** | space tokens | flat static scale; density (if any) = global preset |
|
|
|
| **Bootstrap / Ant / Carbon / Fluent** | spacer scale | same — flat + static |
|
|
|
| **Utopia.fyi** | fluid space (technique) | an **external calculator**, not a token system integrated with density + zoom |
|
|
|
|
|
|
**Common limit**: space is a **flat px scale**, **static** (doesn't breathe with
|
|
|
the viewport), **arbitrary** (derives from nothing), and **disconnected** from
|
|
|
density / zoom as a system. Utopia proved fluid space but as a spreadsheet, not
|
|
|
as a token engine.
|
|
|
|
|
|
## 2. Where Eidos stands today (strong on 2 of 3 axes)
|
|
|
|
|
|
- **Density** — 3 levels (`compact · comfortable · spacious`) × **2 axes**
|
|
|
(`spaceScale` + `controlScale`). Tightens layout without touching text
|
|
|
legibility. ✓ (above average)
|
|
|
- **Scaling** — global zoom `90–110` that scales the px **including typography**
|
|
|
(Radix parity), composing with density. ✓
|
|
|
- **Layout** — containers + padding + breakpoints + aspect-ratios. ✓
|
|
|
- **Composition** — `--space-{key}` is emitted as `calc(value ·
|
|
|
var(--density-space-scale) · var(--scaling))`: density × zoom already compose. ✓
|
|
|
- **BUT space ITSELF** (`STATIC_SPACE`) is **flat, arbitrary** px (base 4,
|
|
|
hand-placed half-steps), **static** (doesn't breathe) and **builder-less** —
|
|
|
unlike type, which has `buildTypeScale` (modular + fluid) + `applyTypeScale`
|
|
|
(runtime). It is the **lagging axis**.
|
|
|
|
|
|
## 3. The novel model — space as rhythm
|
|
|
|
|
|
1. **Modular** — every step = base unit × N (a coherent ladder), not loose px.
|
|
|
2. **Fluid** — `clamp()`: space **breathes with the viewport** (like fluid type —
|
|
|
almost no framework does it for space). Reuses the type scale's `fluidClamp`.
|
|
|
3. **Three orthogonal axes** — **rhythm** (the scale) × **density** (compactness)
|
|
|
× **scaling** (zoom), composed multiplicatively. One minimal seed governs them.
|
|
|
4. **Runtime builder** — `buildSpaceScale(seed)` (pure) + `applySpacing(seed)`
|
|
|
(DOM), sibling of `applyColorScheme` / `applyTypeScale` / `applyDepth` /
|
|
|
`applyShape`. Completes the quintet.
|
|
|
|
|
|
## 3.bis Structural = state-only (no two moments)
|
|
|
|
|
|
Unlike motion / depth / shape, space **does not "happen"**: it is the stage, not
|
|
|
the happening. The **two-moments** model (state vs event) belongs to the
|
|
|
**expressive** channels. Forcing an "eventful space" would be a costume — the
|
|
|
doctrinally honest position is that the novelty here is **rhythm + fluidity +
|
|
|
axis composition**, not eventfulness. (Same rigor: don't invent a moment that
|
|
|
doesn't exist.)
|
|
|
|
|
|
## 4. Doctrine — _strong default, open cage_
|
|
|
|
|
|
| Piece | Strong default | Open door |
|
|
|
|---|---|---|
|
|
|
| **space scale** | authored `STATIC_SPACE` (stable, curated) | `buildSpaceScale` / `applySpacing` = **modular + fluid opt-in** alternative (same stance as `applyTypeScale` over the authored scale) |
|
|
|
| **density** | 3 levels × 2 axes | config-driven + runtime (`[data-density]`) |
|
|
|
| **scaling** | `90–110`, universal factors | runtime (`[data-scaling]`); composes with density |
|
|
|
| **composition** | `calc(value · density · scaling)` | the raw `--space-*` primitives always reachable; the builder **preserves** the composition |
|
|
|
| **whole system** | canonical theme | runtime `applySpacing(seed)` |
|
|
|
|
|
|
## 5. Token contract
|
|
|
|
|
|
```
|
|
|
--space-{key} value · var(--density-space-scale) · var(--scaling) (existing scale — kept)
|
|
|
```
|
|
|
|
|
|
The builder **rewrites the `value`** (managed block) with a modular/fluid one,
|
|
|
**preserving** the `calc(… · density · scaling)` so density and zoom keep
|
|
|
composing. Zero renames → zero breakage.
|
|
|
|
|
|
## 6. Phases
|
|
|
|
|
|
1. **Space builder** — `buildSpaceScale(seed)` (pure: base unit × ladder, fluid
|
|
|
via `fluidClamp`) + `ActiveEidos.applySpacing` / `clearSpacing` (managed block
|
|
|
that preserves `· density · scaling`) + export + test. Opt-in; `STATIC_SPACE`
|
|
|
untouched.
|
|
|
2. **Showcase + docs** — `/temas/estructura` (density × scaling × fluid space,
|
|
|
live) + theming reference §structure + this RFC.
|
|
|
3. ⏸️ (future) **`applyTheme(seed)`** — one seed composing type + space (shared
|
|
|
rhythm).
|
|
|
|
|
|
## 7. Composition with the existing
|
|
|
|
|
|
- **`fluidClamp`** (from the type scale) → fluid space (not reinvented).
|
|
|
- **`calc(value · density · scaling)`** → preserved (density + zoom keep composing).
|
|
|
- **`buildTypeScale`** → the exact pattern `buildSpaceScale` mirrors (seed →
|
|
|
fluid ladder).
|
|
|
- **Box/Flex/Grid/Stack/Container** → consume `--space-*`; untouched.
|
|
|
|
|
|
## 8. Doctrine (parallel to color / typography / depth / shape)
|
|
|
|
|
|
- **Authored scale = stable canon**; the builder = **opt-in** mathematical
|
|
|
alternative (same as typography). The theme retunes, the builder recomposes.
|
|
|
- **Density and scaling = axes orthogonal** to rhythm; the three compose.
|
|
|
- **Open cage**: raw `--space-*` always one step away.
|
|
|
|
|
|
## 9. Out of scope
|
|
|
|
|
|
- **Rigid baseline grid** (pixel-perfect vertical rhythm): modular + fluid rhythm
|
|
|
gives cadence without imposing a rigid grid that fights real content.
|
|
|
- **Reinventing layout**: `Box · Flex · Grid · Stack · Container · AutoGrid`
|
|
|
already cover composition; here we elevate **space**, not the layout primitives.
|