ADRs 042, 047–049: Composition, Slot Content, and Ready-Made Examples#91
Open
nathanacurtis wants to merge 22 commits into
Open
ADRs 042, 047–049: Composition, Slot Content, and Ready-Made Examples#91nathanacurtis wants to merge 22 commits into
nathanacurtis wants to merge 22 commits into
Conversation
Introduces Composition as a peer type to Component, covering slot defaults, component examples, layout patterns, and page views. Supersedes draft ADR-025 (nested slot API). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Component.examples: Record<string, Composition> (inline, kind-tagged)
- CompositionRef { $composition: string } in Children union for slot bindings
- Slot defaults live in variant/element layer, vary per variant
- PropConfigurations widening retained (consumer inline pattern)
- System-scoped compositions.yaml schema deferred to follow-on ADR
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…faults - Rename CompositionRef → CompositionReference (then remove: not needed) - Remove CompositionReference from Children union — Children unchanged - Slot default composition lives in Element.$extensions['com.figma'] following established provenance-metadata pattern on Props/TokenReference - Add ElementExtensions + FigmaElementExtension types on Element - Slot defaults are Figma provenance, not public component API Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
defaultComposition is meaningful only when Element.children is a PropBinding (slot-bound container / Figma SlotNode). Container elements with string[] children are FrameNodes and must never carry it. No new element type introduced. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ComponentExample = SlotExample | InstanceExample (kind-discriminated) - SlotExample: kind+'slot'+anatomy+elements+layout — no inline nesting - InstanceExample: kind+propConfigurations (scalars)+slots (named refs) - Composition retained as structural base for system-scoped follow-on - PropConfigurations widens to PropBinding only; inline Composition deferred - Remove CompositionKind; layout/page kinds moved to follow-on ADR - All examples use aSlotProperty/aSlotElement naming Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ciple to ADR 042 - Replace Card/ProductCard examples with ActionList/ActionListItem throughout - Add sensitizing example section: illustrates 56 to 16 entry reduction via one-level-deep principle and no cross-component references - Add two new Decision Drivers: One level deep and No cross-component references - Update Option A Pros to call out scale reduction explicitly - Update Notes to explain the ActionListItem boundary and why it is intentional Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ADR-042 now covers only the Composition base type (anatomy, elements, layout). The four-ADR breakdown: 043 — Component Examples: InstanceExample + Component.examples 044 — Slot Content: SlotExample + Element extensions 045 — PropConfigurations PropBinding Example anchors on ActionListItem with state/title/description scalar props; slots are introduced in ADR-044. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…opBinding
043: InstanceExample + ComponentExamples + Component.examples
ActionListItem anchors the example with state/title/description scalar props
InstanceExample.slots forward-compatible; meaningful once 044 lands
044: SlotExample + ElementExtensions + Element.$extensions
ActionListItem startVisual/endVisual slots; ActionList items slot one level deep
16 entries on ActionList (not 56); one-level-deep principle; no cross-component refs
Widens ComponentExamples to ComponentExample = InstanceExample | SlotExample
045: Widen PropConfigurations to include PropBinding
Completes binding pattern already on Element.content, instanceOf, Styles.visible
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…xample - Replace thin two-option section with four substantive options exploring: - Anatomy/elements convergence (B — rejected: breaks SlotExample inheritance) - All three required (A — selected) - elements optional (C — rejected: anatomy-only is degenerate) - layout optional (D — rejected: implied order is invisible convention) - Fix example: ActionListItem with root/label/description, not a single 'item' - Add description? field alongside title? - Note nested-instance-with-slot constraint explicitly in Notes - Note anticipated metadata extensions (tags, deprecated, guidelines) - Propagate required elements+layout to ADR-044 SlotExample Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 2x page grid padding and nav–content gutter at wide viewports - Increase sidebar item spacing (+4px) and padding (+2px → 8px) - Remove distinct surface colors and borders between nav/sidebar/content - Force dark mode and hide theme toggle - Move GitHub and Figma Plugin links from header to top of sidebar Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lotBinding Substantial revisions following review: - Drop SlotExample type; reuse Composition directly - Drop the per-entry `slot` field — content entries are slot-agnostic - Make slot content a sibling field (`Component.slotContent`) rather than a discriminated-union peer of `InstanceExample` in `Component.examples` - Move Figma default-fill reference into `SlotBinding.$extensions['com.figma'].default` (inside `Element.children`, not a sibling on `Element`) to reflect that it is design-tool authoring provenance that code consumers must correctly ignore - Defer recursion (nested slot filling) and its motivating example to a follow-on ADR; keep this ADR scoped to one level deep - Add rejected options for Element-sibling field, content widening - Tighten Context and trim Option A example to the minimum needed to show both reference sites Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ionale Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ompositions main owns ADR-043 (custom-color-format-config) and PR #60 owns ADR-044/045 (duplicate-layer-disambiguation, processing-provenance-signals). This branch's three ADRs collide with both. Move ours to the next free range so PR #60 and already-merged work remain valid: - 043-component-examples -> 046-component-examples - 044-slot-content -> 047-slot-content - 045-prop-configurations-binding -> 048-prop-configurations-binding Reserve 049 for the deferred recursion ADR (Nested Slot Compositions, called out as a follow-on in ADR-047). Stub authored. Updates all ADR-NNN cross-references and branch-name references inside our four ADRs and INDEX.md. INDEX.md description for the slot-content row also brought in line with the redesigned ADR-047 title (the prior description referenced removed concepts like SlotExample / defaultComposition). Indexing change only - no design decisions altered. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…+cli-0.14.0 # Conflicts: # adr/INDEX.md # packages/cli/CHANGELOG.md # packages/cli/package.json
…type # Conflicts: # adr/042-composition-type.md # adr/INDEX.md
Slot fill is unified under Element.propConfigurations per ADR-049, so InstanceExample.slots becomes redundant. With slot fills handled separately, Component.examples only ever holds InstanceExample entries and the kind discriminator carries no information. Updates Decision Drivers, Options A and B, Notes, Consequences, schema definition, and parity check to match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…search scratchpads
ADR-049 now compares four shapes for cross-boundary slot fill:
A. Nested only (inline Composition under propConfigurations)
B. Flat only (key reference, discriminated as { \$slotContent: <key> })
C. Both forms accepted
D. Sibling field (Element.slotFills)
Key decisions captured:
- Recursion depth is unbounded (Decision Driver, not Out of Scope)
- Cycle detection is a constraint, enforced by consumer validators
- Layout direction lives in styles.layoutMode, not at the slot boundary
- Named compositions can live in Component.slotContent (component-scoped)
OR in 1+ external composition files (system-scoped, ADR-042 follow-on)
- Discriminated reference form { \$slotContent: <key> } parallels PropBinding
Scratchpads in adr/research/049/ demonstrate the design space concretely
through a deeply-nested filter results page (Page > Row > Accordion >
CheckboxGroup > Checkbox > custom-children) in both nested and flat
forms. The flat form is system-scoped (spans multiple components).
ADR-047 simplifications (drop \$extensions / SlotBinding) and field-naming
questions (slotContent vs compositions; \$slotContent vs \$composition)
flagged for follow-up rather than rolled in.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…mples; add Pill scratchpad
Three coordinated changes across the composition ADRs:
1. Reference form is JSON Pointer, paralleling ADR-008 PropBinding.
- ADR-049's discriminated reference becomes { $composition: <pointer> }
(rotated from $slotContent; pointer makes the registry home explicit).
- ADR-047's SlotBinding.$extensions['com.figma'].default value becomes
a JSON Pointer to a Composition (was a bare slotContent key).
- Scratchpads updated: example.flat.yaml wraps records under a top-level
`compositions:` namespace so absolute pointers resolve; example.pill.yaml
(new) wraps under `components: pill:` for the same reason.
2. Rename ComponentExamples → InstanceExamples; Component.examples →
Component.instanceExamples. Disambiguates against Props.examples and
Anatomy.examples (which carry sample content, not InstanceExample
entries). Cited in ADR-046 Semver section as the first ADR-side
application of Constitution §VI rule 3 (no code-platform consensus
on this specs-schema-specific authoring construct).
3. New cross-ADR scratchpad example.pill.yaml — a Pill component that
exercises ADR-008 (PropBinding), ADR-046 (instanceExamples),
ADR-047 (slotContent + SlotBinding with Figma authoring default),
and ADR-049 (discriminated $composition reference) in one file.
Three documented usages span the surface: configuredLabel
(custom:false + label scalar), composedLabel (custom:true filled
with Figma's default composition), removableLabel (custom:true
filled with text + remove glyph composition).
Cleanup along the way: ADR-047 had stale references to the removed
InstanceExample.slots field (six sites in Notes / Pros / Consequences /
Out of scope / Option D rejection). All updated to point at the unified
propConfigurations.<slotName> mechanism per ADR-049. The Option A example
in ADR-047 was wrapped under `components: actionListItem:` and updated
to JSON Pointer references, replacing the pre-rename `examples.slots`
form with `instanceExamples.propConfigurations.<slot>: { $composition }`.
ADR-042 forward references (lines 25, 195, 206) updated from
Component.examples to Component.instanceExamples.
INDEX.md row 046 updated to reflect the new title and field name.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
No description provided.