{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "mac-window",
  "title": "Mac Window",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "macOS window chrome: traffic lights whose glyphs appear on hover, a centered title or unified toolbar, an optional translucent sidebar with vibrancy, and active and inactive appearances.",
  "registryDependencies": [
    "utils",
    "https://ui.ballmac.com/r/i18n.json"
  ],
  "files": [
    {
      "path": "registry/ballmac/components/mac-window.tsx",
      "content": "// Ballmac UI: Mac Window. https://ui.ballmac.com/components/mac-window\n\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { useMessages } from \"@/lib/ballmac/i18n\"\n\ntype MacWindowContextValue = {\n  active: boolean\n  onClose?: () => void\n  onMinimize?: () => void\n  onZoom?: () => void\n}\n\nconst MacWindowContext = React.createContext<MacWindowContextValue>({ active: true })\n\ntype MacWindowProps = React.ComponentProps<\"div\"> & {\n  /** Active (key) window: colored traffic lights and full-strength title. Inactive windows gray out, as on macOS. */\n  active?: boolean\n  /** Called by the red close button. Without a handler the light is drawn but not focusable. */\n  onClose?: () => void\n  /** Called by the yellow minimize button. */\n  onMinimize?: () => void\n  /** Called by the green zoom (full screen) button. */\n  onZoom?: () => void\n}\n\n/**\n * A macOS window frame. Compose it from MacWindowTitleBar + MacWindowContent, or MacWindowSidebar +\n * MacWindowMain for a sidebar layout with vibrancy. Traffic-light colors are the --mac-close, --mac-minimize\n * and --mac-zoom CSS variables; override them on the window if you like.\n */\nfunction MacWindow({ active = true, onClose, onMinimize, onZoom, className, style, ...props }: MacWindowProps) {\n  const context = React.useMemo(() => ({ active, onClose, onMinimize, onZoom }), [active, onClose, onMinimize, onZoom])\n  return (\n    <MacWindowContext.Provider value={context}>\n      <div\n        data-slot=\"mac-window\"\n        data-state={active ? \"active\" : \"inactive\"}\n        className={cn(\n          \"group/mac-window relative isolate flex min-w-0 flex-col overflow-hidden rounded-[14px] bg-card text-card-foreground has-[[data-slot=mac-window-sidebar]]:flex-row has-[[data-slot=mac-window-sidebar]]:bg-transparent\",\n          \"shadow-[0_0_0_0.5px_rgb(0_0_0/0.22),0_24px_60px_-12px_rgb(0_0_0/0.35),0_8px_20px_-8px_rgb(0_0_0/0.2)]\",\n          \"dark:shadow-[0_0_0_0.5px_rgb(0_0_0/0.9),inset_0_0_0_0.5px_rgb(255_255_255/0.16),0_24px_60px_-12px_rgb(0_0_0/0.7)]\",\n          \"data-[state=inactive]:shadow-[0_0_0_0.5px_rgb(0_0_0/0.18),0_12px_30px_-12px_rgb(0_0_0/0.25)]\",\n          \"dark:data-[state=inactive]:shadow-[0_0_0_0.5px_rgb(0_0_0/0.9),inset_0_0_0_0.5px_rgb(255_255_255/0.1),0_12px_30px_-12px_rgb(0_0_0/0.5)]\",\n          className\n        )}\n        style={\n          {\n            \"--mac-close\": \"oklch(0.7 0.19 25)\",\n            \"--mac-minimize\": \"oklch(0.84 0.16 84)\",\n            \"--mac-zoom\": \"oklch(0.76 0.19 145)\",\n            ...style,\n          } as React.CSSProperties\n        }\n        {...props}\n      />\n    </MacWindowContext.Provider>\n  )\n}\n\nconst glyphs = {\n  close: <path d=\"M3.5 3.5l5 5m0-5l-5 5\" strokeWidth=\"1.3\" strokeLinecap=\"round\" />,\n  minimize: <path d=\"M3 6h6\" strokeWidth=\"1.4\" strokeLinecap=\"round\" />,\n  zoom: <path d=\"M3.4 8.6V5l3.6 3.6zM8.6 3.4V7L5 3.4z\" stroke=\"none\" fill=\"currentColor\" />,\n} as const\n\nfunction TrafficLight({ kind, label, onPress }: { kind: keyof typeof glyphs; label: string; onPress?: () => void }) {\n  const shared = cn(\n    \"relative flex size-3 shrink-0 items-center justify-center rounded-full text-black/60 outline-none\",\n    \"bg-(--light) shadow-[inset_0_0_0_0.5px_rgb(0_0_0/0.18)] dark:shadow-[inset_0_0_0_0.5px_rgb(255_255_255/0.12)]\",\n    \"group-data-[state=inactive]/mac-window:bg-foreground/15 group-data-[state=inactive]/mac-window:group-hover/lights:bg-(--light)\"\n  )\n  const style = { \"--light\": `var(--mac-${kind})` } as React.CSSProperties\n  const glyph = (\n    <svg\n      viewBox=\"0 0 12 12\"\n      aria-hidden=\"true\"\n      stroke=\"currentColor\"\n      fill=\"none\"\n      className=\"size-3 opacity-0 transition-opacity duration-100 group-hover/lights:opacity-100 group-has-[:focus-visible]/lights:opacity-100\"\n    >\n      {glyphs[kind]}\n    </svg>\n  )\n  if (!onPress) {\n    return (\n      <span data-slot={`mac-window-${kind}`} className={shared} style={style} aria-hidden=\"true\">\n        {glyph}\n      </span>\n    )\n  }\n  return (\n    <button\n      type=\"button\"\n      data-slot={`mac-window-${kind}`}\n      aria-label={label}\n      onClick={onPress}\n      className={cn(shared, \"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background\")}\n      style={style}\n    >\n      {glyph}\n    </button>\n  )\n}\n\ntype MacWindowControlsProps = React.ComponentProps<\"div\"> & {\n  /** Accessible labels for the three buttons. */\n  labels?: { close?: string; minimize?: string; zoom?: string }\n}\n\n/** The red, yellow and green traffic lights. Glyphs appear when the pointer is over any of them. */\nfunction MacWindowControls({ labels, className, ...props }: MacWindowControlsProps) {\n  const { onClose, onMinimize, onZoom } = React.useContext(MacWindowContext)\n  const msg = useMessages()\n  return (\n    <div data-slot=\"mac-window-controls\" dir=\"ltr\" className={cn(\"group/lights flex shrink-0 items-center gap-2\", className)} {...props}>\n      <TrafficLight kind=\"close\" label={labels?.close ?? msg(\"mac-window.close\", \"Close window\")} onPress={onClose} />\n      <TrafficLight kind=\"minimize\" label={labels?.minimize ?? msg(\"mac-window.minimize\", \"Minimize window\")} onPress={onMinimize} />\n      <TrafficLight kind=\"zoom\" label={labels?.zoom ?? msg(\"mac-window.zoom\", \"Zoom window\")} onPress={onZoom} />\n    </div>\n  )\n}\n\ntype MacWindowTitleBarProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n  /** Window title, centered in the bar. */\n  title?: React.ReactNode\n  /** Draw the traffic lights at the leading edge. Turn off when a MacWindowSidebar already shows them. */\n  controls?: boolean\n}\n\n/**\n * The title bar. With only a title it is a compact 28px bar; children render as a trailing toolbar\n * and grow it to the 52px unified-toolbar height.\n */\nfunction MacWindowTitleBar({ title, controls = true, className, children, ...props }: MacWindowTitleBarProps) {\n  const hasToolbar = React.Children.count(children) > 0\n  return (\n    <div\n      data-slot=\"mac-window-titlebar\"\n      className={cn(\n        \"relative flex shrink-0 items-center gap-3 border-b border-foreground/[0.08] px-3 select-none\",\n        hasToolbar ? \"h-[52px] px-4\" : \"h-8\",\n        className\n      )}\n      {...props}\n    >\n      {controls ? <MacWindowControls /> : null}\n      {title ? (\n        <div\n          data-slot=\"mac-window-title\"\n          className={cn(\n            \"pointer-events-none truncate text-[13px] font-semibold text-foreground/85 group-data-[state=inactive]/mac-window:text-muted-foreground\",\n            hasToolbar ? \"min-w-0\" : \"absolute inset-x-20 text-center\"\n          )}\n        >\n          {title}\n        </div>\n      ) : null}\n      {hasToolbar ? (\n        <div data-slot=\"mac-window-toolbar\" className=\"ms-auto flex min-w-0 items-center gap-1 text-foreground/70 group-data-[state=inactive]/mac-window:text-foreground/35\">\n          {children}\n        </div>\n      ) : null}\n    </div>\n  )\n}\n\ntype MacWindowToolbarButtonProps = React.ComponentProps<\"button\">\n\n/** A borderless toolbar button that highlights on hover, sized for 16px icons. Give icon-only buttons an aria-label. */\nfunction MacWindowToolbarButton({ className, type = \"button\", ...props }: MacWindowToolbarButtonProps) {\n  return (\n    <button\n      type={type}\n      data-slot=\"mac-window-toolbar-button\"\n      className={cn(\n        \"inline-flex h-7 min-w-7 shrink-0 items-center justify-center gap-1.5 rounded-md px-1.5 text-[13px] outline-none transition-colors duration-150 hover:bg-foreground/[0.07] hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\ntype MacWindowSidebarProps = React.ComponentProps<\"div\"> & {\n  /** Draw the traffic lights at the top of the sidebar. */\n  controls?: boolean\n}\n\n/** A translucent source-list sidebar that blurs whatever is behind the window (vibrancy). */\nfunction MacWindowSidebar({ controls = true, className, children, ...props }: MacWindowSidebarProps) {\n  return (\n    <div\n      data-slot=\"mac-window-sidebar\"\n      className={cn(\n        \"flex w-52 shrink-0 flex-col border-e border-foreground/[0.08] bg-background/60 backdrop-blur-2xl backdrop-saturate-150 dark:bg-background/50\",\n        className\n      )}\n      {...props}\n    >\n      {controls ? (\n        <div className=\"flex h-[52px] shrink-0 items-center px-4\">\n          <MacWindowControls />\n        </div>\n      ) : null}\n      {children}\n    </div>\n  )\n}\n\ntype MacWindowSidebarItemProps = React.ComponentProps<\"button\"> & {\n  /** Marks the selected row (sets aria-current). */\n  selected?: boolean\n}\n\n/** A source-list row: icon, label and an optional trailing count. */\nfunction MacWindowSidebarItem({ selected = false, className, type = \"button\", ...props }: MacWindowSidebarItemProps) {\n  return (\n    <button\n      type={type}\n      data-slot=\"mac-window-sidebar-item\"\n      data-selected={selected ? \"\" : undefined}\n      aria-current={selected ? \"true\" : undefined}\n      className={cn(\n        \"flex h-7 w-full items-center gap-2 rounded-md px-2 text-start text-[13px] text-foreground/85 outline-none transition-colors duration-100 hover:bg-foreground/[0.05] focus-visible:ring-[3px] focus-visible:ring-ring/50 data-selected:bg-foreground/[0.09] data-selected:font-medium data-selected:text-foreground [&_svg]:size-4 [&_svg]:shrink-0\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\ntype MacWindowMainProps = React.ComponentProps<\"div\">\n\n/** The opaque column next to a sidebar; holds the title bar and content. */\nfunction MacWindowMain({ className, ...props }: MacWindowMainProps) {\n  return <div data-slot=\"mac-window-main\" className={cn(\"flex min-w-0 flex-1 flex-col bg-card\", className)} {...props} />\n}\n\ntype MacWindowContentProps = React.ComponentProps<\"div\">\n\nfunction MacWindowContent({ className, ...props }: MacWindowContentProps) {\n  return <div data-slot=\"mac-window-content\" className={cn(\"min-h-0 flex-1 overflow-auto\", className)} {...props} />\n}\n\nexport {\n  MacWindow,\n  MacWindowContent,\n  MacWindowControls,\n  MacWindowMain,\n  MacWindowSidebar,\n  MacWindowSidebarItem,\n  MacWindowTitleBar,\n  MacWindowToolbarButton,\n  type MacWindowContentProps,\n  type MacWindowControlsProps,\n  type MacWindowMainProps,\n  type MacWindowProps,\n  type MacWindowSidebarItemProps,\n  type MacWindowSidebarProps,\n  type MacWindowTitleBarProps,\n  type MacWindowToolbarButtonProps,\n}\n",
      "type": "registry:ui",
      "target": "@components/ballmac/mac-window.tsx"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "window",
      "macos",
      "traffic lights",
      "chrome",
      "mockup",
      "sidebar",
      "frame"
    ],
    "version": "1.0.0",
    "updated": "2026-09-29",
    "ai": {
      "summary": "Frame content as a Mac app window. Simple: <MacWindow><MacWindowTitleBar title=\"…\" /><MacWindowContent>…</MacWindowContent></MacWindow>. Sidebar layout: <MacWindow><MacWindowSidebar>rows…</MacWindowSidebar><MacWindowMain><MacWindowTitleBar controls={false} title>toolbar buttons</MacWindowTitleBar><MacWindowContent/></MacWindowMain></MacWindow>. Size the window with className.",
      "whenToUse": [
        "Product screenshots and mockups of a Mac app on a landing page",
        "Framing a code sample, terminal session or settings panel so it reads as desktop software",
        "Interactive app demos where the sidebar and toolbar actually work"
      ],
      "whenNotToUse": [
        "Modal dialogs in a web app (use dialog)",
        "Browser mockups; this draws native window chrome, not an address bar"
      ],
      "composesWith": [
        "dock",
        "menu-bar",
        "segmented-control"
      ],
      "a11y": [
        {
          "keys": "Tab",
          "action": "Reaches the traffic lights only when onClose, onMinimize or onZoom handlers are set, then toolbar and sidebar buttons"
        },
        {
          "keys": "Enter / Space",
          "action": "Activates the focused traffic light or button"
        }
      ],
      "customization": [
        "active: false grays the lights and title like a background window",
        "onClose / onMinimize / onZoom: make the lights real buttons with aria-labels (labels prop on MacWindowControls)",
        "--mac-close, --mac-minimize, --mac-zoom: traffic-light colors (CSS variables on the window)",
        "MacWindowTitleBar: title, controls, children become a trailing toolbar (use MacWindowToolbarButton)",
        "MacWindowSidebar: translucent, blurs what's behind the window; MacWindowSidebarItem for rows (selected sets aria-current)"
      ]
    },
    "examples": [
      "mac-window-demo",
      "mac-window-stack"
    ],
    "url": "https://ui.ballmac.com/components/mac-window"
  },
  "categories": [
    "macos"
  ],
  "type": "registry:ui"
}