{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "pricing-matrix-sticky-header",
  "title": "Pricing — Sticky Header Matrix",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/pricing-matrix-sticky-header/pricing-matrix-sticky-header.component.ts",
      "content": "// Long feature matrix whose plan header row pins to the top while the body scrolls,\n// so the column a checkmark belongs to stays identifiable at any scroll depth.\n// Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input } from '@angular/core'\nimport { Check, LucideAngularModule, Minus } 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 {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport interface PricingStickyRow {\n  feature: string\n  values: (boolean | string)[]\n}\n\nconst plans = ['Team', 'Business', 'Enterprise']\n\n// Cells are true / false / a string, so a plan can state a limit rather than\n// only claiming a feature exists.\nconst rows: PricingStickyRow[] = [\n  { feature: 'Certified metric definitions', values: ['50', '500', 'Unlimited'] },\n  { feature: 'Connected warehouses', values: ['1', '3', 'Unlimited'] },\n  { feature: 'Query budget per team', values: [false, true, true] },\n  { feature: 'Row-level access control', values: [false, true, true] },\n  { feature: 'SCIM provisioning', values: [false, true, true] },\n  { feature: 'Audit log export', values: [false, '90 days', 'Unlimited'] },\n  { feature: 'Period locking', values: [false, true, true] },\n  { feature: 'Embedded dashboards', values: [false, true, true] },\n  { feature: 'Data residency choice', values: [false, false, true] },\n  { feature: 'Customer-managed keys', values: [false, false, true] },\n  { feature: 'Private link', values: [false, false, true] },\n  { feature: 'Named support engineer', values: [false, false, true] },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-pricing-matrix-sticky-header, [ui-pricing-matrix-sticky-header]',\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    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <section data-slot=\"pricing-matrix-sticky-header\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-4xl px-6 py-20 lg:py-28\">\n        <span ui-badge variant=\"secondary\">Compare plans</span>\n        <h2 class=\"mt-4 text-3xl font-semibold tracking-tight sm:text-4xl\">Every line, no asterisks</h2>\n        <p class=\"text-muted-foreground mt-3 text-lg\">\n          Limits differ between plans. Where a plan caps something, the cap is written in the cell.\n        </p>\n\n        <div ui-card class=\"mt-8\">\n          <div ui-card-content class=\"p-0\">\n            <!-- The header pins with CSS alone. Thirty rows down, a checkmark is\n                 still attributable to a column without scrolling back up. -->\n            <div class=\"max-h-[28rem] overflow-auto\">\n              <table ui-table>\n                <thead ui-table-header class=\"bg-card sticky top-0 z-10\">\n                  <tr ui-table-row>\n                    <th ui-table-head class=\"bg-card\">Capability</th>\n                    @for (plan of plans; track plan) {\n                      <th ui-table-head class=\"bg-card text-center\">{{ plan }}</th>\n                    }\n                  </tr>\n                </thead>\n                <tbody ui-table-body>\n                  @for (row of rows; track row.feature) {\n                    <tr ui-table-row>\n                      <td ui-table-cell class=\"font-medium\">{{ row.feature }}</td>\n                      @for (value of row.values; track $index) {\n                        <td ui-table-cell class=\"text-center\">\n                          @if (value === true) {\n                            <lucide-icon [img]=\"Check\" class=\"text-success mx-auto size-4\" aria-hidden=\"true\" />\n                            <span class=\"sr-only\">Included</span>\n                          } @else if (value === false) {\n                            <lucide-icon\n                              [img]=\"Minus\"\n                              class=\"text-muted-foreground/50 mx-auto size-4\"\n                              aria-hidden=\"true\"\n                            />\n                            <span class=\"sr-only\">Not included</span>\n                          } @else {\n                            <span class=\"font-mono text-xs\">{{ value }}</span>\n                          }\n                        </td>\n                      }\n                    </tr>\n                  }\n                </tbody>\n              </table>\n            </div>\n          </div>\n        </div>\n\n        <div class=\"mt-6 flex flex-wrap gap-3\">\n          <button ui-button>Start on Team</button>\n          <button ui-button variant=\"outline\">Talk about Enterprise</button>\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiPricingMatrixStickyHeaderComponent {\n  protected readonly Check = Check\n  protected readonly Minus = Minus\n\n  readonly plans = plans\n  readonly rows = rows\n\n  @Input('class') className?: string\n\n  get rootClass(): string {\n    return cn('bg-background', this.className)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/pricing-matrix-sticky-header/pricing-matrix-sticky-header.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/pricing-matrix-sticky-header/index.ts",
      "content": "export { UiPricingMatrixStickyHeaderComponent, type PricingStickyRow } from './pricing-matrix-sticky-header.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/pricing-matrix-sticky-header/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/table.json"
  ],
  "description": "Long feature matrix whose plan header row pins to the top while the body scrolls, so the column a checkmark belongs to stays identifiable at any scroll depth.",
  "categories": [
    "marketing"
  ],
  "deprecated": true,
  "replacedBy": "pricing"
}