6.7 KiB
| title | type | audience | status | source |
|---|---|---|---|---|
| RFC — Eidos structural systems (space · density · scale) | rfc | human + agent | partially implemented — phase 1 (space builder) pending | 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-typography.md,rfc-depth.mdandrfc-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–110that scales the px including typography (Radix parity), composing with density. ✓ - Layout — containers + padding + breakpoints + aspect-ratios. ✓
- Composition —
--space-{key}is emitted ascalc(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 hasbuildTypeScale(modular + fluid) +applyTypeScale(runtime). It is the lagging axis.
3. The novel model — space as rhythm
- Modular — every step = base unit × N (a coherent ladder), not loose px.
- Fluid —
clamp(): space breathes with the viewport (like fluid type — almost no framework does it for space). Reuses the type scale'sfluidClamp. - Three orthogonal axes — rhythm (the scale) × density (compactness) × scaling (zoom), composed multiplicatively. One minimal seed governs them.
- Runtime builder —
buildSpaceScale(seed)(pure) +applySpacing(seed)(DOM), sibling ofapplyColorScheme/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
- Space builder —
buildSpaceScale(seed)(pure: base unit × ladder, fluid viafluidClamp) +ActiveEidos.applySpacing/clearSpacing(managed block that preserves· density · scaling) + export + test. Opt-in;STATIC_SPACEuntouched. - Showcase + docs —
/temas/estructura(density × scaling × fluid space, live) + theming reference §structure + this RFC. - ⏸️ (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 patternbuildSpaceScalemirrors (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 · AutoGridalready cover composition; here we elevate space, not the layout primitives.