Package Exports
- nachtify
- nachtify/src/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (nachtify) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
React Color Palette Context Menu Library
A reusable React library for adding a color palette context menu with column-based color application to your tables and data displays.
Features
✅ Context Menu with Color Palette - Right-click to open a color picker menu ✅ Column-Based Color Application - Apply colors to specific columns or groups ✅ localStorage Persistence - Colors are automatically saved and loaded ✅ Circular Color Swatches - Beautiful UI with 11 predefined colors ✅ Arrow Navigation - Scroll through colors with left/right arrows ✅ Group Color Support - Apply colors to all rows in a group (e.g., gender) ✅ Export/Import - Save and load color schemes as JSON files ✅ Customizable Menu Items - Add custom actions to the context menu
Installation
npm install react-color-palette-context-menu
# or
yarn add react-color-palette-context-menuQuick Start
1. Import the component and library
import {
ColorPaletteContextMenu,
THEME_COLORS,
loadColors,
saveColors,
applyColumnColor,
getColumnColor,
applyGroupColor,
getGroupColor
} from 'react-color-palette-context-menu';2. Set up state
import { useState, useEffect } from 'react';
export default function MyTable() {
const [colors, setColors] = useState(() => loadColors());
const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0, row: null, column: null });
const [colorScrollIndex, setColorScrollIndex] = useState(0);
// Auto-save colors to localStorage
useEffect(() => {
saveColors(colors);
}, [colors]);
const handleRowContextMenu = (e, rowId, column) => {
e.preventDefault();
setContextMenu({
visible: true,
x: e.clientX,
y: e.clientY,
row: rowId,
column: column
});
};
const closeContextMenu = () => {
setContextMenu({ visible: false, x: 0, y: 0, row: null, column: null });
};
return (
<div>
<table>
<tbody>
{data.map(row => (
<tr
key={row.id}
onContextMenu={(e) => handleRowContextMenu(e, row.id, 'name')}
style={{ backgroundColor: getGroupColor(colors, `group-${row.group}`) }}
>
<td style={{ backgroundColor: getColumnColor(colors, row.id, 'name') }}>
{row.name}
</td>
</tr>
))}
</tbody>
</table>
<ColorPaletteContextMenu
visible={contextMenu.visible}
x={contextMenu.x}
y={contextMenu.y}
colorScrollIndex={colorScrollIndex}
onColorScrollChange={setColorScrollIndex}
onColorSelect={(color) => {
setColors(prev => applyColumnColor(prev, contextMenu.row, contextMenu.column, color));
closeContextMenu();
}}
onClose={closeContextMenu}
menuItems={[
{
label: 'Edit',
icon: <Edit3 size={16} />,
onClick: () => console.log('Edit'),
hasBorder: true
},
{
label: 'Delete',
icon: <Trash2 size={16} />,
onClick: () => console.log('Delete'),
isDanger: true
}
]}
/>
</div>
);
}API Reference
Components
ColorPaletteContextMenu
A context menu component with integrated color palette.
Props:
visible(boolean) - Show/hide the menux(number) - X positiony(number) - Y positioncolorScrollIndex(number) - Current scroll position in color paletteonColorScrollChange(function) - Called when scrolling colorsonColorSelect(function) - Called when a color is selectedonClose(function) - Called when menu should closemenuItems(array) - Custom menu itemsshowColorPalette(boolean) - Show/hide color palette (default: true)title(string) - Color palette section title (default: 'Theme Color')
Menu Item Structure:
{
label: 'Item Label',
icon: <IconComponent />,
onClick: () => {},
hasBorder: true, // Show border below item
isDanger: false // Red color for dangerous actions
}Library Functions
loadColors()
Load colors from localStorage.
const colors = loadColors();saveColors(colors)
Save colors to localStorage.
saveColors(colors);clearColors()
Clear all colors from localStorage.
clearColors();applyColumnColor(colors, rowId, column, color)
Apply color to a specific row and column.
const updated = applyColumnColor(colors, 1, 'name', THEME_COLORS[2]);getColumnColor(colors, rowId, column, fallbackColor)
Get color for a specific row and column.
const color = getColumnColor(colors, 1, 'name', 'transparent');applyGroupColor(colors, groupKey, color)
Apply color to all rows in a group.
const updated = applyGroupColor(colors, 'gender-Male', THEME_COLORS[2]);getGroupColor(colors, groupKey)
Get color for a group.
const color = getGroupColor(colors, 'gender-Male');exportColorsToFile(colors, filename)
Export colors to a JSON file.
exportColorsToFile(colors, 'my-colors.json');importColorsFromFile(file)
Import colors from a JSON file.
const colors = await importColorsFromFile(fileInput.files[0]);Constants
THEME_COLORS
Array of 11 predefined colors:
[
{ name: 'Default', value: 'default', primary: '#FFFFFF', ... },
{ name: 'Indigo', value: 'indigo', primary: '#4F46E5', ... },
{ name: 'Blue', value: 'blue', primary: '#3B82F6', ... },
{ name: 'Purple', value: 'purple', primary: '#9333EA', ... },
{ name: 'Pink', value: 'pink', primary: '#EC4899', ... },
{ name: 'Red', value: 'red', primary: '#EF4444', ... },
{ name: 'Orange', value: 'orange', primary: '#F97316', ... },
{ name: 'Amber', value: 'amber', primary: '#F59E0B', ... },
{ name: 'Green', value: 'green', primary: '#10B981', ... },
{ name: 'Teal', value: 'teal', primary: '#14B8A6', ... },
{ name: 'Cyan', value: 'cyan', primary: '#06B6D4', ... }
]localStorage Structure
Colors are stored under the key colorPaletteData:
{
"1-name": "#4F46E5",
"2-name": "#3B82F6",
"gender-Male": "#10B981",
"gender-Female": "#EC4899"
}Example: Complete Table with Color Palette
import { useState, useEffect } from 'react';
import { Edit3, Trash2 } from 'lucide-react';
import {
ColorPaletteContextMenu,
loadColors,
saveColors,
applyColumnColor,
getColumnColor,
applyGroupColor,
getGroupColor
} from 'react-color-palette-context-menu';
export default function DataTable() {
const [colors, setColors] = useState(() => loadColors());
const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0, row: null, column: null });
const [colorScrollIndex, setColorScrollIndex] = useState(0);
const data = [
{ id: 1, name: 'John Doe', gender: 'Male', department: 'Sales' },
{ id: 2, name: 'Jane Smith', gender: 'Female', department: 'Marketing' },
{ id: 3, name: 'Bob Johnson', gender: 'Male', department: 'IT' }
];
useEffect(() => {
saveColors(colors);
}, [colors]);
const handleContextMenu = (e, rowId, column) => {
e.preventDefault();
setContextMenu({
visible: true,
x: e.clientX,
y: e.clientY,
row: rowId,
column: column
});
};
const closeContextMenu = () => {
setContextMenu({ visible: false, x: 0, y: 0, row: null, column: null });
};
return (
<div className="p-8">
<table className="w-full border-collapse">
<thead>
<tr className="bg-gray-100">
<th className="px-4 py-2 text-left">Name</th>
<th className="px-4 py-2 text-left">Gender</th>
<th className="px-4 py-2 text-left">Department</th>
</tr>
</thead>
<tbody>
{data.map(row => (
<tr
key={row.id}
style={{ backgroundColor: getGroupColor(colors, `gender-${row.gender}`) }}
>
<td
className="px-4 py-2 cursor-context-menu"
onContextMenu={(e) => handleContextMenu(e, row.id, 'name')}
style={{ backgroundColor: getColumnColor(colors, row.id, 'name') }}
>
{row.name}
</td>
<td className="px-4 py-2">{row.gender}</td>
<td className="px-4 py-2">{row.department}</td>
</tr>
))}
</tbody>
</table>
<ColorPaletteContextMenu
visible={contextMenu.visible}
x={contextMenu.x}
y={contextMenu.y}
colorScrollIndex={colorScrollIndex}
onColorScrollChange={setColorScrollIndex}
onColorSelect={(color) => {
setColors(prev => applyColumnColor(prev, contextMenu.row, contextMenu.column, color));
closeContextMenu();
}}
onClose={closeContextMenu}
menuItems={[
{
label: 'Edit',
icon: <Edit3 size={16} />,
onClick: () => alert('Edit clicked'),
hasBorder: true
},
{
label: 'Delete',
icon: <Trash2 size={16} />,
onClick: () => alert('Delete clicked'),
isDanger: true
}
]}
/>
</div>
);
}How It Works
- Right-click on a cell → Context menu appears with color palette
- Select a color → Color is applied to that cell/column
- Colors are saved → Automatically persisted to localStorage
- Page refresh → Colors are restored from localStorage
Styling
The component uses Tailwind CSS classes. Make sure Tailwind CSS is installed in your project:
npm install -D tailwindcss postcss autoprefixerBrowser Support
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.