{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "retro-bevel-button",
  "title": "RetroBevelButton",
  "description": "Mac OS 9 Appearance Manager bevel button with small/normal/large bevels, icon above or beside the label, sticky toggle (aria-pressed) behaviour and an optional pop-up menu arrow.",
  "dependencies": [
    "class-variance-authority"
  ],
  "registryDependencies": [
    "https://nostalgia-ui.com/r/nostalgia-theme.json"
  ],
  "files": [
    {
      "path": "registry/new-york/ui/retro-bevel-button.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* ------------------------------------------------------------------ */\n/*  Variants                                                           */\n/* ------------------------------------------------------------------ */\n\n/*\n * Mac OS 9 Appearance Manager bevel buttons came in three bevel depths.\n * Each depth adds one more ring of highlight / shadow inside the black\n * frame. The \"on\" state inverts the rings and darkens the face.\n */\nconst retroBevelButtonVariants = cva(\n  [\n    \"relative inline-flex items-center justify-center gap-[4px]\",\n    \"border border-os9-black bg-os9-gray-300 text-os9-black\",\n    \"font-[family-name:var(--os9-font-heading)] text-[12px] tracking-[0.42px] leading-[0.98]\",\n    \"cursor-pointer select-none whitespace-nowrap\",\n    \"transition-none\",\n    \"focus-visible:os9-focus-ring\",\n    \"active:bg-os9-gray-700 active:text-os9-white\",\n    \"data-[state=on]:bg-os9-gray-700 data-[state=on]:text-os9-white\",\n    \"data-open:bg-os9-gray-700 data-open:text-os9-white\",\n    \"disabled:pointer-events-none disabled:cursor-not-allowed disabled:text-os9-gray-600 disabled:border-os9-gray-600 disabled:[&_svg]:opacity-50\",\n  ],\n  {\n    variants: {\n      bevel: {\n        small: [\n          \"shadow-[inset_1px_1px_0_var(--os9-white),inset_-1px_-1px_0_var(--os9-gray-700)]\",\n          \"active:shadow-[inset_1px_1px_0_var(--os9-gray-800),inset_-1px_-1px_0_var(--os9-gray-500)]\",\n          \"data-[state=on]:shadow-[inset_1px_1px_0_var(--os9-gray-800),inset_-1px_-1px_0_var(--os9-gray-500)]\",\n        ],\n        normal: [\n          \"shadow-[inset_1px_1px_0_var(--os9-white),inset_-1px_-1px_0_var(--os9-gray-700),inset_2px_2px_0_var(--os9-gray-200),inset_-2px_-2px_0_var(--os9-gray-500)]\",\n          \"active:shadow-[inset_1px_1px_0_var(--os9-black),inset_-1px_-1px_0_var(--os9-gray-500),inset_2px_2px_0_var(--os9-gray-800),inset_-2px_-2px_0_var(--os9-gray-600)]\",\n          \"data-[state=on]:shadow-[inset_1px_1px_0_var(--os9-black),inset_-1px_-1px_0_var(--os9-gray-500),inset_2px_2px_0_var(--os9-gray-800),inset_-2px_-2px_0_var(--os9-gray-600)]\",\n        ],\n        large: [\n          \"shadow-[inset_1px_1px_0_var(--os9-white),inset_-1px_-1px_0_var(--os9-gray-800),inset_2px_2px_0_var(--os9-white),inset_-2px_-2px_0_var(--os9-gray-700),inset_3px_3px_0_var(--os9-gray-200),inset_-3px_-3px_0_var(--os9-gray-500)]\",\n          \"active:shadow-[inset_1px_1px_0_var(--os9-black),inset_-1px_-1px_0_var(--os9-gray-400),inset_2px_2px_0_var(--os9-black),inset_-2px_-2px_0_var(--os9-gray-500),inset_3px_3px_0_var(--os9-gray-800),inset_-3px_-3px_0_var(--os9-gray-600)]\",\n          \"data-[state=on]:shadow-[inset_1px_1px_0_var(--os9-black),inset_-1px_-1px_0_var(--os9-gray-400),inset_2px_2px_0_var(--os9-black),inset_-2px_-2px_0_var(--os9-gray-500),inset_3px_3px_0_var(--os9-gray-800),inset_-3px_-3px_0_var(--os9-gray-600)]\",\n        ],\n      },\n      size: {\n        sm: \"min-h-[20px] min-w-[20px] px-[4px] py-[2px] text-[10px]\",\n        default: \"min-h-[24px] min-w-[24px] px-[8px] py-[4px]\",\n        lg: \"min-h-[32px] min-w-[32px] px-[10px] py-[6px]\",\n      },\n      iconPosition: {\n        left: \"flex-row\",\n        top: \"flex-col gap-[4px]\",\n        right: \"flex-row-reverse\",\n      },\n    },\n    compoundVariants: [\n      { iconPosition: \"top\", size: \"default\", className: \"min-w-[56px] py-[6px]\" },\n      { iconPosition: \"top\", size: \"lg\", className: \"min-w-[72px] py-[8px]\" },\n    ],\n    defaultVariants: {\n      bevel: \"normal\",\n      size: \"default\",\n      iconPosition: \"left\",\n    },\n  }\n)\n\n/* ------------------------------------------------------------------ */\n/*  Pop-up menu arrow                                                  */\n/* ------------------------------------------------------------------ */\n\nfunction BevelMenuArrow({ direction }: { direction: \"down\" | \"right\" }) {\n  return (\n    <svg\n      width=\"7\"\n      height=\"7\"\n      viewBox=\"0 0 7 7\"\n      aria-hidden=\"true\"\n      className={cn(\n        \"pointer-events-none shrink-0\",\n        direction === \"down\"\n          ? \"absolute right-[4px] bottom-[4px]\"\n          : \"absolute right-[4px] top-1/2 -translate-y-1/2\"\n      )}\n    >\n      <path\n        d={direction === \"down\" ? \"M0 2H7L3.5 6Z\" : \"M2 0V7L6 3.5Z\"}\n        fill=\"currentColor\"\n      />\n    </svg>\n  )\n}\n\n/* ------------------------------------------------------------------ */\n/*  RetroBevelButton                                                   */\n/* ------------------------------------------------------------------ */\n\ninterface RetroBevelButtonProps\n  extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n    VariantProps<typeof retroBevelButtonVariants> {\n  /** Icon rendered above / beside the label (e.g. a RetroIcon). */\n  icon?: React.ReactNode\n  /**\n   * Makes the button a sticky toggle (aria-pressed). Implied when\n   * `pressed` or `defaultPressed` is provided.\n   */\n  toggle?: boolean\n  /** Controlled pressed state (toggle behaviour). */\n  pressed?: boolean\n  /** Initial pressed state when uncontrolled (toggle behaviour). */\n  defaultPressed?: boolean\n  /** Fires when the pressed state changes (toggle behaviour). */\n  onPressedChange?: (pressed: boolean) => void\n  /**\n   * Shows the pop-up menu indicator. `true` / \"down\" draws the arrow in\n   * the bottom-right corner; \"right\" draws a sideways arrow (submenu).\n   */\n  menu?: boolean | \"down\" | \"right\"\n}\n\nconst RetroBevelButton = React.forwardRef<\n  HTMLButtonElement,\n  RetroBevelButtonProps\n>(function RetroBevelButton(\n  {\n    className,\n    bevel,\n    size,\n    iconPosition,\n    icon,\n    toggle,\n    pressed: pressedProp,\n    defaultPressed,\n    onPressedChange,\n    menu,\n    onClick,\n    children,\n    type = \"button\",\n    ...props\n  },\n  ref\n) {\n  const isToggle =\n    toggle || pressedProp !== undefined || defaultPressed !== undefined\n  const [uncontrolledPressed, setUncontrolledPressed] = React.useState(\n    defaultPressed ?? false\n  )\n  const isControlled = pressedProp !== undefined\n  const pressed = isControlled ? pressedProp : uncontrolledPressed\n\n  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n    onClick?.(event)\n    if (event.defaultPrevented || !isToggle) return\n    const next = !pressed\n    if (!isControlled) setUncontrolledPressed(next)\n    onPressedChange?.(next)\n  }\n\n  const menuDirection = menu === \"right\" ? \"right\" : menu ? \"down\" : null\n\n  return (\n    <button\n      ref={ref}\n      type={type}\n      aria-pressed={isToggle ? pressed : undefined}\n      aria-haspopup={menuDirection ? \"menu\" : undefined}\n      data-state={isToggle ? (pressed ? \"on\" : \"off\") : undefined}\n      className={cn(\n        retroBevelButtonVariants({ bevel, size, iconPosition }),\n        menuDirection && \"pr-[16px]\",\n        className\n      )}\n      onClick={handleClick}\n      {...props}\n    >\n      {icon ? (\n        <span className=\"inline-flex shrink-0 items-center justify-center\">\n          {icon}\n        </span>\n      ) : null}\n      {children != null && children !== false ? (\n        <span className=\"inline-flex items-center\">{children}</span>\n      ) : null}\n      {menuDirection ? <BevelMenuArrow direction={menuDirection} /> : null}\n    </button>\n  )\n})\nRetroBevelButton.displayName = \"RetroBevelButton\"\n\nexport { RetroBevelButton, retroBevelButtonVariants }\nexport type { RetroBevelButtonProps }\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}