Implement create custom recommendations

This commit is contained in:
adilallo
2026-04-20 12:41:10 -06:00
parent e9dab04b34
commit 45bbbb8a35
75 changed files with 6403 additions and 1452 deletions
@@ -26,6 +26,7 @@ const CardStackContainer = memo<CardStackProps>(
description = "",
layout = "default",
compactRecommendedLimit = 5,
compactCardIds,
compactDesktopLayout: compactDesktopLayoutProp = "grid",
headerLockupSize,
toggleAlignment = "center",
@@ -83,6 +84,7 @@ const CardStackContainer = memo<CardStackProps>(
description={description}
layout={layout}
compactRecommendedLimit={compactRecommendedLimit}
compactCardIds={compactCardIds}
compactDesktopLayout={compactDesktopLayoutProp}
headerLockupSize={headerLockupSize}
toggleAlignment={toggleAlignment}
@@ -25,6 +25,16 @@ export interface CardStackProps {
* Max recommended cards in compact (non-expanded) mode. Default 5; Figma compact stack uses 3.
*/
compactRecommendedLimit?: number;
/**
* Optional explicit list of card ids to render in the compact slot, in
* order. When provided, this overrides the default
* `cards.filter(c => c.recommended)` selection — the `recommended` flag
* then only controls the visual "Recommended" badge. Used by the
* create-flow card-deck steps so facet scores can pick the compact set
* (and badge only the truly matched subset). Cards whose ids are not in
* `cards` are silently dropped.
*/
compactCardIds?: string[];
/**
* At `md+`, how compact recommended cards are laid out. `flexWrap` matches Figma Flow — Compact Card Stack (three cards in a row).
* `pyramidFive` = two rows (3 + 2) centered for five recommended cards (membership step).
@@ -50,6 +60,7 @@ export interface CardStackViewProps {
description: string;
layout: "default" | "singleStack";
compactRecommendedLimit: number;
compactCardIds: string[] | undefined;
compactDesktopLayout: "grid" | "flexWrap" | "pyramidFive";
headerLockupSize: HeaderLockupSizeValue | undefined;
toggleAlignment: "center" | "end";
@@ -17,6 +17,7 @@ export function CardStackView({
description,
layout,
compactRecommendedLimit,
compactCardIds,
compactDesktopLayout,
headerLockupSize,
toggleAlignment,
@@ -24,10 +25,22 @@ export function CardStackView({
}: CardStackViewProps) {
const lockupSize = headerLockupSize ?? "L";
const isSelected = (id: string) => selectedIds.includes(id);
// Compact: recommended only (default up to 5). Expanded: all cards.
const compactCards = cards
.filter((c) => c.recommended ?? false)
.slice(0, compactRecommendedLimit);
// Compact: explicit `compactCardIds` (caller-driven, used by create-flow
// facet ranker) takes precedence over the legacy `recommended`-filter so
// the screen can show un-tagged cards in the compact slot when there is
// no facet signal yet (CR-88 §10).
const compactCards = (() => {
if (compactCardIds && compactCardIds.length > 0) {
const byId = new Map(cards.map((c) => [c.id, c]));
return compactCardIds
.map((id) => byId.get(id))
.filter((c): c is (typeof cards)[number] => c !== undefined)
.slice(0, compactRecommendedLimit);
}
return cards
.filter((c) => c.recommended ?? false)
.slice(0, compactRecommendedLimit);
})();
// Single stack: always one column; expand reveals more in same stack (scrollable)
if (layout === "singleStack") {