Phase 2: layout overflow and scrolling#30
Merged
Conversation
10-task TDD plan realizing docs/specs/2026-05-08-buiy-layout-design/overflow-and-scrolling.md. Scope: 4 components (Overflow, Scroll, ScrollOffset, ScrollSnapItem) + 9 supporting enum types; Overflow → taffy::Style.overflow mapping per spec § 1.1; ScrollbarWidth → taffy::Style.scrollbar_width as f32 (12/8/0); Style Bundle extension with overflow + scroll fields and 12 fluent setters; sync_styles' change-detection trigger set widens to include Changed<Overflow> and Changed<Scroll> while excluding Changed<ScrollOffset> and Changed<ScrollSnapItem> — pinned by tests/layout_scroll_offset_no_invalidate.rs. Marks Phase 1 as [landed] and Phase 2 as [active] in docs/README.md. Spec: docs/specs/2026-05-08-buiy-layout-design/overflow-and-scrolling.md Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md
Two BLOCKERs: 1. Merged Tasks 5 (translate.rs widening) + 6 (systems.rs widening) into a single atomic Task 5 — splitting them left the lib uncompilable between commits because StyleView is the bridge between sync_styles' query and style_to_taffy. Renumbered remaining tasks 7→6, 8→7, 9→8, 10→9. 2. Fixed Task 8's ScrollOffset-no-invalidate test: ResolvedLayout derives only Clone (not Copy + PartialEq), so by-deref-value capture and direct assert_eq! both fail to compile. Switched to per-field (Vec2) capture and comparison; Vec2 has Copy + PartialEq. Nits: - Added rationale for ScrollbarWidth → f32 (Auto=12 / Thin=8 / None=0) matching common platform scrollbar widths. - Corrected the inline comment on map_overflow_mode regarding Taffy 0.10's Hidden/Clip distinction (Hidden reserves gutter, Clip doesn't). - Added a note to Task 2 explicitly directing executors to use #[reflect(Component, Default)] (matching BoxModel/Position/FlexParams), not #[reflect(Component)] (Phase 1's Display oversight). - Verified empirically that integration tests can use taffy::* without a dev-dep addition; documented in Task 7. - Cross-references in coverage map and body text updated for renumbering. - Final-note commit count corrected (10 = 9 task-commits + 1 plan-write). Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md
Adds OverflowMode, ScrollbarGutter, ScrollbarWidth, ScrollbarColor, ScrollBehavior, OverscrollBehavior, SnapType, SnapAlign, SnapStop — the supporting type surface for Phase 2 components in the next tasks. Spec: docs/specs/2026-05-08-buiy-layout-design/overflow-and-scrolling.md Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md task 1
Both ship with default = no-op (Visible/Visible, no snap). Overflow exposes is_scroll_container() — the spec § 1.2 predicate for sticky-positioning containing-block resolution (Phase 7). #[allow(dead_code)] on is_scroll_container: method is part of the documented public API and consumed in Phase 7; suppress the lint rather than silently remove or hide it. Spec: docs/specs/2026-05-08-buiy-layout-design/overflow-and-scrolling.md Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md task 2
ScrollOffset is runtime state — mutating it must not invalidate ResolvedLayout. ScrollSnapItem is child-side, like FlexItem; both stay decomposed-only (not in Style Bundle). Their exclusion from sync_styles' change-detection filter is enforced in Task 5. Spec: docs/specs/2026-05-08-buiy-layout-design/overflow-and-scrolling.md Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md task 3
Adds container-side overflow and scroll-snap fields plus 12 fluent setters. ScrollOffset (runtime) and ScrollSnapItem (child-side) stay out of the Bundle per architecture.md § 2.4. Spec: docs/specs/2026-05-08-buiy-layout-design/architecture.md § 2.2-2.4 Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md task 4
Atomic. Extends StyleView with `overflow` + `scroll`; maps OverflowMode
{Visible, Hidden, Clip, Scroll, Auto} → taffy::Overflow {Visible,
Hidden, Hidden, Scroll, Scroll} per spec § 1.1; ScrollbarWidth
{Auto, Thin, None} → 12.0 / 8.0 / 0.0 (f32).
Widens sync_styles' Or<(Changed<...>)> filter to include
Changed<Overflow> + Changed<Scroll>, matching architecture.md § 1.2.
Changed<ScrollOffset> and Changed<ScrollSnapItem> are intentionally
excluded — runtime state and child-side respectively (Task 8 asserts).
Spec: docs/specs/2026-05-08-buiy-layout-design/overflow-and-scrolling.md § 1.1
Spec: docs/specs/2026-05-08-buiy-layout-design/architecture.md § 1.2
Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md task 5
LayoutPlugin now reflects Overflow / Scroll / ScrollOffset / ScrollSnapItem; the four components and 9 supporting enums are re-exported from buiy_core and the buiy facade. Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md task 6
…ection End-to-end fixture: spawn Buiy entities with each OverflowMode variant, verify the resulting taffy::Style.overflow.x/y matches spec § 1.1 mapping. Adds doc-hidden by_entity / tree_ref accessors on LayoutTree to enable integration-test inspection of the Taffy bridge state. Spec: docs/specs/2026-05-08-buiy-layout-design/overflow-and-scrolling.md § 1, § 5 Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md task 7
…layout Pins Phase 2's central correctness invariant: mutating runtime/child-side scroll components must not enter sync_styles' trigger filter. Test mirrors the filter directly so future filter widenings against this contract surface in CI. Spec: docs/specs/2026-05-08-buiy-layout-design/overflow-and-scrolling.md § 2.1 Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md task 8
Adds Unreleased entries for the four new components, 9 enum types, Style Bundle extension, and the sync_styles trigger-set widening. Plan: docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.md task 9
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.
Summary
Phase 2 of the layout migration — ships overflow / scrolling component set on top of the Phase 1 foundation:
Overflow(per-axis overflow + scrollbar config),Scroll(snap container),ScrollOffset(runtime state),ScrollSnapItem(decomposed-only child-side).OverflowMode,ScrollbarGutter,ScrollbarWidth,ScrollbarColor,ScrollBehavior,OverscrollBehavior,SnapType,SnapAlign,SnapStop.OverflowMode::{Visible, Hidden, Clip, Scroll, Auto}→taffy::Overflow::{Visible, Hidden, Hidden, Scroll, Scroll}(per spec § 1.1);ScrollbarWidth::{Auto, Thin, None}→taffy::Style.scrollbar_width: f32(12.0 / 8.0 / 0.0).StyleBundle extension:OverflowandScrolljoin the Bundle (always-insert pattern from Phase 1) plus 12 fluent setters.ScrollOffsetandScrollSnapItemare decomposed-only per architecture.md § 2.4.sync_styles's change-detection trigger filter widens to includeChanged<Overflow>+Changed<Scroll>while deliberately excludingChanged<ScrollOffset>+Changed<ScrollSnapItem>— scroll-position mutations bypass the Taffy translate path entirely. The exclusion is pinned bycrates/buiy_core/tests/layout_scroll_offset_no_invalidate.rs, which mirrors the filter directly so any future widening against this contract surfaces in CI.Spec:
docs/specs/2026-05-08-buiy-layout-design/overflow-and-scrolling.mdPlan:
docs/plans/2026-05-08-buiy-layout-overflow-and-scrolling.mdTest plan
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningsRUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-depscargo test --workspace— 93 passed / 0 failed / 4 ignored (was 74 baseline; Phase 2 adds 19 tests)cargo deny checkOverflow::is_scroll_container()predicate matches spec § 1.2OverflowModevariants map to expectedtaffy::Overflowvalue through full pipelineScrollOffset/ScrollSnapItemdoes NOT triggersync_styles(yields 0 entities through the filter mirror)ResolvedLayoutis byte-equal across a scroll-only frameWorkflow
Authored via the project's superpowers skills:
writing-plansproduced the 9-task planResolvedLayoutonly derivesClone)subagent-driven-developmentwalked the 9 tasks with implementer → spec-reviewer → code-quality-reviewer cyclesOBSERVATIONSof the review)🤖 Generated with Claude Code