{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "dependencies": [
    "@base-ui/react@1.8.0"
  ],
  "description": "A dropdown action menu on Base UI: arrow keys, typeahead and collision-aware placement.",
  "docs": "Two steps after installing: import the copied stylesheet once at your app entry — it lands at `styles/liquefy-ui.css` — or `@import` it from your global CSS *before* `tailwindcss`, so Tailwind utilities keep winning over component styles. Then wrap the tree in `<LiquefyProvider>`, which is where every component reads its tokens from. Every copied file already carries its own 'use client' directive. Full documentation: https://liquefy-ui.com/#/docs/installation",
  "files": [
    {
      "content": "'use client'\n\nimport { Menu } from '@base-ui/react/menu'\nimport type { CSSProperties, ReactElement, ReactNode } from 'react'\nimport { useLiquefyPortalContainer } from '@/lib/provider'\nimport { useLiquidStyles, type LiquidStyleProps } from '@/lib/styles-prop'\n\n// The previous version measured the trigger by hand, flipped the popup with a\n// couple of thresholds and listened for outside pointerdown. None of it handled\n// the keyboard: no arrow keys, no Home/End, no typeahead, no focus return.\n// Base UI covers all of that, plus collision-aware positioning and the\n// --available-height the popup now caps itself to.\n\nexport type LiquidMenuItemDef = {\n  danger?: boolean\n  disabled?: boolean\n  icon?: ReactNode\n  label: ReactNode\n  onSelect?: () => void\n  shortcut?: string\n  type?: 'item'\n} | {\n  type: 'separator'\n}\n\nexport type LiquidMenuProps = LiquidStyleProps & {\n  align?: 'start' | 'end'\n  className?: string\n  items: LiquidMenuItemDef[]\n  style?: CSSProperties\n  trigger: ReactElement<Record<string, unknown>>\n}\n\nexport const LiquidMenu = ({ align = 'start', className, items, style, styles, trigger }: LiquidMenuProps) => {\n  const portalContainer = useLiquefyPortalContainer()\n  // The anchor span stays the layout box, so className/style/styles keep meaning\n  // what they did before the popup moved into a portal.\n  const root = useLiquidStyles('lq-menu', { className, style, styles })\n\n  return (\n    <span className={root.className} style={root.style}>\n      <Menu.Root>\n        <Menu.Trigger render={trigger} />\n        <Menu.Portal container={portalContainer ?? undefined}>\n          <Menu.Positioner align={align} className=\"lq-menu__positioner\" side=\"bottom\" sideOffset={7}>\n            <Menu.Popup className=\"lq-menu__popup lq-popover\">\n              {items.map((item, index) => item.type === 'separator'\n                ? <Menu.Separator className=\"lq-menu__separator\" key={`separator-${index}`} />\n                : (\n                  <Menu.Item\n                    className=\"lq-menu__item\"\n                    data-danger={item.danger}\n                    disabled={item.disabled}\n                    key={index}\n                    // Typeahead matches on this, so give it the text when we have it.\n                    label={typeof item.label === 'string' ? item.label : undefined}\n                    onClick={() => item.onSelect?.()}\n                  >\n                    {item.icon && <span className=\"lq-menu__icon\">{item.icon}</span>}\n                    <span className=\"lq-menu__label\">{item.label}</span>\n                    {item.shortcut && <kbd className=\"lq-menu__shortcut\">{item.shortcut}</kbd>}\n                  </Menu.Item>\n                ))}\n            </Menu.Popup>\n          </Menu.Positioner>\n        </Menu.Portal>\n      </Menu.Root>\n    </span>\n  )\n}\n",
      "path": "registry/liquid-menu.tsx",
      "type": "registry:ui"
    }
  ],
  "name": "liquid-menu",
  "registryDependencies": [
    "https://liquefy-ui.com/r/liquefy-ui.json",
    "https://liquefy-ui.com/r/provider.json",
    "https://liquefy-ui.com/r/styles-prop.json"
  ],
  "title": "LiquidMenu",
  "type": "registry:ui"
}
