vocabulary: list, selectable-card, metadata-list#19
Merged
Conversation
The smallest durable expansion for transactional selection and
comparison — plan pickers, product comparison, booking options — with
nothing hotel-specific and nothing invented: all three are faithful
projections of real upstream Astryx components (verified against
`npx astryx component --json`).
- list (upstream List): the non-tabular collection container. Also the
only way rules can ever say "at least two options": composition
minimums count within a parent, never surface-globally.
- selectable-card (upstream SelectableCard, "plan pickers, filter
chips, or option grids" per its own docs): the named option unit,
with isSelected carried as delivered presentational state.
- metadata-list (upstream MetadataList): the comparable-attributes
unit, DATA-DRIVEN ({label,value} items, grammar-required) — the
Table idiom, because sub-components carry no props under
grammar-constrained generation. The one deliberate upstream
divergence, declared as x-drift; drift-check now reports x-drift
props as acknowledged divergences instead of findings.
Profile mappings project all three through the ordinary emit gates
(catalog grows 9 -> 12 including synthesized Column); renderers land in
BOTH design systems (Astryx via @astryxdesign/core; shadcn as native
token-styled visuals — ring-accented option card, definition-list
metadata). Dialog remains the sole deliberate shadcn placeholder.
Also revises rule.record-collection-requires-table's caveat: the
anticipated "widen to a choice set" is inexpressible (component-choice
require is conjunctive); uniform records still choose tables, list
serves heterogeneous/selectable content, requireOneOf noted as
candidate dspack-gen work.
No new intent yet: the vocabulary is inert until transactional-review
lands with the scenario that validates it (next PR, atomic).
Fail-first: shadcn registry-parity failed against the 12-name catalog
(List/MetadataList/SelectableCard unimplemented) before the renderers
landed; drift-check flagged metadata-list.items before x-drift. Gates:
contracts build:catalogs (all ajv gates) + drift-check clean;
pnpm -r typecheck/test green; local Playwright 102 passed / 4 skipped;
production config vs the local deploy artifact 82 passed. Render proof:
a scratch comparison surface emitted through the real profile renders
in BOTH design systems (selected-state checkbox semantics, metadata
term/definition pairs) — exercised via a throwaway spec, not shipped.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Expands the shared contract vocabulary to include list, selectable-card, and metadata-list, and wires up renderer support for both Astryx (@astryxdesign/core) and the shadcn renderer registry (keeping Dialog as the deliberate placeholder), while updating drift-check behavior to treat x-drift props as acknowledged divergences.
Changes:
- Add
List,SelectableCard, andMetadataListto Astryx + shadcn renderer registries, with new renderer implementations for each design system. - Extend the contracts catalog/profile to describe the three new components (including
metadata-list.itemsas an acknowledged upstream drift viax-drift). - Update parity/e2e/docs/UI notes from “8 of 9” to “11 of 12” / “12 of 12” as appropriate.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shadcn-renderers/src/registry.tsx | Registers shadcn renderers for List / SelectableCard / MetadataList and updates coverage note. |
| packages/shadcn-renderers/src/registry-parity.test.ts | Updates expected custom-renderer coverage to include the three new components. |
| packages/shadcn-renderers/src/components/SelectableCardRender.tsx | Adds shadcn visual implementation for SelectableCard. |
| packages/shadcn-renderers/src/components/MetadataListRender.tsx | Adds shadcn visual implementation for MetadataList as a definition list. |
| packages/shadcn-renderers/src/components/ListRender.tsx | Adds shadcn visual implementation for List with density + optional dividers. |
| packages/contracts/src/drift-check.ts | Adds new component name mappings and treats x-drift props as acknowledged divergences. |
| packages/contracts/src/astryx-profile.ts | Adds A2UI projection entries for List / SelectableCard / MetadataList. |
| packages/contracts/astryx.dspack.json | Adds contract catalog entries for list/selectable-card/metadata-list and updates a table-related rule rationale. |
| packages/astryx-renderers/src/registry.tsx | Registers Astryx renderers for List / SelectableCard / MetadataList. |
| packages/astryx-renderers/src/components/SelectableCardRender.tsx | Adds Astryx core SelectableCard projection (presentational onChange). |
| packages/astryx-renderers/src/components/MetadataListRender.tsx | Adds Astryx core MetadataList projection by synthesizing MetadataListItem children from items. |
| packages/astryx-renderers/src/components/ListRender.tsx | Adds Astryx core List projection. |
| e2e/design-swap.spec.ts | Updates the design-system note assertion to “11 of 12”. |
| docs/renderer-abstraction.md | Updates renderer-abstraction doc coverage numbers to reflect the expanded catalog. |
| apps/web/app/design-system.tsx | Updates Astryx/shadcn design system “note” strings to reflect new catalog totals. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| }; | ||
|
|
||
| export const ListRender: FC<any> = ({ props, buildChild }) => ( | ||
| <div role="list" className={cn("flex flex-col", GAP[props.density as string] ?? "gap-2", props.hasDividers && "divide-y divide-border [&>*]:pt-2 first:[&>*]:pt-0")}> |
Comment on lines
+16
to
+18
| role="option" | ||
| aria-selected={selected} | ||
| aria-disabled={Boolean(props.isDisabled) || undefined} |
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.
What
The approved platform slice (PR A of the transactional-selection design): the smallest durable vocabulary expansion for selection & comparison workflows — plan pickers, product comparison, booking options — with nothing hotel-specific and nothing invented. All three components are faithful projections of real upstream Astryx components, verified against
npx astryx component --json:list(upstream List) — the non-tabular collection container. Platform-load-bearing: composition minimums only count within a parent component, solistis the only way governance can ever say "at least two options."selectable-card(upstream SelectableCard — "plan pickers, filter chips, or option grids" per its own docs) — the named option unit;isSelectedcarried as delivered presentational state (selection lives in the data model; no protocol change).metadata-list(upstream MetadataList) — comparable attributes, data-driven (items: [{label, value}], grammar-required via the 0.1.2 mechanism). This is the one deliberate upstream divergence (upstream is children-based; sub-components carry no props under grammar-constrained generation), declared asx-drifton the prop — and drift-check now reportsx-driftprops as acknowledged divergences instead of findings.Renderers land in both design systems: Astryx via
@astryxdesign/coreimports; shadcn as native token-styled visuals (ring-accented option card, definition-list metadata). Dialog remains the sole deliberate shadcn placeholder (11 of 12).Also revises
rule.record-collection-requires-table's caveat honestly: the anticipated "widen to a choice set" is inexpressible (component-choice.requireis conjunctive) — uniform records still choose tables,listserves heterogeneous/selectable content,requireOneOfnoted as candidate future dspack-gen work.Deliberately no new intent here. The vocabulary is shared and inert until
transactional-reviewlands in the next PR, atomically with the hotel-reservations scenario that validates it (established no-intent-without-scenario discipline).Fail-first evidence
registry-parity.test.tsagainst the 12-name catalog, before the renderers:x-driftmechanism:metadata-list.items: prop not found on Astryx MetadataList(the genuine, documented divergence).Gates
build:catalogs: all ajv gates green on both catalogs; the emitted catalog grows 9 → 12 (incl. synthesized Column).drift-check: "contract vocabulary matches Astryx docs"; the items divergence reported as acknowledged.pnpm -r typecheck/pnpm -r testgreen; local Playwright 102 passed / 4 skipped; production config vs the local deploy artifact 82 passed (receipt-hash/design-swap invariance included).🤖 Generated with Claude Code