{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "scorecard-template",
  "type": "registry:block",
  "title": "Scorecard Template",
  "description": "Graded-evaluation page. Topbar + overall-grade header + per-dimension scorecard rows + optional methodology footnote + Footer.",
  "author": "ofri-peretz <https://github.com/ofri-peretz>",
  "categories": [
    "data",
    "template"
  ],
  "dependencies": [],
  "registryDependencies": [
    "https://ds.interlace.tools/r/theme.json",
    "https://ds.interlace.tools/r/cn.json",
    "https://ds.interlace.tools/r/container.json",
    "https://ds.interlace.tools/r/footer.json",
    "https://ds.interlace.tools/r/grade-badge.json",
    "https://ds.interlace.tools/r/scorecard-row.json",
    "https://ds.interlace.tools/r/section-boundary.json",
    "https://ds.interlace.tools/r/skeleton.json",
    "https://ds.interlace.tools/r/stack.json",
    "https://ds.interlace.tools/r/topbar.json",
    "https://ds.interlace.tools/r/typography.json"
  ],
  "files": [
    {
      "path": "registry/interlace-ui/templates/scorecard-template.tsx",
      "target": "components/ui/templates/scorecard-template.tsx",
      "type": "registry:block",
      "content": "import * as React from 'react';\n\n// @interlace/scorecard-template v1.1.0 — Interlace design system.\n// Docs, props and live preview: https://ds.interlace.tools/c/scorecard-template\n// What changed since: https://ds.interlace.tools/c/scorecard-template#history\n// Generated banner — keep it, the upgrade diff reads this version.\n\n/**\n * @interlace/ui — ScorecardTemplate\n *\n * Graded-evaluation page. Topbar + overall-grade header + per-dimension\n * scorecard rows + optional methodology footnote + Footer.\n *\n * Used by `/scorecard`, plugin scorecards, Lighthouse-style reports.\n * Each dimension row streams independently via SectionBoundary so the\n * overall header paints while individual dimension details are still\n * fetching.\n *\n * ## MIN_VIEWPORT — 320\n */\n\nimport { cn } from '@/lib/utils';\nimport { Container } from '@/components/ui/container';\nimport { GradeBadge, type GradeValue } from '@/components/ui/grade-badge';\nimport { SectionBoundary } from '@/components/ui/section-boundary';\nimport { Stack } from '@/components/ui/stack';\nimport { Typography } from '@/components/ui/typography';\nimport { Topbar } from '@/components/ui/patterns/topbar';\nimport { Footer } from '@/components/ui/patterns/footer';\nimport { ScorecardRow } from '@/components/ui/patterns/scorecard-row';\nimport { Skeleton } from '@/components/ui/skeleton';\n\nexport const MIN_VIEWPORT = 320 as const;\n\ninterface ScorecardDimension {\n  name: React.ReactNode;\n  grade: GradeValue;\n  score: number;\n  caption?: React.ReactNode;\n  details?: React.ReactNode;\n}\n\ninterface ScorecardTemplateProps extends Omit<React.ComponentProps<'div'>, 'title'> {\n  topbar: React.ComponentProps<typeof Topbar>;\n  /** Page title. */\n  title: React.ReactNode;\n  /** One-paragraph lead under the title. */\n  lead?: React.ReactNode;\n  /** Overall result — drives the hero grade pill at the top. */\n  overall?: {\n    grade: GradeValue;\n    score: number;\n    /** Optional caption next to the overall grade (e.g. \"92% pass rate\"). */\n    caption?: React.ReactNode;\n  };\n  /** Per-dimension scores. */\n  dimensions?: ScorecardDimension[];\n  /**\n   * Optional methodology footnote — explains how scores are computed.\n   * Rendered as a muted block under the body.\n   */\n  methodology?: React.ReactNode;\n  footer?: React.ComponentProps<typeof Footer>;\n}\n\nfunction ScorecardTemplate({\n  topbar,\n  title,\n  lead,\n  overall,\n  dimensions = [],\n  methodology,\n  footer,\n  className,\n  ...props\n}: ScorecardTemplateProps) {\n  return (\n    <div\n      data-slot=\"scorecard-template\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      className={cn('bg-background text-foreground', className)}\n      {...props}\n    >\n      <Topbar {...topbar} />\n\n      <main>\n        <Container size=\"content\">\n          <Stack gap=\"xl\" className=\"py-xl\">\n            <SectionBoundary name=\"scorecard-header\" skeletonVariant=\"page-header\">\n              <div className=\"flex flex-col gap-md md:flex-row md:items-center md:justify-between\">\n                <Stack gap=\"sm\">\n                  <Typography variant=\"h1\" as=\"h1\" className=\"text-balance\">\n                    {title}\n                  </Typography>\n                  {lead ? (\n                    <Typography variant=\"long\" tone=\"muted\" className=\"max-w-prose\">\n                      {lead}\n                    </Typography>\n                  ) : null}\n                </Stack>\n                {overall ? (\n                  <div className=\"flex flex-col items-end gap-xs\">\n                    <div className=\"flex items-baseline gap-sm\">\n                      <span className=\"font-body text-h1 font-bold tabular-nums leading-none\">\n                        {overall.score}\n                      </span>\n                      <GradeBadge grade={overall.grade} size=\"lg\" />\n                    </div>\n                    {overall.caption ? (\n                      <Typography variant=\"ui-sm\" tone=\"muted\">\n                        {overall.caption}\n                      </Typography>\n                    ) : null}\n                  </div>\n                ) : null}\n              </div>\n            </SectionBoundary>\n\n            <SectionBoundary\n              name=\"scorecard-dimensions\"\n              skeletonVariant=\"card\"\n            >\n              <Stack gap=\"md\">\n                {dimensions.map((dim, i) => (\n                  <ScorecardRow key={i} {...dim} />\n                ))}\n              </Stack>\n            </SectionBoundary>\n\n            {methodology ? (\n              <SectionBoundary\n                name=\"scorecard-methodology\"\n                skeletonVariant=\"text\"\n              >\n                <div className=\"border-border border-t pt-md\">\n                  <Typography variant=\"ui-sm\" tone=\"muted\">\n                    {methodology}\n                  </Typography>\n                </div>\n              </SectionBoundary>\n            ) : null}\n          </Stack>\n        </Container>\n      </main>\n\n      {footer ? <Footer {...footer} /> : null}\n    </div>\n  );\n}\nScorecardTemplate.displayName = 'ScorecardTemplate';\n\n/**\n * Page-level loading state — the full-page silhouette of\n * `<ScorecardTemplate>`, not a single rect. Rendered by the consumer while\n * the whole route's data is in flight (`loading.tsx` in Next.js), or as\n * a `<SectionBoundary skeleton={…}>` override.\n *\n * Shapes mirror the real layout so the swap is CLS-neutral (R23). One\n * `role=\"status\"` region for the page; inner skeletons pass\n * `label={null}` so screen readers hear one announcement, not ten.\n */\nfunction ScorecardTemplateSkeleton({\n  className,\n  ...props\n}: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"scorecard-template-skeleton\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      role=\"status\"\n      aria-busy=\"true\"\n      aria-label=\"Loading scorecard…\"\n      className={cn('bg-background text-foreground', className)}\n      {...props}\n    >\n      <Skeleton\n        variant=\"rect\"\n        className=\"h-14 w-full rounded-none\"\n        label={null}\n      />\n      <Container size=\"content\">\n        <Stack gap=\"xl\" className=\"py-xl\">\n          <Skeleton variant=\"page-header\" label={null} />\n          <Skeleton variant=\"card\" count={4} label={null} />\n          <Skeleton variant=\"text\" label={null} />\n        </Stack>\n      </Container>\n    </div>\n  );\n}\nScorecardTemplateSkeleton.displayName = 'ScorecardTemplateSkeleton';\nScorecardTemplate.Skeleton = ScorecardTemplateSkeleton;\n\nexport { ScorecardTemplate };\nexport type { ScorecardTemplateProps, ScorecardDimension };\n"
    }
  ],
  "meta": {
    "tier": "template",
    "client": false,
    "minViewport": 320,
    "loading": false,
    "version": "1.1.0",
    "since": "1.0.0"
  },
  "docs": "## @interlace/scorecard-template\n\nInstalled to `components/ui/templates/scorecard-template.tsx`.\n\n```tsx\nimport { /* … */ } from '@/components/ui/templates/scorecard-template';\n```\n\nProps, a11y contract, live preview and source: https://ds.interlace.tools/c/scorecard-template\n\nRequires the `@interlace/theme` CSS baseline (installed automatically as a registry dependency)."
}
