JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 2
  • Score
    100M100P100Q33339F
  • License MIT

A reusable React library for color palette context menu with column-based color application

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-menu

Quick 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 menu
  • x (number) - X position
  • y (number) - Y position
  • colorScrollIndex (number) - Current scroll position in color palette
  • onColorScrollChange (function) - Called when scrolling colors
  • onColorSelect (function) - Called when a color is selected
  • onClose (function) - Called when menu should close
  • menuItems (array) - Custom menu items
  • showColorPalette (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

  1. Right-click on a cell → Context menu appears with color palette
  2. Select a color → Color is applied to that cell/column
  3. Colors are saved → Automatically persisted to localStorage
  4. 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 autoprefixer

Browser Support

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.