{
  "version": "2.5.10",
  "generatedAt": "2026-08-18T05:34:57.088Z",
  "patterns": [
    {
      "id": "dashboard-shell",
      "title": "Dashboard app shell",
      "description": "Sidebar + Header + main content with optional filters and KPI row",
      "components": [
        {
          "id": "sidebar",
          "role": "provider"
        },
        {
          "id": "layout",
          "role": "shell"
        },
        {
          "id": "header",
          "role": "header"
        },
        {
          "id": "filter-strip",
          "role": "filters"
        },
        {
          "id": "statistics-card",
          "role": "kpis"
        },
        {
          "id": "data-table",
          "role": "grid"
        }
      ],
      "recipe": "dashboard",
      "constraints": [
        "SidebarProvider at app root",
        "Use Layout not DynamicLayout for shell"
      ]
    },
    {
      "id": "filter-and-table",
      "title": "Filter panel with data table",
      "description": "Planning workspace with filters and DataTable",
      "components": [
        {
          "id": "filter-panel",
          "role": "filters"
        },
        {
          "id": "data-table",
          "role": "grid"
        }
      ],
      "constraints": [
        "Use DataTable from impact-nova/data-table, not raw ag-grid-react"
      ]
    },
    {
      "id": "wizard-flow",
      "title": "Multi-step wizard",
      "description": "Wizard with progress and step content",
      "components": [
        {
          "id": "wizard",
          "role": "flow"
        },
        {
          "id": "button",
          "role": "actions"
        }
      ],
      "recipe": "wizard-flow"
    },
    {
      "id": "settings-page",
      "title": "Settings page",
      "description": "Card-based settings with form fields and save actions",
      "components": [
        {
          "id": "layout",
          "role": "shell"
        },
        {
          "id": "breadcrumb",
          "role": "navigation"
        },
        {
          "id": "card",
          "role": "sections"
        },
        {
          "id": "input",
          "role": "fields"
        },
        {
          "id": "switch",
          "role": "toggles"
        },
        {
          "id": "button",
          "role": "actions"
        }
      ],
      "recipe": "settings-page"
    },
    {
      "id": "admin-list-page",
      "title": "Admin list page",
      "description": "Breadcrumb, filters, toolbar, and data grid for entity management",
      "components": [
        {
          "id": "breadcrumb",
          "role": "navigation"
        },
        {
          "id": "filter-strip",
          "role": "filters"
        },
        {
          "id": "data-table",
          "role": "grid"
        },
        {
          "id": "dropdown-menu",
          "role": "row-actions"
        }
      ],
      "recipe": "admin-list"
    },
    {
      "id": "analytics-dashboard",
      "title": "Analytics dashboard",
      "description": "KPI cards, charts, and optional data table",
      "components": [
        {
          "id": "statistics-card",
          "role": "kpis"
        },
        {
          "id": "chart",
          "role": "visualization"
        },
        {
          "id": "filter-strip",
          "role": "filters"
        },
        {
          "id": "data-table",
          "role": "grid"
        }
      ],
      "recipe": "analytics-dashboard"
    },
    {
      "id": "empty-to-data-flow",
      "title": "Empty state to data flow",
      "description": "Three-phase UX: empty → filters → populated workspace",
      "components": [
        {
          "id": "empty-container",
          "role": "empty"
        },
        {
          "id": "filter-panel",
          "role": "filters"
        },
        {
          "id": "data-table",
          "role": "grid"
        }
      ],
      "constraints": [
        "See impact-nova://product-quality-bar"
      ]
    },
    {
      "id": "form-page",
      "title": "Form page",
      "description": "Accessible form layout with labels, errors, and actions",
      "components": [
        {
          "id": "card",
          "role": "container"
        },
        {
          "id": "input",
          "role": "fields"
        },
        {
          "id": "select",
          "role": "pickers"
        },
        {
          "id": "textarea",
          "role": "long-text"
        },
        {
          "id": "button",
          "role": "submit"
        }
      ],
      "recipe": "form-page"
    },
    {
      "id": "detail-drawer",
      "title": "Detail drawer / side panel",
      "description": "Master-detail with sheet or drawer for record details",
      "components": [
        {
          "id": "data-table",
          "role": "master"
        },
        {
          "id": "sheet",
          "role": "detail-panel"
        },
        {
          "id": "button",
          "role": "actions"
        }
      ],
      "recipe": "detail-drawer"
    },
    {
      "id": "command-palette-app",
      "title": "Command palette integration",
      "description": "Global keyboard shortcuts and command search",
      "components": [
        {
          "id": "command-palette",
          "role": "provider"
        },
        {
          "id": "layout",
          "role": "shell"
        }
      ],
      "constraints": [
        "See impact-nova://command-palette"
      ]
    },
    {
      "id": "notification-center",
      "title": "Notification center",
      "description": "Header notification icon with panel and toast feedback",
      "components": [
        {
          "id": "header",
          "role": "shell"
        },
        {
          "id": "notification-panel",
          "role": "notifications"
        },
        {
          "id": "toast",
          "role": "feedback"
        }
      ],
      "recipe": "notification-center"
    },
    {
      "id": "kanban-board",
      "title": "Kanban board",
      "description": "Horizontal columns with cards — use HorizontalScroller + Card per column",
      "components": [
        {
          "id": "horizontal-scroller",
          "role": "columns"
        },
        {
          "id": "card",
          "role": "column"
        },
        {
          "id": "badge",
          "role": "counts"
        }
      ],
      "recipe": "kanban-board"
    },
    {
      "id": "search-results",
      "title": "Search results page",
      "description": "Search input with filter chips and results table",
      "components": [
        {
          "id": "input",
          "role": "search"
        },
        {
          "id": "chips",
          "role": "filters"
        },
        {
          "id": "data-table",
          "role": "results"
        }
      ],
      "recipe": "search-results"
    },
    {
      "id": "multi-filter-workspace",
      "title": "Multi-filter planning workspace",
      "description": "Filter strip + filter panel + data table for planning apps",
      "components": [
        {
          "id": "filter-strip",
          "role": "active-filters"
        },
        {
          "id": "filter-panel",
          "role": "filter-sidebar"
        },
        {
          "id": "tabs",
          "role": "views"
        },
        {
          "id": "data-table",
          "role": "grid"
        }
      ],
      "recipe": "planning-workspace"
    },
    {
      "id": "kpi-dashboard",
      "title": "KPI dashboard rail",
      "description": "Horizontal KPI cards above main content",
      "components": [
        {
          "id": "horizontal-scroller",
          "role": "kpi-rail"
        },
        {
          "id": "statistics-card",
          "role": "kpis"
        },
        {
          "id": "chart",
          "role": "trends"
        }
      ],
      "recipe": "kpi-dashboard"
    },
    {
      "id": "confirm-destructive",
      "title": "Destructive confirmation",
      "description": "Alert dialog for delete or irreversible actions",
      "components": [
        {
          "id": "alert-dialog",
          "role": "confirm"
        },
        {
          "id": "button",
          "role": "trigger"
        }
      ],
      "recipe": "confirm-destructive"
    },
    {
      "id": "date-filter-workspace",
      "title": "Date-filtered workspace",
      "description": "Date range picker with filtered data table",
      "components": [
        {
          "id": "date-picker",
          "role": "date-filter"
        },
        {
          "id": "filter-strip",
          "role": "filters"
        },
        {
          "id": "data-table",
          "role": "grid"
        }
      ],
      "recipe": "date-filter-workspace"
    },
    {
      "id": "fiscal-date-filter-workspace",
      "title": "Fiscal date-filtered workspace",
      "description": "Fiscal DateRangePicker / MonthPicker (period) with period-aware filters and a data table. Serialize ranges as { dateFrom, dateTo }.",
      "components": [
        {
          "id": "date-picker",
          "role": "fiscal-date-filter"
        },
        {
          "id": "filter-strip",
          "role": "filters"
        },
        {
          "id": "data-table",
          "role": "grid"
        }
      ],
      "constraints": [
        "Pass calendarKind=\"fiscal\" and fiscalConfig from impact-nova/fiscal-calendar",
        "MonthPicker with calendarKind=fiscal is the period picker — do not invent PeriodPicker",
        "AG Grid DateFilterPicker fiscalConfig applies to date and month variants, not only week",
        "Use impact-nova/fiscal-calendar for server-side FY math; never Date#toISOString for civil keys"
      ],
      "recipe": "fiscal-date-filter-workspace"
    },
    {
      "id": "form-field-control",
      "title": "Accessible form field",
      "description": "Field (FormField alias) composing label, description, error, and a single control — or inline label/error on Input, Combobox, RadioGroup",
      "components": [
        {
          "id": "form-field",
          "role": "wrapper"
        },
        {
          "id": "input",
          "role": "control"
        }
      ],
      "constraints": [
        "Use error not isError on controls",
        "Match htmlFor on Field to control id",
        "Import Field or FormField from impact-nova/form",
        "Controls may use inline label and helperText via FieldControlProps"
      ],
      "recipe": "form-field-control"
    },
    {
      "id": "rsc-client-island",
      "title": "Server page with client Nova island",
      "description": "Fetch on server; pass serializable props to a client wrapper using Nova components",
      "components": [
        {
          "id": "button",
          "role": "actions"
        },
        {
          "id": "select",
          "role": "filters"
        }
      ],
      "constraints": [
        "Client file must use use client directive",
        "Prefer query_components ssrSupport/rscCompatibility for placement",
        "See impact-nova://ssr-rsc"
      ],
      "recipe": "rsc-client-island"
    },
    {
      "id": "virtualized-selectable-list",
      "title": "Large selectable virtualized list",
      "description": "10k+ row windowing with selection and search — compound VirtualizedList*, headless useVirtualizedList, or optional ExpandableListItem rows",
      "components": [
        {
          "id": "virtualized",
          "role": "list-engine"
        },
        {
          "id": "expandable-list-item",
          "role": "optional-row-ui"
        }
      ],
      "constraints": [
        "Import impact-nova/virtualized and impact-nova/expandable-list-item as separate subpaths",
        "ExpandableListItem is optional — any row JSX works inside VirtualizedListItem",
        "Use title/description on ExpandableListItem (not legacy sku/subtitle)",
        "Compound: VirtualizedList > Viewport > Content > Item; or hooks + manual DOM",
        "Expandable rows: getItemProps({ measure: isExpanded }); resetRowSize on collapse",
        "Storybook: Data Display/Virtualized List and Expandable List Item"
      ],
      "recipe": "virtualized-selectable-list"
    },
    {
      "id": "expandable-list-item-preset",
      "title": "Expandable list row (preset API)",
      "description": "Data-driven expandable row with title, description, and typed sections (metrics, attributes, custom)",
      "components": [
        {
          "id": "expandable-list-item",
          "role": "row"
        }
      ],
      "constraints": [
        "Preset: ExpandableListItem with title, description, sections, selection props",
        "Section types: metrics | attributes | custom (ExpandableListItemSection[])",
        "For custom layout use compound parts (ExpandableListItemRoot, Trigger, Content, …)"
      ],
      "recipe": "expandable-list-item-preset"
    },
    {
      "id": "expandable-list-item-compound",
      "title": "Expandable list row (compound API)",
      "description": "Radix-style composable row — Root, Row, Checkbox, Trigger, Content, Metrics, Attributes",
      "components": [
        {
          "id": "expandable-list-item",
          "role": "row"
        }
      ],
      "constraints": [
        "Compose ExpandableListItemRoot > Row > Checkbox + Trigger + Content",
        "Use when preset sections[] is too rigid",
        "Can nest inside impact-nova/virtualized VirtualizedListItem"
      ],
      "recipe": "expandable-list-item-compound"
    },
    {
      "id": "config-driven-dynamic-form",
      "title": "Config-driven dynamic form (ReactHooksForm)",
      "description": "JSON IFormConfig with visibilityDependency, disableDependency, and formContext.validateForm for bulk edit and settings",
      "components": [
        {
          "id": "form-react",
          "role": "form-engine"
        },
        {
          "id": "month-range-picker",
          "role": "period-fields"
        },
        {
          "id": "sheet",
          "role": "panel"
        }
      ],
      "constraints": [
        "Import ReactHooksForm from impact-nova/form-react",
        "Inject network via formContext.transport — Nova never calls HTTP",
        "disableDependency value __empty__ disables AND clears dependents when parent empties",
        "Storybook: Dynamic Form/ReactHooksForm (12 ItemSmart patterns)",
        "Guide: Dynamic Form/Guide · docs/guides/dynamic-form-framework.md",
        "MCP resource: impact-nova://dynamic-form-framework",
        "Fixtures: src/form-react/stories/fixtures/itemSmartProductionFormConfigs.ts"
      ],
      "recipe": "config-driven-dynamic-form"
    },
    {
      "id": "form-required-fields",
      "title": "Form required fields (isRequired)",
      "description": "Static mandatory fields on pickers, selects, and chips — no dependencies yet",
      "components": [
        {
          "id": "form-react",
          "role": "form-engine"
        },
        {
          "id": "chips",
          "role": "required-picker"
        },
        {
          "id": "select",
          "role": "required-select"
        }
      ],
      "constraints": [
        "isRequired: true blocks submit until field has a value",
        "Disabled fields skip required validation",
        "Storybook: Dynamic Form/ReactHooksForm/2. Required fields",
        "ItemSmart: seedWithFormConfig.constant.ts"
      ],
      "recipe": "form-required-fields"
    },
    {
      "id": "form-visibility-dependency",
      "title": "Form visibility dependency (conditional show)",
      "description": "Show/hide fields based on parent value — radio picker swap, filter hierarchy tabs",
      "components": [
        {
          "id": "form-react",
          "role": "form-engine"
        },
        {
          "id": "month-range-picker",
          "role": "period-variant"
        },
        {
          "id": "button-group",
          "role": "tab-selector"
        }
      ],
      "constraints": [
        "visibilityDependency: [{ fieldId, value }] — field hidden when rule not met",
        "Same field id for month_range + multi_month_picker variants; pair with includeOnlyVisibleFieldsInSubmit",
        "doNotIncludeInSubmit on mode radio toggles",
        "Storybook: Dynamic Form/ReactHooksForm/3. Visibility dependency",
        "ItemSmart: itemDetailsBulkEditFormConfig.ts, fullScenarioFilterConfig.ts"
      ],
      "recipe": "form-visibility-dependency"
    },
    {
      "id": "time-phased-metric-bulk-edit",
      "title": "Time-phased metric bulk edit",
      "description": "Month range or multi-month period paired with a numeric value field; value clears when period clears",
      "components": [
        {
          "id": "form-react",
          "role": "form-engine"
        },
        {
          "id": "month-range-picker",
          "role": "period"
        },
        {
          "id": "sheet",
          "role": "bulk-edit-panel"
        }
      ],
      "constraints": [
        "Value field: disableDependency [{ fieldId: periodFieldId, value: '__empty__' }]",
        "Pair with isRequired on value when period is set (client enrich if API omits)",
        "API ids: store_count + store_count_period; mock ids: store_count_value + store_count_month",
        "Auto-clear via useFieldVisibility when period empties",
        "Storybook: Dynamic Form/ReactHooksForm/4. Disable dependency",
        "Cross-field submit: formContext.validateForm — pattern form-validate-form-submit-gate"
      ],
      "recipe": "time-phased-metric-bulk-edit"
    },
    {
      "id": "form-validate-form-submit-gate",
      "title": "Form validateForm submit gate",
      "description": "Cross-field validation via formContext.validateForm — e.g. at least one bulk edit",
      "components": [
        {
          "id": "form-react",
          "role": "form-engine"
        },
        {
          "id": "sheet",
          "role": "bulk-edit-panel"
        }
      ],
      "constraints": [
        "formContext.validateForm returns { isValid, fieldErrors }",
        "Merged with field-level isRequired at submit; drives sendFormStateToParent meta.isSubmittable",
        "Storybook: Dynamic Form/ReactHooksForm/5. Item Details bulk edit validateForm",
        "ItemSmart: itemDetailsBulkEditSubmittable.utils.ts, ItemDetailsBulkEditPanel.tsx"
      ],
      "recipe": "form-validate-form-submit-gate"
    },
    {
      "id": "form-mutually-exclusive-fields",
      "title": "Form mutually exclusive fields",
      "description": "Two value paths — simulate numeric vs copy chips — disableDependency value null",
      "components": [
        {
          "id": "form-react",
          "role": "form-engine"
        },
        {
          "id": "chips",
          "role": "copy-source"
        },
        {
          "id": "numeric-combobox",
          "role": "simulate-value"
        }
      ],
      "constraints": [
        "disableDependency: [{ fieldId: otherField, value: null }] on each field",
        "Filling one disables and clears the other",
        "Storybook: Dynamic Form/ReactHooksForm/10. Scenario simulate",
        "ItemSmart: scenarioBulkEditFallbackFormConfig.constant.ts"
      ],
      "recipe": "form-mutually-exclusive-fields"
    },
    {
      "id": "form-switch-disable-bypass",
      "title": "Form switch disable bypass",
      "description": "Switch/checkbox disables sibling fields — grand total, Omni channel bypass",
      "components": [
        {
          "id": "form-react",
          "role": "form-engine"
        },
        {
          "id": "switch",
          "role": "bypass-toggle"
        }
      ],
      "constraints": [
        "disableDependency: [{ fieldId: switchId, value: 'true' }] on fields to bypass",
        "Storybook: 7. Planning grand total, 8. Planning channel cascade",
        "ItemSmart: bulkEditFormConfig.constant.ts"
      ],
      "recipe": "form-switch-disable-bypass"
    },
    {
      "id": "form-approval-hub-lock",
      "title": "Form approval hub lock selection",
      "description": "Lock checkbox disables date range and channel fields for global-filter period",
      "components": [
        {
          "id": "form-react",
          "role": "form-engine"
        },
        {
          "id": "checkbox",
          "role": "lock-toggle"
        },
        {
          "id": "month-range-picker",
          "role": "period"
        }
      ],
      "constraints": [
        "disableDependency: [{ fieldId: 'lock_complete_selection', value: 'true' }]",
        "Storybook: Dynamic Form/ReactHooksForm/9. Approval hub lock selection",
        "ItemSmart: approvalHubForm.ts"
      ],
      "recipe": "form-approval-hub-lock"
    },
    {
      "id": "filter-form-dependencies",
      "title": "Filter form dependency chain",
      "description": "Cascading disable/clear for region → country → store filters using disableDependency",
      "components": [
        {
          "id": "form-react",
          "role": "form-engine"
        },
        {
          "id": "filter-panel",
          "role": "shell"
        },
        {
          "id": "select",
          "role": "filters"
        }
      ],
      "constraints": [
        "FilterPanel UI is compound; ReactHooksForm optional for JSON-driven filter forms",
        "disableDependency __empty__ chains parent → child; parent isRequired common",
        "Storybook: Dynamic Form/ReactHooksForm/11. Filter disable chain",
        "See also: filter-and-table and multi-filter-workspace patterns",
        "ItemSmart: fullScenarioFilterConfig.ts, globalFilters.constant.ts"
      ],
      "recipe": "filter-form-dependencies"
    },
    {
      "id": "form-filter-visibility-hierarchy",
      "title": "Form filter visibility hierarchy",
      "description": "button_group selection method reveals hierarchy brand/dept/class fields",
      "components": [
        {
          "id": "form-react",
          "role": "form-engine"
        },
        {
          "id": "button-group",
          "role": "selection-method"
        },
        {
          "id": "filter-panel",
          "role": "shell"
        }
      ],
      "constraints": [
        "visibilityDependency on hierarchy fields when product_selection_method === hierarchy",
        "doNotIncludeInSubmit on selection method toggle",
        "Storybook: Dynamic Form/ReactHooksForm/12. Filter visibility hierarchy",
        "ItemSmart: fullScenarioFilterConfig.ts"
      ],
      "recipe": "form-filter-visibility-hierarchy"
    }
  ]
}
