{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hero-dashboard-01",
  "title": "Hero Dashboard Preview",
  "description": "A serif headline, a short pitch, and one call to action over a framed product dashboard on a soft photo wash",
  "dependencies": [
    "class-variance-authority",
    "lucide-react@1",
    "motion@13"
  ],
  "registryDependencies": [
    "https://ui.cortexcn.dev/r/utils.json",
    "avatar",
    "badge",
    "button",
    "card",
    "separator"
  ],
  "files": [
    {
      "path": "registry/blocks/hero-dashboard-01/components/hero-dashboard.tsx",
      "content": "\"use client\";\n\nimport { motion, useReducedMotion, type Variants } from \"motion/react\";\nimport type { ReactNode } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport { Cta, type CtaProps } from \"./hero-cta\";\nimport { DashboardDemo } from \"./hero-dashboard-demo\";\n\n// Cortexcn item \"hero-dashboard-01\", revision 27fff60c5fe5, MIT license.\n// https://ui.cortexcn.dev/r/v/hero-dashboard-01/27fff60c5fe5.json\n\nexport interface HeroDashboardProps {\n  title?: string;\n  /** Starts on its own line under the title. */\n  titleLine2?: string;\n  description?: string;\n  /** Photo behind the product preview, softened by a gradient. */\n  washImage?: string;\n  animation?: \"none\" | \"subtle\";\n  primaryCTA?: CtaProps;\n  variant?: \"standard\" | \"compact\";\n}\n\nconst DEFAULTS = {\n  title: \"Every metric that matters,\",\n  titleLine2: \"in one clear view.\",\n  description:\n    \"Track revenue, users, and activity in real time, with no setup and no spreadsheets.\",\n  // Sample photo from Unsplash (free to use under the Unsplash License).\n  washImage:\n    \"https://images.unsplash.com/photo-1578301978018-3005759f48f7?q=80&w=1144&auto=format&fit=crop\",\n  primaryCTA: {\n    ctaEnabled: true,\n    text: \"Start free\",\n    link: \"\",\n    variant: \"default\",\n    size: \"default\",\n  },\n} satisfies HeroDashboardProps;\n\nconst variantStyles = {\n  standard: {\n    section: \"py-20 sm:py-28\",\n    title: \"text-3xl sm:text-4xl md:text-5xl\",\n    description: \"max-w-md text-sm sm:text-base\",\n    header: \"gap-5\",\n    content: \"gap-14 sm:gap-20\",\n  },\n  compact: {\n    section: \"py-14 sm:py-20\",\n    title: \"text-2xl sm:text-3xl md:text-4xl\",\n    description: \"max-w-sm text-sm\",\n    header: \"gap-4\",\n    content: \"gap-10 sm:gap-14\",\n  },\n} as const;\n\nconst container: Variants = {\n  hidden: {},\n  visible: { transition: { staggerChildren: 0.1, delayChildren: 0.05 } },\n};\n\nconst item: Variants = {\n  hidden: { opacity: 0, y: 12, filter: \"blur(6px)\" },\n  visible: {\n    opacity: 1,\n    y: 0,\n    filter: \"blur(0px)\",\n    transition: { duration: 0.5, ease: [0.22, 1, 0.36, 1] },\n  },\n};\n\nconst mediaItem: Variants = {\n  hidden: { opacity: 0, y: 24, filter: \"blur(8px)\" },\n  visible: {\n    opacity: 1,\n    y: 0,\n    filter: \"blur(0px)\",\n    transition: { duration: 0.6, ease: [0.22, 1, 0.36, 1] },\n  },\n};\n\nfunction Reveal({\n  active,\n  variants,\n  className,\n  children,\n}: Readonly<{\n  active: boolean;\n  variants?: Variants;\n  className?: string;\n  children: ReactNode;\n}>) {\n  if (!active) {\n    return <div className={className}>{children}</div>;\n  }\n\n  return (\n    <motion.div className={className} variants={variants ?? item}>\n      {children}\n    </motion.div>\n  );\n}\n\n/**\n * A serif headline, a short pitch, and one call to action over a framed\n * product dashboard on a soft photo wash.\n */\nexport function HeroDashboard({\n  title = DEFAULTS.title,\n  titleLine2 = DEFAULTS.titleLine2,\n  description = DEFAULTS.description,\n  washImage = DEFAULTS.washImage,\n  animation = \"subtle\",\n  primaryCTA = DEFAULTS.primaryCTA,\n  variant = \"standard\",\n}: Readonly<HeroDashboardProps>) {\n  const reduce = useReducedMotion();\n  const animate = animation === \"subtle\" && !reduce;\n  const vs = variantStyles[variant];\n\n  return (\n    <section className=\"relative isolate w-full overflow-hidden bg-background\">\n      <motion.div\n        className={cn(\n          \"relative z-10 mx-auto flex max-w-6xl flex-col px-6\",\n          vs.section,\n          vs.content,\n        )}\n        initial={animate ? \"hidden\" : false}\n        variants={animate ? container : undefined}\n        viewport={{ once: true, margin: \"-80px\" }}\n        whileInView={animate ? \"visible\" : undefined}\n      >\n        <Reveal\n          active={animate}\n          className={cn(\"flex max-w-2xl flex-col items-start\", vs.header)}\n        >\n          {title && (\n            <h1\n              className={cn(\n                \"text-balance font-normal font-serif text-foreground tracking-tight\",\n                vs.title,\n              )}\n            >\n              {title}\n              {titleLine2 && (\n                <>\n                  <br />\n                  {titleLine2}\n                </>\n              )}\n            </h1>\n          )}\n          {description && (\n            <p\n              className={cn(\n                \"text-balance text-muted-foreground\",\n                vs.description,\n              )}\n            >\n              {description}\n            </p>\n          )}\n          <Cta cta={primaryCTA} />\n        </Reveal>\n\n        <Reveal active={animate} className=\"w-full\" variants={mediaItem}>\n          <div className=\"relative w-full overflow-hidden rounded-md outline outline-black/10 dark:outline-white/10\">\n            {washImage && (\n              // biome-ignore lint/performance/noImgElement: framework-agnostic registry block\n              <img\n                alt=\"\"\n                aria-hidden=\"true\"\n                className=\"absolute inset-0 size-full object-cover\"\n                decoding=\"async\"\n                height={760}\n                src={washImage}\n                width={1144}\n              />\n            )}\n            <div className=\"absolute inset-0 bg-linear-to-b from-background/30 via-background/10 to-background/40\" />\n            <div className=\"relative flex items-center justify-center px-6 py-12 sm:px-12 sm:py-16\">\n              <DashboardDemo />\n            </div>\n          </div>\n        </Reveal>\n      </motion.div>\n    </section>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/hero-dashboard.tsx"
    },
    {
      "path": "registry/blocks/hero-dashboard-01/components/hero-dashboard-demo.tsx",
      "content": "import {\n  Activity,\n  BarChart3,\n  Bell,\n  LayoutGrid,\n  Search,\n  Settings,\n  Users,\n} from \"lucide-react\";\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { Card } from \"@/components/ui/card\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { cn } from \"@/lib/utils\";\n\n// Cortexcn item \"hero-dashboard-01\", revision 27fff60c5fe5, MIT license.\n// https://ui.cortexcn.dev/r/v/hero-dashboard-01/27fff60c5fe5.json\n\nconst nav = [\n  { icon: LayoutGrid, label: \"Overview\", active: true },\n  { icon: BarChart3, label: \"Reports\", active: false },\n  { icon: Users, label: \"Customers\", active: false },\n  { icon: Activity, label: \"Activity\", active: false },\n  { icon: Settings, label: \"Settings\", active: false },\n];\n\nconst stats = [\n  { label: \"Revenue\", value: \"$48.2k\", trend: \"+12.4%\", up: true },\n  { label: \"Active users\", value: \"2,318\", trend: \"+4.1%\", up: true },\n  { label: \"Conversion\", value: \"3.6%\", trend: \"+0.8%\", up: true },\n  { label: \"Churn\", value: \"1.4%\", trend: \"-2.0%\", up: false },\n];\n\nconst bars = [\n  { month: \"Jan\", value: 42 },\n  { month: \"Feb\", value: 58 },\n  { month: \"Mar\", value: 36 },\n  { month: \"Apr\", value: 64 },\n  { month: \"May\", value: 48 },\n  { month: \"Jun\", value: 72 },\n  { month: \"Jul\", value: 55 },\n  { month: \"Aug\", value: 80 },\n  { month: \"Sep\", value: 61 },\n  { month: \"Oct\", value: 88 },\n  { month: \"Nov\", value: 70 },\n  { month: \"Dec\", value: 94 },\n];\n\nconst activity = [\n  {\n    src: \"https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=64&q=80\",\n    name: \"James Doe\",\n    action: \"upgraded to Pro\",\n    time: \"2m\",\n  },\n  {\n    src: \"https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=64&q=80\",\n    name: \"Sara Lin\",\n    action: \"invited 3 members\",\n    time: \"18m\",\n  },\n  {\n    src: \"https://images.unsplash.com/photo-1633332755192-727a05c4013d?w=64&q=80\",\n    name: \"Marcus Vale\",\n    action: \"connected Stripe\",\n    time: \"1h\",\n  },\n];\n\n/** A sample analytics app in a browser window, for the hero's media slot. */\nexport function DashboardDemo() {\n  return (\n    <div className=\"relative w-full max-w-4xl\">\n      <Card className=\"w-full gap-0 overflow-hidden bg-card p-0 shadow-2xl outline outline-black/10 dark:outline-white/10\">\n        {/* Window chrome */}\n        <div className=\"flex items-center gap-2 border-b px-3 py-2.5\">\n          <div className=\"flex shrink-0 gap-1.5\">\n            <span className=\"size-2.5 rounded-full bg-red-400/70\" />\n            <span className=\"size-2.5 rounded-full bg-amber-400/70\" />\n            <span className=\"size-2.5 rounded-full bg-emerald-400/70\" />\n          </div>\n          <div className=\"mx-auto flex h-6 w-full min-w-0 max-w-56 items-center gap-1.5 rounded-md bg-muted px-2 text-[10px] text-muted-foreground\">\n            <Search className=\"size-3 shrink-0\" />\n            <span className=\"truncate\">app.acme.com/overview</span>\n          </div>\n          <Avatar className=\"size-6 shrink-0\">\n            <AvatarImage\n              alt=\"\"\n              src=\"https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=64&q=80\"\n            />\n            <AvatarFallback className=\"text-[9px]\">JD</AvatarFallback>\n          </Avatar>\n        </div>\n\n        <div className=\"flex\">\n          {/* Sidebar */}\n          <div className=\"hidden w-44 shrink-0 flex-col gap-1 border-r p-3 sm:flex\">\n            <div className=\"mb-2 flex items-center gap-2 px-1\">\n              <div className=\"size-6 rounded-lg bg-primary/85\" />\n              <span className=\"font-semibold text-sm tracking-tight\">Acme</span>\n            </div>\n            {nav.map(({ icon: Icon, label, active }) => (\n              <div\n                className={cn(\n                  \"flex items-center gap-2 rounded-lg px-2 py-1.5 text-xs\",\n                  active\n                    ? \"bg-muted font-medium text-foreground\"\n                    : \"text-muted-foreground\",\n                )}\n                key={label}\n              >\n                <Icon className=\"size-3.5 shrink-0\" />\n                <span className=\"truncate\">{label}</span>\n              </div>\n            ))}\n          </div>\n\n          {/* Main */}\n          <div className=\"flex min-w-0 flex-1 flex-col gap-3 p-3 sm:p-4\">\n            {/* Header */}\n            <div className=\"flex items-center justify-between gap-2\">\n              <div className=\"flex min-w-0 flex-col gap-0.5\">\n                <span className=\"truncate font-semibold text-sm tracking-tight\">\n                  Overview\n                </span>\n                <span className=\"truncate text-[10px] text-muted-foreground\">\n                  Last 30 days · updated 2m ago\n                </span>\n              </div>\n              <div className=\"flex shrink-0 items-center gap-1.5\">\n                {/* Hidden on phones so the page title keeps its room. */}\n                <Button className=\"max-sm:hidden\" size=\"xs\" variant=\"outline\">\n                  Export\n                </Button>\n                <Button size=\"xs\">New report</Button>\n              </div>\n            </div>\n\n            {/* KPI row */}\n            <div className=\"grid grid-cols-2 gap-2 lg:grid-cols-4\">\n              {stats.map((stat) => (\n                <div\n                  className=\"min-w-0 rounded-lg border p-2.5\"\n                  key={stat.label}\n                >\n                  <span className=\"block truncate text-[9px] text-muted-foreground\">\n                    {stat.label}\n                  </span>\n                  <div className=\"mt-1 flex flex-wrap items-baseline justify-between gap-x-1\">\n                    <span className=\"font-semibold text-sm tabular-nums\">\n                      {stat.value}\n                    </span>\n                    <span\n                      className={cn(\n                        \"font-medium text-[9px] tabular-nums\",\n                        stat.up\n                          ? \"text-emerald-600 dark:text-emerald-400\"\n                          : \"text-red-500 dark:text-red-400\",\n                      )}\n                    >\n                      {stat.trend}\n                    </span>\n                  </div>\n                </div>\n              ))}\n            </div>\n\n            {/* Chart */}\n            <div className=\"rounded-lg border p-3\">\n              <div className=\"flex items-center justify-between gap-2\">\n                <div className=\"flex min-w-0 flex-col gap-0.5\">\n                  <span className=\"truncate font-medium text-xs\">\n                    Monthly revenue\n                  </span>\n                  <span className=\"truncate text-[9px] text-muted-foreground\">\n                    $48,240 total\n                  </span>\n                </div>\n                <span className=\"flex shrink-0 items-center gap-1 text-[9px] text-muted-foreground\">\n                  <span className=\"size-1.5 rounded-full bg-primary/80\" />\n                  This year\n                </span>\n              </div>\n\n              <div className=\"mt-3 flex h-20 items-end gap-1.5\">\n                {bars.map((bar) => (\n                  <div\n                    className=\"min-h-0.5 flex-1 rounded-sm bg-primary/70\"\n                    key={bar.month}\n                    style={{ height: `${bar.value}%` }}\n                    title={`${bar.month}: ${bar.value}`}\n                  />\n                ))}\n              </div>\n            </div>\n\n            {/* Recent activity */}\n            <div className=\"rounded-lg border p-3\">\n              <div className=\"flex items-center justify-between\">\n                <span className=\"font-medium text-xs\">Recent activity</span>\n                <Badge className=\"text-[9px]\" variant=\"secondary\">\n                  Live\n                </Badge>\n              </div>\n              <div className=\"mt-2 flex flex-col\">\n                {activity.map((entry, index) => (\n                  <div key={entry.name}>\n                    {index > 0 && <Separator className=\"my-2\" />}\n                    <div className=\"flex items-center gap-2\">\n                      <Avatar className=\"size-6 shrink-0\">\n                        <AvatarImage alt=\"\" src={entry.src} />\n                        <AvatarFallback className=\"text-[9px]\">\n                          {entry.name[0]}\n                        </AvatarFallback>\n                      </Avatar>\n                      <span className=\"min-w-0 flex-1 truncate text-[11px]\">\n                        <span className=\"font-medium\">{entry.name}</span>\n                        <span className=\"text-muted-foreground\">\n                          {\" \"}\n                          {entry.action}\n                        </span>\n                      </span>\n                      <span className=\"shrink-0 text-[9px] text-muted-foreground tabular-nums\">\n                        {entry.time}\n                      </span>\n                    </div>\n                  </div>\n                ))}\n              </div>\n            </div>\n          </div>\n        </div>\n      </Card>\n\n      {/* Floating notification */}\n      <div className=\"absolute right-1 bottom-1 max-w-[calc(100%-0.5rem)] sm:-right-4 sm:-bottom-4\">\n        <Card className=\"flex-row items-center gap-2.5 p-2.5 shadow-lg\">\n          <div className=\"relative flex size-8 shrink-0 items-center justify-center rounded-lg bg-primary/15 text-primary\">\n            <Bell className=\"size-4\" />\n            <span className=\"absolute -top-0.5 -right-0.5 size-2 rounded-full border-2 border-card bg-emerald-500\" />\n          </div>\n          <div className=\"flex min-w-0 flex-col\">\n            <span className=\"truncate font-medium text-xs leading-tight\">\n              Payment received\n            </span>\n            <span className=\"truncate text-[10px] text-muted-foreground leading-tight\">\n              $1,290 from Acme Inc.\n            </span>\n          </div>\n          <Badge className=\"ml-1 shrink-0 text-[10px]\" variant=\"secondary\">\n            +$1.2k\n          </Badge>\n        </Card>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/hero-dashboard-demo.tsx"
    },
    {
      "path": "registry/blocks/hero-dashboard-01/components/hero-cta.tsx",
      "content": "import { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { Button, buttonVariants } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\n// Cortexcn item \"hero-dashboard-01\", revision 27fff60c5fe5, MIT license.\n// https://ui.cortexcn.dev/r/v/hero-dashboard-01/27fff60c5fe5.json\n\ntype ButtonVariants = VariantProps<typeof buttonVariants>;\n\nexport type ButtonVariant = NonNullable<ButtonVariants[\"variant\"]>;\n\nexport interface CtaProps {\n  ctaEnabled?: boolean;\n  text: string;\n  /** Leave empty to render a button instead of a link. */\n  link: string;\n  variant?: ButtonVariant;\n  size?: \"default\" | \"sm\" | \"lg\";\n}\n\nconst ctaVariants = cva(\"w-fit rounded-full px-4\", {\n  variants: {\n    invert: {\n      true: \"border-transparent! bg-white! text-zinc-900! hover:bg-zinc-100!\",\n      false: \"\",\n    },\n  },\n  defaultVariants: {\n    invert: false,\n  },\n});\n\nexport function Cta({\n  cta,\n  className,\n  invert,\n}: Readonly<{ cta?: CtaProps; className?: string; invert?: boolean }>) {\n  if (!cta?.ctaEnabled) {\n    return null;\n  }\n\n  const variant = cta.variant ?? (invert ? \"secondary\" : \"default\");\n\n  if (!cta.link) {\n    return (\n      <Button\n        aria-label={cta.text}\n        className={cn(ctaVariants({ invert }), className)}\n        size={cta.size ?? \"default\"}\n        type=\"button\"\n        variant={variant}\n      >\n        {cta.text}\n      </Button>\n    );\n  }\n\n  return (\n    // No aria-label here, so screen readers also hear \"(opens in new tab)\".\n    <a\n      className={cn(\n        buttonVariants({\n          variant,\n          size: cta.size ?? \"default\",\n          className: cn(ctaVariants({ invert }), className),\n        }),\n      )}\n      href={cta.link}\n      rel=\"noopener noreferrer\"\n      target=\"_blank\"\n    >\n      {cta.text}\n      <span className=\"sr-only\">{`${cta.text} (opens in new tab)`}</span>\n    </a>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/hero-cta.tsx"
    }
  ],
  "type": "registry:block",
  "author": "Cortexcn (https://ui.cortexcn.dev)",
  "meta": {
    "license": "MIT",
    "revision": "27fff60c5fe5"
  }
}