{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "how-it-works-tabbed-steps",
  "title": "How It Works — Tabbed Steps",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/how-it-works-tabbed-steps/how-it-works-tabbed-steps.component.ts",
      "content": "// Step explainer where a vertical tab list of stages swaps a paired detail panel showing\n// the action, the expected result, and a primitive-built screen for that step.\n// Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, signal } from '@angular/core'\nimport { Check, LucideAngularModule } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiCardComponent, UiCardContentComponent } from '@/ui/card/card.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport {\n  UiTabsComponent,\n  UiTabsContentComponent,\n  UiTabsListComponent,\n  UiTabsTriggerComponent,\n} from '@/ui/tabs/tabs.component'\n\nexport interface TabbedStepRow {\n  name: string\n  detail: string\n}\n\nexport interface TabbedStep {\n  id: string\n  label: string\n  action: string\n  result: string\n  rows: TabbedStepRow[]\n}\n\nconst steps: TabbedStep[] = [\n  {\n    id: 'connect',\n    label: 'Connect',\n    action: 'Point us at the warehouse with a read-only role.',\n    result: 'Schema mirrored, 412 tables catalogued, nothing copied out.',\n    rows: [\n      { name: 'warehouse.orders', detail: '2.4M rows' },\n      { name: 'warehouse.refunds', detail: '88k rows' },\n      { name: 'warehouse.fx_rates', detail: 'daily' },\n    ],\n  },\n  {\n    id: 'define',\n    label: 'Define',\n    action: 'Author the metric as a file and open a pull request.',\n    result: 'Reviewed by its owner, with a diff and a revert path.',\n    rows: [\n      { name: 'revenue_net', detail: 'finance-analytics' },\n      { name: 'margin_by_channel', detail: 'finance-analytics' },\n      { name: 'pipeline_weighted', detail: 'revops' },\n    ],\n  },\n  {\n    id: 'certify',\n    label: 'Certify',\n    action: 'Reconcile the definition against the prior four quarters.',\n    result: 'Sign-off recorded; the metric can now be published.',\n    rows: [\n      { name: 'Q4 2025', detail: 'matched' },\n      { name: 'Q3 2025', detail: 'matched' },\n      { name: 'Q2 2025', detail: 'matched' },\n    ],\n  },\n  {\n    id: 'publish',\n    label: 'Publish',\n    action: 'Release to every consumer at once.',\n    result: 'Dashboards, exports, and the API resolve the same number.',\n    rows: [\n      { name: 'Exec summary', detail: 'live' },\n      { name: 'Finance close pack', detail: 'live' },\n      { name: 'Partner API', detail: 'live' },\n    ],\n  },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-how-it-works-tabbed-steps, [ui-how-it-works-tabbed-steps]',\n  standalone: true,\n  // React renders the root <section> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiSeparatorComponent,\n    UiTabsComponent,\n    UiTabsContentComponent,\n    UiTabsListComponent,\n    UiTabsTriggerComponent,\n  ],\n  template: `\n    <section data-slot=\"how-it-works-tabbed-steps\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-6xl px-6 py-20 lg:py-28\">\n        <div class=\"max-w-2xl\">\n          <span ui-badge variant=\"secondary\">How it works</span>\n          <h2 class=\"mt-4 text-3xl font-semibold tracking-tight sm:text-4xl\">Pick a stage to see what it produces</h2>\n        </div>\n\n        <ui-tabs [value]=\"activeStep()\" (valueChange)=\"setActiveStep($event)\" orientation=\"vertical\" class=\"mt-10\">\n          <div class=\"grid gap-8 lg:grid-cols-[16rem_1fr] lg:gap-12\">\n            <!-- Vertical tab rail: orientation is set on both list and triggers so\n                 arrow keys move up and down rather than left and right. -->\n            <ui-tabs-list variant=\"underline\" orientation=\"vertical\" class=\"h-auto w-full flex-col items-stretch\">\n              @for (step of allSteps; track step.id; let index = $index) {\n                <button\n                  ui-tabs-trigger\n                  [value]=\"step.id\"\n                  variant=\"underline\"\n                  orientation=\"vertical\"\n                  class=\"justify-start gap-3\"\n                >\n                  <span class=\"text-muted-foreground font-mono text-xs\">{{ pad(index + 1) }}</span>\n                  {{ step.label }}\n                </button>\n              }\n            </ui-tabs-list>\n\n            @for (step of allSteps; track step.id) {\n              <ui-tabs-content [value]=\"step.id\" class=\"mt-0\">\n                <!-- min-h keeps the panel from collapsing between stages. -->\n                <div class=\"grid min-h-[20rem] gap-6 sm:grid-cols-2\">\n                  <div>\n                    <p class=\"text-muted-foreground text-sm\">You do</p>\n                    <p class=\"mt-1.5 text-lg leading-snug font-medium text-balance\">{{ step.action }}</p>\n\n                    <ui-separator class=\"my-5\" />\n\n                    <p class=\"text-muted-foreground text-sm\">You get</p>\n                    <p class=\"mt-1.5 flex items-start gap-2 text-sm leading-relaxed\">\n                      <lucide-icon [img]=\"Check\" class=\"text-primary mt-0.5 size-4 shrink-0\" aria-hidden=\"true\" />\n                      <span>{{ step.result }}</span>\n                    </p>\n\n                    <button ui-button variant=\"link\" class=\"mt-5 h-auto p-0\">Read this step in the docs</button>\n                  </div>\n\n                  <div ui-card class=\"self-start\">\n                    <div ui-card-content class=\"p-0\">\n                      <div class=\"border-border text-muted-foreground border-b px-4 py-2.5 font-mono text-xs\">\n                        {{ step.label }}\n                      </div>\n                      <ul class=\"divide-border divide-y\">\n                        @for (row of step.rows; track row.name) {\n                          <li class=\"flex items-center justify-between gap-4 px-4 py-2.5\">\n                            <span class=\"min-w-0 truncate font-mono text-xs\">{{ row.name }}</span>\n                            <span class=\"text-muted-foreground shrink-0 text-xs\">{{ row.detail }}</span>\n                          </li>\n                        }\n                      </ul>\n                    </div>\n                  </div>\n                </div>\n              </ui-tabs-content>\n            }\n          </div>\n        </ui-tabs>\n      </div>\n    </section>\n  `,\n})\nexport class UiHowItWorksTabbedStepsComponent {\n  protected readonly Check = Check\n  protected readonly allSteps = steps\n\n  @Input() set defaultStep(v: string) {\n    if (steps.some((step) => step.id === v)) this.activeStep.set(v)\n  }\n  @Input('class') className?: string\n\n  readonly activeStep = signal('connect')\n\n  get rootClass(): string {\n    return cn('bg-background', this.className)\n  }\n\n  pad(n: number): string {\n    return String(n).padStart(2, '0')\n  }\n\n  setActiveStep(value: string): void {\n    if (steps.some((step) => step.id === value)) this.activeStep.set(value)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/how-it-works-tabbed-steps/how-it-works-tabbed-steps.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/how-it-works-tabbed-steps/index.ts",
      "content": "export {\n  UiHowItWorksTabbedStepsComponent,\n  type TabbedStep,\n  type TabbedStepRow,\n} from './how-it-works-tabbed-steps.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/how-it-works-tabbed-steps/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/separator.json",
    "https://uipkge.dev/r/angular/tabs.json"
  ],
  "description": "Step explainer where a vertical tab list of stages swaps a paired detail panel showing the action, the expected result, and a primitive-built screen for that step.",
  "categories": [
    "marketing"
  ]
}