{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "error-pages",
  "title": "Error Pages",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/error-pages/ErrorPages.tsx",
      "content": "'use client'\n\nimport type { ComponentProps, ReactNode } from 'react'\nimport { Clock, RotateCcw } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\n\nexport type ErrorPagesVariant = '404' | '500' | '403' | 'maintenance'\n\nexport interface ErrorPagesProps {\n  /** `'all'` renders the full gallery; a single variant renders just that screen. */\n  variant?: ErrorPagesVariant | 'all'\n  size?: 'sm' | 'default'\n  className?: string\n  title?: string\n  description?: string\n  /** Status numeral. Pass `''` to hide. */\n  code?: string\n  /** Eyebrow pill (maintenance ETA by default). Pass `''` to hide. */\n  tag?: string\n  /** Replaces the HTTP response panel on a single variant. Pass `''` to hide art. */\n  image?: string\n  imageAlt?: string\n  primaryLabel?: string\n  secondaryLabel?: string\n  primaryHref?: string\n  secondaryHref?: string\n  showPrimary?: boolean\n  showSecondary?: boolean\n  primaryDisabled?: boolean\n  secondaryDisabled?: boolean\n  onHome?: () => void\n  onSearch?: () => void\n  onRetry?: () => void\n  onStatus?: () => void\n  onSwitchAccount?: () => void\n  onRequestAccess?: () => void\n  onSubscribe?: () => void\n}\n\nconst copy = (fallback: string, override?: string) => (override === undefined ? fallback : override)\n\nfunction Action({\n  href,\n  onClick,\n  children,\n  ...buttonProps\n}: {\n  href?: string\n  onClick?: () => void\n  children: ReactNode\n} & Omit<ComponentProps<typeof Button>, 'onClick'>) {\n  if (href) {\n    return (\n      <Button asChild {...buttonProps}>\n        <a href={href} onClick={onClick}>\n          {children}\n        </a>\n      </Button>\n    )\n  }\n  return (\n    <Button {...buttonProps} onClick={onClick}>\n      {children}\n    </Button>\n  )\n}\n\nexport function ErrorPages({\n  variant = 'all',\n  size = 'default',\n  className,\n  title,\n  description,\n  code,\n  tag,\n  image,\n  imageAlt = '',\n  primaryLabel,\n  secondaryLabel,\n  primaryHref,\n  secondaryHref,\n  showPrimary = true,\n  showSecondary = true,\n  primaryDisabled = false,\n  secondaryDisabled = false,\n  onHome,\n  onSearch,\n  onRetry,\n  onStatus,\n  onSwitchAccount,\n  onRequestAccess,\n  onSubscribe,\n}: ErrorPagesProps) {\n  const pick = (v: ErrorPagesVariant, fallback: string, override?: string) =>\n    variant === v ? copy(fallback, override) : fallback\n\n  const frameClass = cn(\n    'border-border bg-card overflow-hidden rounded-xl border text-left',\n    size === 'sm' && 'rounded-lg',\n  )\n  const imgClass = 'aspect-[16/10] w-full object-cover'\n  const bodyClass = size === 'sm' ? 'p-5' : 'p-6'\n  const codeClass = cn('font-semibold tracking-tighter', size === 'sm' ? 'text-2xl' : 'text-4xl')\n  const titleClass = cn('mt-1.5 font-semibold tracking-tight', size === 'sm' ? 'text-base' : 'text-xl')\n  const descClass = 'text-muted-foreground mt-2 max-w-sm text-sm'\n  const actionsClass = cn('flex flex-wrap items-center gap-2', size === 'sm' ? 'mt-4' : 'mt-5')\n  const actionSize = size === 'sm' ? ('xs' as const) : ('sm' as const)\n\n  const show = (v: ErrorPagesVariant) => variant === 'all' || variant === v\n\n  const title404 = pick('404', 'Page not found', title)\n  const desc404 = pick(\n    '404',\n    \"The page you're looking for doesn't exist or was moved. Check the URL or head back home.\",\n    description,\n  )\n  const code404 = pick('404', '404', code)\n  const image404 = pick('404', '/illustrations/error-404.jpg', image)\n  const primary404 = pick('404', 'Go home', primaryLabel)\n  const secondary404 = pick('404', 'Search docs', secondaryLabel)\n\n  const title500 = pick('500', 'Internal server error', title)\n  const desc500 = pick(\n    '500',\n    'Something went wrong on our end. The team has been notified — try again in a moment.',\n    description,\n  )\n  const code500 = pick('500', '500', code)\n  const image500 = pick('500', '/illustrations/error-500.jpg', image)\n  const primary500 = pick('500', 'Retry', primaryLabel)\n  const secondary500 = pick('500', 'Status page', secondaryLabel)\n\n  const title403 = pick('403', 'Access denied', title)\n  const desc403 = pick(\n    '403',\n    \"You don't have permission to view this page. Switch accounts or ask an admin to request access.\",\n    description,\n  )\n  const code403 = pick('403', '403', code)\n  const image403 = pick('403', '/illustrations/error-403.jpg', image)\n  const primary403 = pick('403', 'Request access', primaryLabel)\n  const secondary403 = pick('403', 'Switch account', secondaryLabel)\n\n  const title503 = pick('maintenance', 'Scheduled maintenance', title)\n  const desc503 = pick(\n    'maintenance',\n    \"We're upgrading our systems. The service will be back online shortly.\",\n    description,\n  )\n  const code503 = pick('maintenance', '503', code)\n  const image503 = pick('maintenance', '/illustrations/error-maintenance.jpg', image)\n  const tag503 = pick('maintenance', 'Back online around 14:00 UTC', tag)\n  const primary503 = pick('maintenance', 'Subscribe for updates', primaryLabel)\n  const secondary503 = variant === 'maintenance' ? (secondaryLabel ?? '') : (secondaryLabel ?? '')\n\n  return (\n    <div\n      data-slot=\"error-pages\"\n      data-size={size}\n      className={cn(variant === 'all' && 'grid gap-4 sm:grid-cols-2', className)}\n    >\n      {show('404') && (\n        <article className={frameClass} data-slot=\"error-page\" data-variant=\"404\" role=\"status\">\n          {image404 ? (\n            <img src={image404} alt={imageAlt} className={imgClass} />\n          ) : image404 === undefined ? (\n            <div className=\"border-border bg-muted/40 border-b font-mono\" aria-hidden=\"true\">\n              <div className=\"border-border text-muted-foreground truncate border-b px-3 py-2 text-xs\">\n                GET /pricing/teams\n              </div>\n              <div className=\"space-y-1 p-3 text-xs leading-relaxed\">\n                <p>\n                  <span className=\"text-muted-foreground\">HTTP/1.1</span> {code404 || '404'} Not Found\n                </p>\n                <p className=\"text-muted-foreground\">x-request-id: req_9k2e18</p>\n              </div>\n            </div>\n          ) : null}\n          <div className={bodyClass}>\n            {code404 ? <p className={codeClass}>{code404}</p> : null}\n            <h3 className={titleClass}>{title404}</h3>\n            <p className={descClass}>{desc404}</p>\n            {variant === '404' && tag ? (\n              <p className=\"text-muted-foreground mt-3 inline-flex items-center rounded-full border px-3 py-1 text-xs\">\n                {tag}\n              </p>\n            ) : null}\n            {showPrimary || showSecondary ? (\n              <div className={actionsClass}>\n                {showPrimary ? (\n                  <Action href={primaryHref} size={actionSize} disabled={primaryDisabled} onClick={onHome}>\n                    {primary404}\n                  </Action>\n                ) : null}\n                {showSecondary ? (\n                  <Action\n                    href={secondaryHref}\n                    size={actionSize}\n                    variant=\"ghost\"\n                    disabled={secondaryDisabled}\n                    onClick={onSearch}\n                  >\n                    {secondary404}\n                  </Action>\n                ) : null}\n              </div>\n            ) : null}\n          </div>\n        </article>\n      )}\n\n      {show('500') && (\n        <article className={frameClass} data-slot=\"error-page\" data-variant=\"500\" role=\"alert\">\n          {image500 ? (\n            <img src={image500} alt={imageAlt} className={imgClass} />\n          ) : image500 === undefined ? (\n            <div className=\"border-border bg-muted/40 border-b font-mono\" aria-hidden=\"true\">\n              <div className=\"border-border text-muted-foreground truncate border-b px-3 py-2 text-xs\">\n                POST /api/v1/invoices\n              </div>\n              <div className=\"space-y-1 p-3 text-xs leading-relaxed\">\n                <p>\n                  <span className=\"text-muted-foreground\">HTTP/1.1</span>{' '}\n                  <span className=\"text-destructive\">{code500 || '500'} Internal Server Error</span>\n                </p>\n                <p className=\"text-muted-foreground\">error: ECONNRESET at Worker.run:142</p>\n              </div>\n            </div>\n          ) : null}\n          <div className={bodyClass}>\n            {code500 ? <p className={codeClass}>{code500}</p> : null}\n            <h3 className={titleClass}>{title500}</h3>\n            <p className={descClass}>{desc500}</p>\n            {variant === '500' && tag ? (\n              <p className=\"text-muted-foreground mt-3 inline-flex items-center rounded-full border px-3 py-1 text-xs\">\n                {tag}\n              </p>\n            ) : null}\n            {showPrimary || showSecondary ? (\n              <div className={actionsClass}>\n                {showPrimary ? (\n                  <Action href={primaryHref} size={actionSize} disabled={primaryDisabled} onClick={onRetry}>\n                    <RotateCcw />\n                    {primary500}\n                  </Action>\n                ) : null}\n                {showSecondary ? (\n                  <Action\n                    href={secondaryHref}\n                    size={actionSize}\n                    variant=\"outline\"\n                    disabled={secondaryDisabled}\n                    onClick={onStatus}\n                  >\n                    {secondary500}\n                  </Action>\n                ) : null}\n              </div>\n            ) : null}\n          </div>\n        </article>\n      )}\n\n      {show('403') && (\n        <article className={frameClass} data-slot=\"error-page\" data-variant=\"403\" role=\"alert\">\n          {image403 ? (\n            <img src={image403} alt={imageAlt} className={imgClass} />\n          ) : image403 === undefined ? (\n            <div className=\"border-border bg-muted/40 border-b font-mono\" aria-hidden=\"true\">\n              <div className=\"border-border text-muted-foreground truncate border-b px-3 py-2 text-xs\">\n                GET /admin/billing\n              </div>\n              <div className=\"space-y-1 p-3 text-xs leading-relaxed\">\n                <p>\n                  <span className=\"text-muted-foreground\">HTTP/1.1</span>{' '}\n                  <span className=\"text-warning\">{code403 || '403'} Forbidden</span>\n                </p>\n                <p className=\"text-muted-foreground\">scope billing:read — denied for guest</p>\n              </div>\n            </div>\n          ) : null}\n          <div className={bodyClass}>\n            {code403 ? <p className={codeClass}>{code403}</p> : null}\n            <h3 className={titleClass}>{title403}</h3>\n            <p className={descClass}>{desc403}</p>\n            {variant === '403' && tag ? (\n              <p className=\"text-muted-foreground mt-3 inline-flex items-center rounded-full border px-3 py-1 text-xs\">\n                {tag}\n              </p>\n            ) : null}\n            {showPrimary || showSecondary ? (\n              <div className={actionsClass}>\n                {showSecondary ? (\n                  <Action\n                    href={secondaryHref}\n                    size={actionSize}\n                    variant=\"outline\"\n                    disabled={secondaryDisabled}\n                    onClick={onSwitchAccount}\n                  >\n                    {secondary403}\n                  </Action>\n                ) : null}\n                {showPrimary ? (\n                  <Action href={primaryHref} size={actionSize} disabled={primaryDisabled} onClick={onRequestAccess}>\n                    {primary403}\n                  </Action>\n                ) : null}\n              </div>\n            ) : null}\n          </div>\n        </article>\n      )}\n\n      {show('maintenance') && (\n        <article className={frameClass} data-slot=\"error-page\" data-variant=\"maintenance\" role=\"status\">\n          {image503 ? (\n            <img src={image503} alt={imageAlt} className={imgClass} />\n          ) : image503 === undefined ? (\n            <div className=\"border-border bg-muted/40 border-b font-mono\" aria-hidden=\"true\">\n              <div className=\"border-border text-muted-foreground truncate border-b px-3 py-2 text-xs\">GET /health</div>\n              <div className=\"space-y-1 p-3 text-xs leading-relaxed\">\n                <p>\n                  <span className=\"text-muted-foreground\">HTTP/1.1</span>{' '}\n                  <span className=\"text-warning\">{code503 || '503'} Service Unavailable</span>\n                </p>\n                <p className=\"text-muted-foreground\">Retry-After: 3600</p>\n              </div>\n            </div>\n          ) : null}\n          <div className={bodyClass}>\n            {code503 ? <p className={codeClass}>{code503}</p> : null}\n            <h3 className={titleClass}>{title503}</h3>\n            <p className={descClass}>{desc503}</p>\n            {tag503 ? (\n              <p className=\"text-muted-foreground mt-3 inline-flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs\">\n                <Clock className=\"size-3.5\" aria-hidden=\"true\" />\n                {tag503}\n              </p>\n            ) : null}\n            {showPrimary || (showSecondary && secondary503) ? (\n              <div className={actionsClass}>\n                {showPrimary ? (\n                  <Action\n                    href={primaryHref}\n                    size={actionSize}\n                    variant=\"ghost\"\n                    disabled={primaryDisabled}\n                    onClick={onSubscribe}\n                  >\n                    {primary503}\n                  </Action>\n                ) : null}\n                {showSecondary && secondary503 ? (\n                  <Action\n                    href={secondaryHref}\n                    size={actionSize}\n                    variant=\"outline\"\n                    disabled={secondaryDisabled}\n                    onClick={onStatus}\n                  >\n                    {secondary503}\n                  </Action>\n                ) : null}\n              </div>\n            ) : null}\n          </div>\n        </article>\n      )}\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "~/components/blocks/ErrorPages.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/button.json"
  ],
  "description": "Pack of four status screens — 404, 500, 403, and 503 — each with a matching isometric illustration, code, copy, and actions. `variant` picks a single screen, `size` compacts it. Override title, description, image, code, tag, labels, hrefs, disabled flags, and callbacks. Pass `image=\"\"` to hide the art.",
  "categories": [
    "layout",
    "marketing",
    "utility"
  ],
  "deprecated": true,
  "replacedBy": "error-page"
}