WORK-471
ID:WORK-471Status:done

Attribute-triggered behavior dispatch path

Add a behavior dispatch path that mounts a behavior by attribute selector ([data-layout="carousel"]) independent of rune identity. This is the linchpin that makes carousel adoption config-only. Per SPEC-100 Design notes.

Priority:highComplexity:moderateMilestone:v0.26.0Source:SPEC-100
claude/spec-100-carousel-layout-mode View source

Criteria completion

Criteria completion: 3 of 3 (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-100-carousel-layout-mode current done
main donechangeset-release/main doneclaude/v0.26.0-milestone-2vuxi9 ready
History 3
  1. 8058ef6
    Created (done)by bjornolofandersson
  2. af14bbd
    Content editedby Claude
    WORK-471: attribute-triggered behavior dispatch path
  3. 17d2678
    Content editedby Claude
    v0.26.0: accept ADR-018 + SPEC-099/100/108, break down into 15 work item

Scope

  • Today's dispatch (packages/behaviors/src/index.ts) is a data-rune-keyed map; the only non-rune paths are the special-cased data-reveal scan and the data-layout-behaviors scan. Nothing binds on an arbitrary attribute like [data-layout="carousel"].
  • Add a new attribute-triggered dispatch path: applyBehaviors also scans [data-layout="carousel"] and mounts the shared carousel behavior once per host, regardless of the host's data-rune. Honour normal cleanup/teardown semantics.
  • This item delivers the dispatch mechanism + its registration seam; lifting the carousel behavior body out of gallery is a separate, dependent work item. Avoid double-mounting when a rune also has a data-rune behavior (e.g. gallery).

Acceptance Criteria

  • applyBehaviors mounts the carousel behavior on every [data-layout="carousel"] host independent of data-rune; adoption needs no per-rune behavior registration.
  • A host that also has a data-rune behavior (e.g. gallery) does not double-mount; cleanup tears down correctly.
  • The new path is covered by a behavior test.

Dependencies

None hard — behaviors-layer infrastructure; the carousel behavior body this dispatches is lifted by a separate, dependent item.

References

  • Spec: SPEC-100 Design notes (the dispatch path is new plumbing, not a selector swap).
  • packages/behaviors/src/index.ts (applyBehaviors, the data-rune map, the data-reveal/data-layout-behaviors scans).

Resolution

Completed: 2026-06-25

Branch: claude/spec-100-carousel-layout-mode

What was done

  • packages/behaviors/src/index.ts — new attribute-triggered dispatch: a layoutModeBehaviors registry keyed by data-layout value, a registerLayoutModeBehaviors() add-only registrar, getLayoutModeBehaviorNames(), and a scan in initRuneBehaviors that mounts the registered behavior on every [data-layout="<value>"] host independent of data-rune (respecting the framework-managed + presentational guards).
  • packages/behaviors/test/layout-mode-dispatch.test.ts — verifies dispatch on every matching host (any/no rune), exactly once per host (no double-mount), cleanup teardown, add-only semantics, and getLayoutModeBehaviorNames().

Notes

  • The carousel behavior body itself is registered in WORK-472 (which also drops setupCarousel from galleryBehavior, so gallery's lightbox + the shared carousel are distinct, non-double-mounted concerns). The dispatch is the linchpin that makes adoption config-only.
  • Follow-on to confirm in adoption (WORK-474/475): the adapter's behavior-bundle inclusion heuristic (getBehaviorNames/data-rune) should also account for [data-layout] layout-mode behaviors so a carousel-only page ships the bundle.