A customizable and lightweight React overflow menu component with a modern design.
npm install jattac.libs.web.overflow-menuOverflowMenu Component
IOverflowMenuItem Interface
bash
npm install jattac.libs.web.overflow-menu react react-dom framer-motion @radix-ui/react-dropdown-menu
`
> Note on Peer Dependencies: This component requires react, react-dom, framer-motion, and @radix-ui/react-dropdown-menu to be installed in your project.
Getting Started
Here's a basic example to get you up and running in seconds.
`jsx
import React from 'react';
import OverflowMenu, { IOverflowMenuItem } from 'jattac.libs.web.overflow-menu';
import 'jattac.libs.web.overflow-menu/dist/index.css'; // Don't forget to import the styles!
const App = () => {
const menuItems: IOverflowMenuItem[] = [
{
content: 'Edit Profile',
onClick: () => alert('Editing Profile!'),
},
{
content: 'View Settings',
onClick: () => alert('Viewing Settings!'),
},
{
content: 'Log Out',
onClick: () => alert('Logging Out!'),
},
];
return (
);
};
export default App;
`
API and Props
$3
The OverflowMenu component accepts the following props:
| Prop | Type | Required | Default | Description |
|-------------|-----------------------|----------|-------------|------------------------------------------------------------------------------------------------------------|
| items | IOverflowMenuItem[] | Yes | - | An array of objects that define the menu items. |
| icon | ReactNode | No | DefaultIcon | A custom trigger icon to open the menu. |
| className | string | No | '' | A CSS class to apply to the trigger button for custom styling. |
| portal | HTMLElement | No | null | A DOM element to render the menu into. Use this to prevent z-index issues with parent containers. |
$3
Each item in the items array must conform to this interface:
`typescript
interface IOverflowMenuItem {
content: React.ReactNode; // The content to display for the item.
onClick?: () => void; // Function to call when the item is clicked.
}
`
---
Recipes: From Zero to Expert
Here are some common use cases to help you get the most out of the component.
$3
You can provide any ReactNode as the trigger icon. This is great for using a custom SVG or an icon from a library like react-icons.
`jsx
import { BsThreeDotsVertical } from 'react-icons/bs';
// ...
} />
`
$3
The content property of a menu item can be any valid ReactNode. This allows you to create rich menu items with icons, styled text, and more.
`jsx
import { FiEdit, FiLogOut } from 'react-icons/fi';
const richMenuItems: IOverflowMenuItem[] = [
{
content: (
Edit Profile
),
onClick: () => alert('Editing Profile!'),
},
{
content: (
Log Out
),
onClick: () => alert('Logging Out!'),
},
];
// ...
`
$3
To avoid z-index issues with parent containers, you can render the menu in a React Portal.
`jsx
const App = () => {
const portalContainer = document.getElementById('portal-container');
// ...
return (
{/ ... other content ... /}
);
}
`
> Best Practice: Using a portal is highly recommended for menus that might be rendered inside complex layouts, such as tables, modals, or other components with their own stacking context.
---
Styling and Customization
The component is styled using CSS Modules, but it's designed to be easily customized. The underlying Radix UI components expose data- attributes that you can use to target specific states and parts of the menu.
Here are some of the most common selectors:
| Selector | Description |
|----------------------------------------|-------------------------------------------|
| [data-state="open"] | Applied to the trigger when the menu is open. |
| [data-state="closed"] | Applied to the trigger when the menu is closed. |
| .jattac-overflow-menu-content | The menu content container. |
| .jattac-overflow-menu-item | An individual menu item. |
| [data-highlighted] | Applied to a menu item when it is highlighted (e.g., on hover or with keyboard navigation). |
Example: Overriding the background color of a highlighted item
`css
/ In your application's global CSS file /
.jattac-overflow-menu-item[data-highlighted] {
background-color: #f0f0f0;
color: #333;
}
``