{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "error-template",
  "type": "registry:block",
  "title": "Error Template",
  "description": "Full-page error surface — 404 / 500 / 503 / generic. Centred column with the status code + title + description + action buttons (back home, contact support, retry).",
  "author": "ofri-peretz <https://github.com/ofri-peretz>",
  "categories": [
    "feedback",
    "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/section-boundary.json",
    "https://ds.interlace.tools/r/skeleton.json",
    "https://ds.interlace.tools/r/stack.json",
    "https://ds.interlace.tools/r/typography.json"
  ],
  "files": [
    {
      "path": "registry/interlace-ui/templates/error-template.tsx",
      "target": "components/ui/templates/error-template.tsx",
      "type": "registry:block",
      "content": "import * as React from 'react';\n\n// @interlace/error-template v1.1.0 — Interlace design system.\n// Docs, props and live preview: https://ds.interlace.tools/c/error-template\n// What changed since: https://ds.interlace.tools/c/error-template#history\n// Generated banner — keep it, the upgrade diff reads this version.\n\n/**\n * @interlace/ui — ErrorTemplate\n *\n * Full-page error surface — 404 / 500 / 503 / generic. Centred column\n * with the status code + title + description + action buttons (back home,\n * contact support, retry).\n *\n * One template, four variants — pick via `variant`. Pass `actions` for\n * the CTA cluster.\n *\n * ## MIN_VIEWPORT — 320\n */\n\nimport { cn } from '@/lib/utils';\nimport { Container } from '@/components/ui/container';\nimport { SectionBoundary } from '@/components/ui/section-boundary';\nimport { Stack } from '@/components/ui/stack';\nimport { Typography } from '@/components/ui/typography';\nimport { Skeleton } from '@/components/ui/skeleton';\n\nexport const MIN_VIEWPORT = 320 as const;\n\ntype ErrorVariant = '404' | '500' | '503' | 'generic';\n\ninterface ErrorTemplateProps extends Omit<React.ComponentProps<'main'>, 'title'> {\n  variant?: ErrorVariant;\n  /** Override the default status code displayed. */\n  statusCode?: React.ReactNode;\n  /** Title. Defaults per `variant`. */\n  title?: React.ReactNode;\n  /** Description. Defaults per `variant`. */\n  description?: React.ReactNode;\n  /** Action button row (typically Back home + Contact). */\n  actions?: React.ReactNode;\n}\n\nconst DEFAULTS: Record<\n  ErrorVariant,\n  { code: string; title: string; description: string }\n> = {\n  '404': {\n    code: '404',\n    title: 'Page not found',\n    description:\n      \"We couldn't find the page you were looking for. It may have moved, or never existed.\",\n  },\n  '500': {\n    code: '500',\n    title: 'Something went wrong',\n    description:\n      'An unexpected error occurred on our end. Try again, and if it keeps happening, let us know.',\n  },\n  '503': {\n    code: '503',\n    title: 'We\\'ll be right back',\n    description:\n      'The site is undergoing maintenance. Please check back in a few minutes.',\n  },\n  generic: {\n    code: '!',\n    title: 'Something went wrong',\n    description: 'An unexpected error occurred.',\n  },\n};\n\nfunction ErrorTemplate({\n  variant = '404',\n  statusCode,\n  title,\n  description,\n  actions,\n  className,\n  ...props\n}: ErrorTemplateProps) {\n  const fallback = DEFAULTS[variant];\n  return (\n    <main\n      data-slot=\"error-template\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      data-variant={variant}\n      className={cn(\n        'bg-background flex min-h-screen items-center justify-center py-xl',\n        className,\n      )}\n      {...props}\n    >\n      <Container size=\"prose\">\n        <SectionBoundary name=\"error-body\" skeletonVariant=\"card\">\n          <Stack gap=\"lg\" align=\"center\" className=\"text-center\">\n            <div\n              aria-hidden\n              className=\"text-primary font-body text-h1 font-bold tracking-display\"\n            >\n              {statusCode ?? fallback.code}\n            </div>\n            <Typography variant=\"h2\" as=\"h1\" className=\"text-balance\">\n              {title ?? fallback.title}\n            </Typography>\n            <Typography\n              variant=\"long\"\n              tone=\"muted\"\n              className=\"max-w-prose\"\n            >\n              {description ?? fallback.description}\n            </Typography>\n            {actions ? (\n              <div className=\"mt-md flex flex-col items-center gap-sm sm:flex-row\">\n                {actions}\n              </div>\n            ) : null}\n          </Stack>\n        </SectionBoundary>\n      </Container>\n    </main>\n  );\n}\nErrorTemplate.displayName = 'ErrorTemplate';\n\n/**\n * Page-level loading state — the full-page silhouette of\n * `<ErrorTemplate>`, 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 ErrorTemplateSkeleton({\n  className,\n  ...props\n}: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"error-template-skeleton\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      role=\"status\"\n      aria-busy=\"true\"\n      aria-label=\"Loading…\"\n      className={cn(\n        'bg-background flex min-h-screen items-center justify-center py-xl',\n        className,\n      )}\n      {...props}\n    >\n      <Container size=\"prose\">\n        <Stack gap=\"lg\" align=\"center\">\n          <Skeleton variant=\"page-header\" label={null} />\n          <Skeleton variant=\"button\" label={null} />\n        </Stack>\n      </Container>\n    </div>\n  );\n}\nErrorTemplateSkeleton.displayName = 'ErrorTemplateSkeleton';\nErrorTemplate.Skeleton = ErrorTemplateSkeleton;\n\nexport { ErrorTemplate };\nexport type { ErrorTemplateProps, ErrorVariant };\n"
    }
  ],
  "meta": {
    "tier": "template",
    "client": false,
    "minViewport": 320,
    "loading": false,
    "version": "1.1.0",
    "since": "1.0.0"
  },
  "docs": "## @interlace/error-template\n\nInstalled to `components/ui/templates/error-template.tsx`.\n\n```tsx\nimport { /* … */ } from '@/components/ui/templates/error-template';\n```\n\nProps, a11y contract, live preview and source: https://ds.interlace.tools/c/error-template\n\nRequires the `@interlace/theme` CSS baseline (installed automatically as a registry dependency)."
}
