{"_id":"@denisbitter/bitter-button-menu","name":"@denisbitter/bitter-button-menu","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@denisbitter/bitter-button-menu","version":"1.0.0","description":"A beautiful radial/orbit menu button component with smooth animations","main":"dist/index.cjs.js","module":"dist/index.esm.js","types":"dist/index.d.ts","scripts":{"build":"rollup -c","dev":"rollup -c -w","prepare":"npm run build"},"keywords":["react","menu","radial-menu","orbit-menu","navigation","button","animation","framer-motion"],"author":{"name":"Denis Bitter","email":"saghallo@denisbitter.de"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/THEORIGINALBITTER/bitter-button-menu.git"},"dependencies":{"framer-motion":"^11.0.0","react":"^18.2.0","react-dom":"^18.2.0","react-router-dom":"^6.20.0"},"devDependencies":{"@babel/core":"^7.29.0","@babel/preset-env":"^7.29.0","@babel/preset-react":"^7.28.5","@rollup/plugin-babel":"^6.1.0","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-node-resolve":"^15.2.3","@rollup/plugin-terser":"^0.4.4","@types/react":"^18.2.0","rollup":"^4.9.0","rollup-plugin-peer-deps-external":"^2.2.4","rollup-plugin-postcss":"^4.0.2","rollup-plugin-typescript2":"^0.36.0","typescript":"^5.3.3"},"gitHead":"071d5ed6ec333812cd88f0f3f242ec24f5ddd68e","_id":"@denisbitter/bitter-button-menu@1.0.0","bugs":{"url":"https://github.com/THEORIGINALBITTER/bitter-button-menu/issues"},"homepage":"https://github.com/THEORIGINALBITTER/bitter-button-menu#readme","_nodeVersion":"25.6.1","_npmVersion":"11.9.0","dist":{"integrity":"sha512-MhcCSwSji8DGKCFCNUgQgaCJoZOwAyVNTPTsGCSgsIG84LdzOi0mkfUT45YJf6YXEA5D1KX55PJ4fBlTkis53Q==","shasum":"2a34698060c6556adba5e655354a2b2accf6b60f","tarball":"https://registry.npmjs.org/@denisbitter/bitter-button-menu/-/bitter-button-menu-1.0.0.tgz","fileCount":7,"unpackedSize":226301,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBkG75xFtil6SrBMXwR7TWVESAomWxcyepzoGIyqhcKjAiEAjrth4PIi+5gIAfOTdn6KR9Gp4QlfoSqf/eDVVf753oY="}]},"_npmUser":{"name":"theoriginalbitter.de","email":"saghallo@theoriginalbitter.de"},"directories":{},"maintainers":[{"name":"theoriginalbitter.de","email":"saghallo@theoriginalbitter.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/bitter-button-menu_1.0.0_1771871508562_0.581951598725911"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-23T18:31:48.407Z","1.0.0":"2026-02-23T18:31:48.746Z","modified":"2026-02-23T18:31:48.975Z"},"maintainers":[{"name":"theoriginalbitter.de","email":"saghallo@theoriginalbitter.de"}],"description":"A beautiful radial/orbit menu button component with smooth animations","homepage":"https://github.com/THEORIGINALBITTER/bitter-button-menu#readme","keywords":["react","menu","radial-menu","orbit-menu","navigation","button","animation","framer-motion"],"repository":{"type":"git","url":"git+https://github.com/THEORIGINALBITTER/bitter-button-menu.git"},"author":{"name":"Denis Bitter","email":"saghallo@denisbitter.de"},"bugs":{"url":"https://github.com/THEORIGINALBITTER/bitter-button-menu/issues"},"license":"MIT","readme":"# @denisbitter/bitter-button-menu\n\nA beautiful, customizable radial/orbit menu button component for React applications with smooth animations powered by Framer Motion.\n\n![Version](https://img.shields.io/npm/v/@denisbitter/bitter-button-menu)\n![License](https://img.shields.io/npm/l/@denisbitter/bitter-button-menu)\n\n## Features\n\n- 🎨 **Highly Customizable**: Full control over colors, sizes, animations, and behavior\n- 🌀 **Radial Menu Layout**: Items arranged in a circle around the main button\n- ✨ **Smooth Animations**: Beautiful spring animations powered by Framer Motion\n- 📱 **Responsive**: Works on all screen sizes\n- 🎯 **TypeScript Support**: Full type definitions included\n- 🔧 **Easy Integration**: Works seamlessly with React Router\n- 🎭 **Submenu Support**: Nested menu capability\n- 💾 **Smart Persistence**: Tooltip state saved in localStorage\n- 🎪 **Scroll Behavior**: Button follows scroll with configurable behavior\n\n## Installation\n\n```bash\nnpm install @denisbitter/bitter-button-menu\n```\n\nor\n\n```bash\nyarn add @denisbitter/bitter-button-menu\n```\n\n## Basic Usage\n\n```jsx\nimport React from 'react';\nimport BitterButtonWithMenu from '@denisbitter/bitter-button-menu';\n\nfunction App() {\n  const mainMenuItems = [\n    {\n      id: \"home\",\n      label: \"Home\",\n      angle: 0,\n      route: \"/\",\n    },\n    {\n      id: \"about\",\n      label: \"About\",\n      angle: -90,\n      route: \"/about\",\n    },\n    {\n      id: \"contact\",\n      label: \"Contact\",\n      angle: -180,\n      route: \"/contact\",\n    }\n  ];\n\n  return (\n    <BitterButtonWithMenu\n      logoSrc=\"/path/to/your/logo.png\"\n      logoAlt=\"Menu\"\n      mainMenuItems={mainMenuItems}\n    />\n  );\n}\n\nexport default App;\n```\n\n## Advanced Usage\n\n### With Submenus\n\n```jsx\nimport React from 'react';\nimport BitterButtonWithMenu from '@denisbitter/bitter-button-menu';\n\nfunction App() {\n  const mainMenuItems = [\n    {\n      id: \"home\",\n      label: \"Home\",\n      angle: 0,\n      route: \"/\",\n    },\n    {\n      id: \"about\",\n      label: \"About\",\n      angle: -90,\n      action: \"openSubmenu\",\n      submenu: \"about\",\n      hasSubmenu: true,\n    }\n  ];\n\n  const submenuItems = {\n    about: [\n      {\n        id: \"back\",\n        label: \"Back\",\n        angle: 0,\n        action: \"closeSubmenu\",\n        isBack: true,\n      },\n      {\n        id: \"team\",\n        label: \"Team\",\n        angle: -60,\n        route: \"/about/team\",\n      },\n      {\n        id: \"history\",\n        label: \"History\",\n        angle: -120,\n        route: \"/about/history\",\n      }\n    ]\n  };\n\n  return (\n    <BitterButtonWithMenu\n      logoSrc=\"/path/to/your/logo.png\"\n      mainMenuItems={mainMenuItems}\n      submenuItems={submenuItems}\n    />\n  );\n}\n```\n\n### With Custom Configuration\n\n```jsx\nimport React from 'react';\nimport BitterButtonWithMenu from '@denisbitter/bitter-button-menu';\n\nfunction App() {\n  const customConfig = {\n    visual: {\n      radius: 120,\n      button: {\n        width: 70,\n        height: 70,\n      },\n      colors: {\n        backdrop: \"rgba(0, 0, 0, 0.3)\",\n      },\n    },\n    animation: {\n      menuItem: {\n        stiffness: 300,\n        damping: 25,\n        staggerDelay: 0.08,\n      },\n    },\n  };\n\n  const mainMenuItems = [\n    // ... your menu items\n  ];\n\n  return (\n    <BitterButtonWithMenu\n      logoSrc=\"/path/to/your/logo.png\"\n      mainMenuItems={mainMenuItems}\n      config={customConfig}\n      accentColor=\"#FF6B35\"\n      tooltipText=\"Open Menu\"\n      tooltipDuration={5000}\n    />\n  );\n}\n```\n\n### With Dynamic Name Context\n\n```jsx\nimport React from 'react';\nimport BitterButtonWithMenu from '@denisbitter/bitter-button-menu';\n\nfunction App() {\n  const mainMenuItems = [\n    {\n      id: \"home\",\n      label: \"Hello {name}\",\n      angle: 0,\n      route: \"/\",\n      dynamic: true,\n    }\n  ];\n\n  const nameContext = {\n    name: \"John\"\n  };\n\n  return (\n    <BitterButtonWithMenu\n      logoSrc=\"/path/to/your/logo.png\"\n      mainMenuItems={mainMenuItems}\n      nameContext={nameContext}\n    />\n  );\n}\n```\n\n## Props\n\n### BitterButtonWithMenu\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `logoSrc` | `string` | - | URL/path to the logo image |\n| `logoAlt` | `string` | `\"Menu Button\"` | Alt text for the logo |\n| `mainMenuItems` | `Array` | `[]` | Array of main menu item configurations |\n| `submenuItems` | `Object` | `{}` | Object with submenu configurations (key: submenu id) |\n| `onMenuClick` | `Function` | - | Callback when menu is toggled |\n| `onOverlayOpen` | `Function` | - | Callback when overlay action is triggered |\n| `config` | `Object` | default config | Custom configuration object |\n| `nameContext` | `Object` | - | Context for dynamic name replacement |\n| `tooltipText` | `string` | `\"Menü öffnen\"` | Text to show in tooltip |\n| `tooltipDuration` | `number` | `6000` | Duration tooltip stays visible (ms) |\n| `accentColor` | `string` | `\"#AC8E66\"` | Accent color for highlights |\n\n### Menu Item Configuration\n\n```typescript\n{\n  id: string;              // Unique identifier\n  label: string;           // Display text\n  angle: number;           // Position angle (-180 to 180)\n  route?: string;          // React Router route\n  action?: string;         // Action type: 'openOverlay', 'openSubmenu', 'closeSubmenu'\n  submenu?: string;        // Submenu ID (if action is 'openSubmenu')\n  hasSubmenu?: boolean;    // Indicates item has submenu\n  dynamic?: boolean;       // Enable dynamic label replacement\n  isMainMenu?: boolean;    // Style as main menu item\n  isBack?: boolean;        // Style as back button\n  onClick?: Function;      // Custom click handler\n}\n```\n\n### Configuration Object\n\n```typescript\n{\n  visual: {\n    radius: number;                    // Radius of menu circle\n    menuOffset: number;                // Offset when menu opens\n    colors: {\n      primary: string;\n      primaryDark: string;\n      background: string;\n      backgroundDark: string;\n      text: string;\n      border: string;\n      borderHighlight: string;\n      backdrop: string;\n    };\n    button: {\n      width: number;\n      height: number;\n      fontSize: string;\n      fontFamily: string;\n    };\n    backdrop: {\n      blur: string;\n      opacity: number;\n    };\n  };\n  animation: {\n    menuItem: {\n      stiffness: number;\n      damping: number;\n      staggerDelay: number;\n    };\n    backdrop: {\n      duration: number;\n    };\n  };\n}\n```\n\n## Hooks\n\n### useOrbitMenuConfig\n\nAccess and customize the menu configuration at runtime.\n\n```jsx\nimport { useOrbitMenuConfig } from '@denisbitter/bitter-button-menu';\n\nfunction CustomMenuControls() {\n  const { config, updateConfig, applyPreset, resetConfig } = useOrbitMenuConfig();\n\n  return (\n    <div>\n      <button onClick={() => updateConfig('visual.radius', 150)}>\n        Increase Radius\n      </button>\n      <button onClick={() => applyPreset('compact')}>\n        Apply Compact Preset\n      </button>\n      <button onClick={resetConfig}>\n        Reset to Default\n      </button>\n    </div>\n  );\n}\n```\n\n## Presets\n\nAvailable configuration presets:\n- `compact` - Smaller radius and faster animations\n- `spacious` - Larger radius and slower animations\n- `fast` - Quick, snappy animations\n- `smooth` - Slower, smoother animations\n\n## Styling\n\nThe component uses Tailwind CSS classes. Make sure you have Tailwind CSS configured in your project, or the styles won't work properly.\n\n### Tailwind Configuration\n\nAdd to your `tailwind.config.js`:\n\n```js\nmodule.exports = {\n  content: [\n    \"./src/**/*.{js,jsx,ts,tsx}\",\n    \"./node_modules/@denisbitter/bitter-button-menu/dist/**/*.js\"\n  ],\n  // ... rest of your config\n}\n```\n\n## Browser Support\n\n- Chrome (latest)\n- Firefox (latest)\n- Safari (latest)\n- Edge (latest)\n\n## Requirements\n\n- React 18+\n- React Router DOM 6+\n- Framer Motion 11+\n\n## License\n\nMIT © Denis Bitter\n\n## Author\n\nDenis Bitter\n- Email: saghallo@denisbitter.de\n- GitHub: [@THEORIGINALBITTER](https://github.com/THEORIGINALBITTER)\n- LinkedIn: [denisbitter](https://www.linkedin.com/in/denisbitter/)\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## Support\n\nIf you encounter any issues or have questions, please file an issue on the [GitHub repository](https://github.com/THEORIGINALBITTER/bitter-button-menu/issues).\n","readmeFilename":"README.md","_rev":"1-fad676ef3809cc7485725adde88e45ff"}