{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dashboard-template",
  "type": "registry:block",
  "title": "Dashboard Template",
  "description": "Application dashboard surface. Topbar at top, persistent left sidebar (nav links), main content area (children). The standard \"logged-in app\" layout: every SaaS dashboard reaches for this shape.",
  "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/section-boundary.json",
    "https://ds.interlace.tools/r/skeleton.json",
    "https://ds.interlace.tools/r/stack.json",
    "https://ds.interlace.tools/r/topbar.json"
  ],
  "files": [
    {
      "path": "registry/interlace-ui/templates/dashboard-template.tsx",
      "target": "components/ui/templates/dashboard-template.tsx",
      "type": "registry:block",
      "content": "import * as React from 'react';\n\n// @interlace/dashboard-template v1.1.0 — Interlace design system.\n// Docs, props and live preview: https://ds.interlace.tools/c/dashboard-template\n// What changed since: https://ds.interlace.tools/c/dashboard-template#history\n// Generated banner — keep it, the upgrade diff reads this version.\n\n/**\n * @interlace/ui — DashboardTemplate\n *\n * Application dashboard surface. Topbar at top, persistent left sidebar\n * (nav links), main content area (children). The standard\n * \"logged-in app\" layout: every SaaS dashboard reaches for this shape.\n *\n * ## MIN_VIEWPORT — 480\n *\n * Below 480, the sidebar collapses (consumer wires a Sheet+Drawer for\n * the hamburger menu). Above 480 it stays persistent.\n */\n\nimport { cn } from '@/lib/utils';\nimport { SectionBoundary } from '@/components/ui/section-boundary';\nimport { Topbar } from '@/components/ui/patterns/topbar';\nimport { Skeleton } from '@/components/ui/skeleton';\nimport { Stack } from '@/components/ui/stack';\n\nexport const MIN_VIEWPORT = 480 as const;\n\ninterface DashboardTemplateProps extends React.ComponentProps<'div'> {\n  topbar: React.ComponentProps<typeof Topbar>;\n  /** Sidebar nav (typically a list of links). */\n  sidebar: React.ReactNode;\n  /** Page heading row (above the main content). */\n  header?: React.ReactNode;\n  /** Main content area. */\n  children: React.ReactNode;\n}\n\nfunction DashboardTemplate({\n  topbar,\n  sidebar,\n  header,\n  children,\n  className,\n  ...props\n}: DashboardTemplateProps) {\n  return (\n    <div\n      data-slot=\"dashboard-template\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      className={cn(\n        'bg-background text-foreground flex min-h-screen flex-col',\n        className,\n      )}\n      {...props}\n    >\n      <Topbar {...topbar} />\n\n      <div className=\"flex flex-1\">\n        <aside\n          className=\"border-border bg-card hidden w-60 shrink-0 border-r md:block\"\n          aria-label=\"Primary navigation\"\n        >\n          <SectionBoundary name=\"dashboard-sidebar\" skeletonVariant=\"card\">\n            {sidebar}\n          </SectionBoundary>\n        </aside>\n\n        <main className=\"flex-1 px-lg py-lg\">\n          {header ? (\n            <SectionBoundary\n              name=\"dashboard-header\"\n              skeletonVariant=\"page-header\"\n              className=\"mb-lg\"\n            >\n              {header}\n            </SectionBoundary>\n          ) : null}\n          <SectionBoundary name=\"dashboard-body\" skeletonVariant=\"card\">\n            {children}\n          </SectionBoundary>\n        </main>\n      </div>\n    </div>\n  );\n}\nDashboardTemplate.displayName = 'DashboardTemplate';\n\n/**\n * Page-level loading state — the full-page silhouette of\n * `<DashboardTemplate>`, 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 DashboardTemplateSkeleton({\n  className,\n  ...props\n}: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"dashboard-template-skeleton\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      role=\"status\"\n      aria-busy=\"true\"\n      aria-label=\"Loading dashboard…\"\n      className={cn(\n        'bg-background text-foreground flex min-h-screen flex-col',\n        className,\n      )}\n      {...props}\n    >\n      <Skeleton\n        variant=\"rect\"\n        className=\"h-14 w-full rounded-none\"\n        label={null}\n      />\n      <div className=\"flex flex-1\">\n        <div className=\"border-border hidden w-60 shrink-0 border-r p-md md:block\">\n          <Skeleton variant=\"text\" count={6} label={null} />\n        </div>\n        <div className=\"flex-1 px-lg py-lg\">\n          <Stack gap=\"lg\">\n            <Skeleton variant=\"page-header\" label={null} />\n            <Skeleton variant=\"card\" count={2} label={null} />\n          </Stack>\n        </div>\n      </div>\n    </div>\n  );\n}\nDashboardTemplateSkeleton.displayName = 'DashboardTemplateSkeleton';\nDashboardTemplate.Skeleton = DashboardTemplateSkeleton;\n\nexport { DashboardTemplate };\nexport type { DashboardTemplateProps };\n"
    }
  ],
  "meta": {
    "tier": "template",
    "client": false,
    "minViewport": 480,
    "loading": false,
    "version": "1.1.0",
    "since": "1.0.0"
  },
  "docs": "## @interlace/dashboard-template\n\nInstalled to `components/ui/templates/dashboard-template.tsx`.\n\n```tsx\nimport { /* … */ } from '@/components/ui/templates/dashboard-template';\n```\n\nProps, a11y contract, live preview and source: https://ds.interlace.tools/c/dashboard-template\n\nRequires the `@interlace/theme` CSS baseline (installed automatically as a registry dependency)."
}
