WORK-467
ID:WORK-467Status:done

Feature layout axis + transform-level default resolution

Give feature an honest layout axis (grid | list) drawn from the canonical const, with the media-position-derived default resolved in the transform so the author override and the default never collide. Per SPEC-099 §1 + §4.

Priority:highComplexity:moderateMilestone:v0.26.0Source:SPEC-099
claude/spec-099-feature-layout-axis View source

Criteria completion

Criteria completion: 4 of 4 (100%) checked; tracking started on Jun 25, no incremental history yet0%25%50%75%100%Jun 25Jul 11

Tracking started Jun 25 — check back for trends.

Branches 3
claude/spec-099-feature-layout-axis current done
main donechangeset-release/main doneclaude/v0.26.0-milestone-2vuxi9 ready
History 3
  1. 4216f8b
    Created (done)by bjornolofandersson
  2. 8528ebb
    Content editedby Claude
    plan: mark SPEC-099 work items (WORK-467/468/469) done
  3. 17d2678
    Content editedby Claude
    v0.26.0: accept ADR-018 + SPEC-099/100/108, break down into 15 work item

Scope

  • Add a layout attribute to feature (plugins/marketing/src/tags/feature.ts), matching grid | list imported from the canonical const (WORK-466) — no bespoke columns value.
  • Resolve the default in the transform, not via a config variant: compute effectiveLayout = attrs.layout ?? derive(mediaPosition) (stacked top/bottom → grid, beside start/end → list) and emit it as a single layout meta. Author override beats the derived default; exactly one data-layout lands on the element.
  • layout is always emitted (both grid and list are styled) — no default-suppression guard (unlike width).
  • This item only introduces the axis + emission; retiring the old media-position coupling and moving the CSS onto [data-layout] is a separate, dependent work item.

Acceptance Criteria

  • feature accepts layout matching grid | list, both imported from the canonical const.
  • The engine emits a single data-layout from the resolved layout meta.
  • When layout is unset it derives from media-position (stacked → grid, beside → list); an explicit layout overrides that default.
  • Item arrangement and media placement are independently controllable (media beside content and layout="grid" is reachable).

Dependencies

  • WORK-466 — imports grid/list from the canonical const.

References

  • Spec: SPEC-099 §1 (layout axis), §4 (transform-level default resolution).
  • plugins/marketing/src/tags/feature.ts, packages/runes/src/tags/common.ts (SplitLayoutModel, buildLayoutMetas).

Resolution

Completed: 2026-06-25

Branch: claude/spec-099-feature-layout-axis

What was done

  • plugins/marketing/src/tags/feature.ts — added the layout attribute (grid|list via layoutMatches([LAYOUT.grid, LAYOUT.list])); resolve effectiveLayout = attrs.layout ?? derive(media-position) (stacked→grid, beside→list) in the transform and emit a single always-present layout meta.
  • plugins/marketing/src/config.tslayout modifier (source: 'meta', noBemClass: true) so the meta maps to data-layout.
  • plugins/marketing/test/feature.test.ts — 4 tests: default grid, media-derived list, explicit override (both directions), always-present.

Notes

  • Author override and the media-derived default never collide because exactly one value is computed in the transform. Output unchanged for existing content; the CSS move + coupling removal is WORK-468.