{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "device-frame",
  "type": "registry:component",
  "title": "Device frame",
  "description": "Wraps any React UI in a phone with notch, status bar and side buttons, or a browser window with a URL bar. Built from theme tokens for light and dark.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/blocks/device-frame.tsx",
      "type": "registry:ui",
      "target": "components/ui/device-frame.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { LockIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\n/*\n * DeviceFrame: a phone or a browser window around live UI. The frame is\n * built from the kit's own surfaces, so it picks up the material and the\n * light like everything else: a lit bezel edge, a glass screen sheen.\n */\n\ntype DeviceFrameProps = {\n  device?: \"phone\" | \"browser\"\n  /** Browser only. */\n  url?: string\n  /** Phone status bar time. */\n  time?: string\n  children?: React.ReactNode\n  className?: string\n  screenClassName?: string\n}\n\nfunction PhoneFrame({ time = \"9:41\", children, className, screenClassName }: DeviceFrameProps) {\n  return (\n    <div\n      data-slot=\"device-frame\"\n      data-device=\"phone\"\n      className={cn(\n        \"relative mx-auto w-[300px] rounded-[52px] bg-[oklch(0.17_0.006_260)] p-[11px] shadow-lg\",\n        \"shadow-[inset_calc(var(--sx)*-1.5px)_calc(var(--sy)*-1.5px)_0_0_oklch(1_0_0/0.35),inset_0_0_0_1px_oklch(1_0_0/0.08),var(--o12x)_var(--o12y)_40px_-8px_oklch(0_0_0/0.35),var(--o28x)_var(--o28y)_80px_-20px_oklch(0_0_0/0.45)]\",\n        className\n      )}\n    >\n      {/* side buttons */}\n      <span aria-hidden className=\"absolute top-[120px] -left-[3px] h-14 w-[3px] rounded-l bg-[oklch(0.17_0.006_260)]\" />\n      <span aria-hidden className=\"absolute top-[190px] -left-[3px] h-14 w-[3px] rounded-l bg-[oklch(0.17_0.006_260)]\" />\n      <span aria-hidden className=\"absolute top-[150px] -right-[3px] h-20 w-[3px] rounded-r bg-[oklch(0.17_0.006_260)]\" />\n      <div className={cn(\"relative h-[610px] overflow-hidden rounded-[42px] bg-bg text-fg\", screenClassName)}>\n        <div className=\"relative z-20 flex h-11 items-center justify-between px-7 text-[13px] font-semibold tabular-nums\">\n          <span>{time}</span>\n          <span aria-hidden className=\"absolute top-2.5 left-1/2 h-[26px] w-[92px] -translate-x-1/2 rounded-full bg-black\" />\n          <span className=\"flex items-center gap-1\" aria-hidden>\n            <span className=\"flex items-end gap-[2px]\">\n              {[4, 6, 8, 10].map((h) => (\n                <span key={h} className=\"w-[3px] rounded-sm bg-current\" style={{ height: h }} />\n              ))}\n            </span>\n            <span className=\"ml-1 h-[11px] w-[22px] rounded-[3px] border border-current/60 p-[1.5px]\">\n              <span className=\"block h-full w-[70%] rounded-[1px] bg-current\" />\n            </span>\n          </span>\n        </div>\n        <div className=\"absolute inset-0 top-11 overflow-hidden\">{children}</div>\n        {/* screen glass sheen, follows the light */}\n        <div\n          aria-hidden\n          className=\"pointer-events-none absolute inset-0 z-30 rounded-[inherit] bg-[linear-gradient(var(--la),transparent_55%,oklch(1_0_0/0.07)_75%,transparent_90%)]\"\n        />\n        <span aria-hidden className=\"absolute bottom-2 left-1/2 z-30 h-[5px] w-32 -translate-x-1/2 rounded-full bg-fg/80\" />\n      </div>\n    </div>\n  )\n}\n\nfunction BrowserFrame({ url = \"app.lumen.io\", children, className, screenClassName }: DeviceFrameProps) {\n  return (\n    <div data-slot=\"device-frame\" data-device=\"browser\" className={cn(\"overflow-hidden rounded-2xl border border-border bg-surface shadow-overlay\", className)}>\n      <div className=\"flex h-11 items-center gap-3 border-b border-border bg-sunken/60 px-4\">\n        <span className=\"flex gap-1.5\" aria-hidden>\n          {[0, 1, 2].map((i) => (\n            <span key={i} className=\"size-3 rounded-full border border-border-strong bg-bg\" />\n          ))}\n        </span>\n        <div className=\"mx-auto flex h-7 w-full max-w-sm items-center justify-center gap-1.5 rounded-lg border border-border bg-bg px-3 font-mono text-[11.5px] text-fg-muted\">\n          <LockIcon className=\"size-3\" />\n          {url}\n        </div>\n        <span className=\"w-12\" aria-hidden />\n      </div>\n      <div className={cn(\"relative bg-bg\", screenClassName)}>{children}</div>\n    </div>\n  )\n}\n\nfunction DeviceFrame(props: DeviceFrameProps) {\n  const content = props.children ?? (\n    <div className=\"grid h-full min-h-72 place-items-center p-8 text-center\">\n      <div>\n        <p className=\"text-sm font-medium text-fg\">Your app goes here</p>\n        <p className=\"mt-1 text-xs text-fg-muted\">Pass any UI as children.</p>\n      </div>\n    </div>\n  )\n  return props.device === \"browser\" ? <BrowserFrame {...props}>{content}</BrowserFrame> : <PhoneFrame {...props}>{content}</PhoneFrame>\n}\n\nexport { DeviceFrame }\nexport type { DeviceFrameProps }\n"
    }
  ]
}
