Created
September 16, 2025 19:33
-
-
Save ejabu/72f7ea92ca9c12f1c73ef156683c938f to your computer and use it in GitHub Desktop.
Revisions
-
ejabu created this gist
Sep 16, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,200 @@ import React, { useState } from 'react'; import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer, Cell } from 'recharts'; const data = [ { name: 'Jan', value: 400, details: 'Q1 Performance: Strong growth in new markets' }, { name: 'Feb', value: 300, details: 'Q1 Performance: Seasonal adjustment period' }, { name: 'Mar', value: 300, details: 'Q1 Performance: Recovery after February dip' }, { name: 'Apr', value: 200, details: 'Q2 Performance: Market consolidation phase' }, { name: 'May', value: 278, details: 'Q2 Performance: Mid-quarter improvement' }, { name: 'Jun', value: 189, details: 'Q2 Performance: End of quarter challenges' }, { name: 'Jul', value: 349, details: 'Q3 Performance: Summer campaign success' }, { name: 'Aug', value: 400, details: 'Q3 Performance: Peak season results' }, ]; const BarChartWithContextMenu = () => { const [contextMenu, setContextMenu] = useState(null); const [hoveredIndex, setHoveredIndex] = useState(null); const [activeSubmenu, setActiveSubmenu] = useState(null); const handleBarClick = (event, data, index) => { event.stopPropagation(); setContextMenu({ x: event.clientX, y: event.clientY, data: data, index: index }); }; const handleContextMenuAction = (action, data) => { console.log(`${action} clicked for:`, data); alert(`${action} selected for ${data.name}: ${data.details}`); setContextMenu(null); setActiveSubmenu(null); }; const handleClickOutside = () => { setContextMenu(null); setActiveSubmenu(null); }; const getBarColor = (index) => { return hoveredIndex === index ? '#ff6b6b' : '#8884d8'; }; return ( <div className="w-full h-96 p-4 bg-white relative" onClick={handleClickOutside} > <h2 className="text-2xl font-bold mb-4 text-gray-800">Monthly Performance</h2> <ResponsiveContainer width="100%" height="100%"> <BarChart data={data} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}> <XAxis dataKey="name" tick={{ fontSize: 12 }} axisLine={{ stroke: '#e0e0e0' }} /> <YAxis tick={{ fontSize: 12 }} axisLine={{ stroke: '#e0e0e0' }} gridline={{ stroke: '#f0f0f0' }} /> <Bar dataKey="value" radius={[4, 4, 0, 0]} onMouseEnter={(data, index) => setHoveredIndex(index)} onMouseLeave={() => setHoveredIndex(null)} > {data.map((entry, index) => ( <Cell key={`cell-${index}`} fill={getBarColor(index)} onClick={(event) => handleBarClick(event, entry, index)} style={{ cursor: 'pointer' }} /> ))} </Bar> </BarChart> </ResponsiveContainer> {contextMenu && ( <div className="absolute bg-white border border-gray-300 rounded-md shadow-lg z-10 min-w-48" style={{ left: contextMenu.x, top: contextMenu.y, }} onClick={(e) => e.stopPropagation()} > <div className="py-1"> <div className="px-4 py-2 text-sm font-medium text-gray-700 border-b border-gray-200"> {contextMenu.data.name} - {contextMenu.data.value} </div> <button className="block w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100" onClick={() => handleContextMenuAction('View Details', contextMenu.data)} > View Details </button> {/* Drill Down with submenu */} <div className="relative" onMouseEnter={() => setActiveSubmenu('drilldown')} onMouseLeave={() => setActiveSubmenu(null)} > <button className="flex items-center justify-between w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100"> <span>Drill Down</span> <span className="text-xs">▶</span> </button> {activeSubmenu === 'drilldown' && ( <div className="absolute left-full top-0 ml-1 bg-white border border-gray-300 rounded-md shadow-lg min-w-40"> <div className="py-1"> <button className="block w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100" onClick={() => handleContextMenuAction('Daily Breakdown', contextMenu.data)} > Daily Breakdown </button> <button className="block w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100" onClick={() => handleContextMenuAction('Weekly Analysis', contextMenu.data)} > Weekly Analysis </button> <button className="block w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100" onClick={() => handleContextMenuAction('Product Categories', contextMenu.data)} > Product Categories </button> <button className="block w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100" onClick={() => handleContextMenuAction('Regional Data', contextMenu.data)} > Regional Data </button> </div> </div> )} </div> {/* Export Data with submenu */} <div className="relative" onMouseEnter={() => setActiveSubmenu('export')} onMouseLeave={() => setActiveSubmenu(null)} > <button className="flex items-center justify-between w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100"> <span>Export Data</span> <span className="text-xs">▶</span> </button> {activeSubmenu === 'export' && ( <div className="absolute left-full top-0 ml-1 bg-white border border-gray-300 rounded-md shadow-lg min-w-32"> <div className="py-1"> <button className="block w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100" onClick={() => handleContextMenuAction('Export as CSV', contextMenu.data)} > CSV </button> <button className="block w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100" onClick={() => handleContextMenuAction('Export as PDF', contextMenu.data)} > PDF </button> <button className="block w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100" onClick={() => handleContextMenuAction('Export as Excel', contextMenu.data)} > Excel </button> <button className="block w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100" onClick={() => handleContextMenuAction('Export as JSON', contextMenu.data)} > JSON </button> </div> </div> )} </div> <button className="block w-full px-4 py-2 text-sm text-left text-gray-700 hover:bg-gray-100" onClick={() => handleContextMenuAction('Compare', contextMenu.data)} > Compare </button> </div> </div> )} </div> ); }; export default BarChartWithContextMenu;