spec: buiy-layout-design (multi-file folder)#27
Merged
Conversation
Graduates the buiy-layout-design slot from the foundation roadmap
(specs/2026-05-07-buiy-foundation/README.md § 4) into a 9-file sub-spec
covering the full layout feature inventory in foundation visuals.md § 3.2.
Files:
- README.md — purpose, scope, sub-spec
roadmap, open questions
- architecture.md — Taffy bridge, hybrid Style
builder + decomposed
components, 8-step system
pipeline, LayoutTree GC,
topological invariant,
error model
- box-model.md — sizing, units, intrinsic
keywords, logical aliases,
Calc
- display-and-positioning.md — Display enum, Position kinds,
anchor positioning as
post-Taffy overlay pass
- flex-and-grid.md — Flex/Grid via Taffy +
multi-column, subgrid +
masonry status
- container-queries-and-writing-modes.md — same-frame re-layout (B)
container-query strategy;
writing-mode + direction +
text-orientation
- overflow-and-scrolling.md — overflow modes, scroll snap,
scrollbar styling
- stacking-and-top-layer.md — stacking-context formation,
z-index, top-layer escape
- transforms-and-containment.md — transform/translate/rotate/
scale longhands, contain,
content-visibility,
will-change
Architectural decisions (with runners-up rejected):
- Hybrid component API. Ergonomic Style builder — struct-literal AND
fluent form over the same fields — expands on insert into a Bundle
of small public-fielded decomposed components (BoxModel, Display,
Position, FlexParams/Item, GridParams/Item, Container, WritingMode,
Overflow, Scroll, Stacking, Transform, Containment, Anchor). The
decomposed components are canonical for ECS storage, BSN authoring,
and reflection. Rejected: pure-decomposed-only (loses spawn
ergonomics); mega-Style (violates project convention, foundation
goal #1.3 / issue #19).
- Anchor positioning: post-Taffy overlay pass. Buiy extends Taffy where
Taffy doesn't ship a feature; we never patch Taffy's algorithm.
Rejected: Taffy-integrated (requires upstream change); defer entirely
(loses tier-C feature).
- Container queries: same-frame re-layout, capped at 2× Taffy on
activation-flip frames. Rejected: one-frame-stale (A — saves perf
nobody is paying anyway, glitches on dramatic resizes); fixed-point
iteration (C — variable cost, debugging-hostile).
- Target-only voice. Phase 0 baseline + migration steps live in plans,
not the spec — keeps spec long-lived as Phase 0 catches up.
Rejected: per-section Phase 0 callouts (rot quickly).
- 9-file folder mirrors foundation/'s child structure. Rejected: single
file (1500-line wall); 14-file mirror of §3.2 verbatim (over-granular).
- Crate placement deferred to foundation README § 5 (open). This spec
works with either buiy_core or a future buiy_layout split.
Catalog: adds "Layout" area to docs/README.md.
https://claude.ai/code/session_01W662m44p1p5Xy57oEXxKg1
Fold the 9 material issues + 1 suggestion from the independent code- reviewer pass into the spec. Material fixes: - Display enum: add Default derive + #[default] = Block. Display had a manual `impl Default` which would clash with #[reflect(Default)]. - ContainerQuery: add Default derive + #[reflect(Default)]. Was the only component in the spec missing the project-convention derive set. - Edges::ZERO: spell out all four fields explicitly. Struct-update syntax `..` requires a const base which Default::default() isn't. - Overflow: scroll_behavior + overscroll_x/overscroll_y were referenced in prose but missing from the struct definition. Add them. - ZIndex::Layer doc comment: clarify it forms a stacking context only when Position::Kind != Static (CSS quirk). - stacking-context formation rule #1: rewrite without inline self- correction. Future readers were copying the wrong rule. - Pipeline numbering: replace ad-hoc "step 5b/5c" notation with named sub-passes 6a/6b/6c/6d under a single PostTaffyOverrides phase. Sub-passes are sticky, table, multi-column, anchor — independent and composed in declared order. - SyncStyles change-detection trigger set: enumerate the Or<Changed<X>> query explicitly. Previously hand-waved as "any tracked layout component"; now states the 18-component union including hierarchy triggers (Children, ChildOf) and the cache-invalidation contract for WritingModeResolved + ContainingBlock. - FlexAxis / FlexWrap / JustifyContent / AlignItems / AlignContent / FlexGap: add explicit enum definitions in flex-and-grid.md. Were referenced from FlexParams + Display::Flex(_) without being defined. Suggestion fixes: - ContainFlags + Reflect: bitflags! macro doesn't compose with #[derive(Reflect)]. Use impl_reflect_value! after the macro. Skipped: - Test-surface assertion mechanism (stylistic; tests will pin the mechanism when the realizing crate lands). - foundation/verification.md anchor (target file lacks a stable anchor for "CI gates"; link points at file root, prose names the section). Initial spec: 9b8f5a5. https://claude.ai/code/session_01W662m44p1p5Xy57oEXxKg1
Three independent reviewers passed over the spec. This commit folds in
every material issue across all three reviews.
Critical (compile/contradiction):
- `Display` enum had a manual `impl Default` AND `#[derive(... Default)]`
with `#[default] Block` — won't compile as shown. Removed the manual
impl; the derive form already covers it.
- display-and-positioning.md sticky-mapping row said "step 6 (anchor
resolution shares the pass)" — leftover from pre-6a-6d numbering.
Now correctly says sub-pass 6a with link to architecture.md § 3.
- `WritingModeResolved` timing contradicted across files: architecture
said "before step 1," container-queries-and-writing-modes said
"during step 1." Architecture is canonical; reworded the CQ-WM file
to match.
- `FlexParams.flex_direction` referenced in display-and-positioning's
Display→Taffy mapping — actual field is `direction`. Fixed.
Important (consistency):
- `MultiColumn` was in the SyncStyles trigger set + flex-and-grid.md
but missing from architecture § 2.1's canonical-storage table. Added,
with tier marker.
- Architecture § 2.1 caption now clarifies the table covers author-set
styling components only — runtime state (ScrollOffset),
rule-carriers (ContainerQuery), longhand transforms
(Translate/Rotate/Scale), and per-item child-side styling
(ScrollSnapItem) live in their owning files but are not on the
table. Closes the loophole the prior reviewer papered over.
- README open question on `position-try` chain depth contradicted
display-and-positioning.md's resolved "v1 supports any chain length."
Reworded the README question to scope to the depth-cap question
only (which is the genuinely open part).
- Architecture component-table description for `Anchor` no longer
promises `anchor-size()` (deferred to v1.x; called out inline).
- `text_orientation` field on `WritingMode` now carries an explicit
tier-E deferral note: stored for forward compat, glyph rotation
lives in buiy-text-rendering-design and ships post-v1.
Implementer-blocking gaps (closed):
- `AnchorNameRegistry` resource defined inline (display-and-positioning
§ 3.1): a `HashMap<SmolStr, Vec<Entity>>` maintained by an observer;
duplicate-name behavior (last-inserted wins, one warn per
(name, frame)) committed.
- Anchor cycle resolution algorithm specified: Kahn topological sort
over (anchored → anchor) DAG; cycles broken by dropping the
most-recently-inserted edge per insertion epoch on
`AnchorNameRegistry` and `AnchorRef::Entity`. Tests can assert
exact cycle membership.
- Step 6 commands-flush boundary committed: all eight steps share one
Commands buffer, applied at step 7's completion. Despawns issued in
6c are not visible to 6d's queries — both see the same world
snapshot from step 0.
- Step 4 read source clarified: `tree.layout(node_id)` (Taffy's per-
node API), not the entity-side `ResolvedLayout` which is written
in step 7.
- Table layout deferral story rewritten: v1 ships only the API surface
+ fallback path; the algorithm is deferred to v1.x. Fallback warns
once per (entity, session) and translates `Display::Table*` to
`Display::Block` for Taffy. The previous text contradicted itself
("v1 implements" + "until table layout ships, falls back to Block").
- Architecture § 2.4 added: child-side components (FlexItem, GridItem,
ScrollSnapItem) and Anchor are decomposed-only by design — `Style`
covers self-styling + container-side properties only. Closes the
hybrid-API-promise gap the implementer reviewer flagged.
- RemovedComponents parent-child ordering rule added: `tree.remove`
returning Err(NotFound) is silently swallowed; either parent-first
or child-first ordering converges to the same final state.
Cross-spec coordination:
- Scroll-driven animations (foundation tier-E) now carries an explicit
deferral marker at overflow-and-scrolling.md § 7. Layout exposes the
data (ScrollOffset, scroll bounds from ResolvedLayout); timeline
machinery lives in buiy-animation-design.
- README § 4.1 added pointing at the (TBC) migration plan in
docs/plans/. Phase 0 → target migration is large enough to warrant
its own plan; this spec is silent on sequencing.
Reviewers' lower-priority items (deferred): perf-contract numbers
(targets live in buiy-verification-design), NaN sanitization (out of
scope for this spec — Taffy's contract), Container::Size ×
ContentVisibility::Auto perf cliff (would require either a
container-aware skip rule or a CV::Auto-aware activation pass; needs
its own design note when the perf surfaces).
Initial spec: 9b8f5a5. First reviewer pass fixes: 02417b7. This: third pass.
https://claude.ai/code/session_01W662m44p1p5Xy57oEXxKg1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Graduates the
buiy-layout-designslot from the foundation roadmap (docs/specs/2026-05-07-buiy-foundation/README.md§ 4) into a 9-file sub-spec covering the full layout feature inventory in foundationvisuals.md§ 3.2.Files
README.mdarchitecture.mdStylebuilder + decomposed components, 8-step system pipeline (with named sub-passes 6a-6d),LayoutTreeGC, topological invariant, error model, change-detection trigger setbox-model.mdCalcdisplay-and-positioning.mdDisplayenum,Positionkinds, anchor positioning as post-Taffy overlay passflex-and-grid.mdcontainer-queries-and-writing-modes.mdoverflow-and-scrolling.mdstacking-and-top-layer.mdtransforms-and-containment.mdcontain,content-visibility,will-changeArchitectural decisions (with runners-up rejected)
Stylebuilder — struct-literal AND fluent form over the same fields — expands on insert into a Bundle of small public-fielded decomposed components (BoxModel,Display,Position,FlexParams/Item,GridParams/Item,Container,WritingMode,Overflow,Scroll,Stacking,Transform,Containment,Anchor). Decomposed components are canonical for ECS storage, BSN authoring, reflection. Rejected: pure-decomposed-only (loses spawn ergonomics); mega-Style(violates project convention, foundation goal init: skills, docs structure, CLAUDE.md skeleton #1.3 / issue spec:buiy-bsn-integration-design#19).buiy_coreor a futurebuiy_layoutsplit.History
Two commits: initial spec (
9b8f5a5) + reviewer fixes (02417b7). The reviewer pass addressed 9 material issues from an independent code-reviewer agent includingDefaultderive consistency, pipeline numbering normalization (named sub-passes 6a-6d underPostTaffyOverridesinstead of ad-hoc5b/5c), missing struct fields (Overflow.scroll_behavior,overscroll_*), enumeratedSyncStyleschange-detection trigger set,bitflags+Reflectintegration viaimpl_reflect_value!, and explicitFlexAxis/FlexWrap/JustifyContent/AlignItems/AlignContent/FlexGapenum definitions.Coordination
References sibling specs from foundation roadmap:
buiy-render-pipeline-design(stacking + top-layer compositing,transform/filterpaint),buiy-text-rendering-design(intrinsic sizing query interface),buiy-focus-model-design,buiy-accessibility-design,buiy-animation-design,buiy-input-events-design,buiy-i18n-design,buiy-window-and-surface-design,buiy-3d-anchored-ui-design.Catalog
docs/README.mdgains a Layout area linking to the multi-file folder.https://claude.ai/code/session_01W662m44p1p5Xy57oEXxKg1
Generated by Claude Code