Instantly share code, notes, and snippets.
Created
September 16, 2025 19:40
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save ejabu/68db0a9fee757592e39c41eb9d383cd6 to your computer and use it in GitHub Desktop.
Bar Chart, Drill Down with Shadcn context menu
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 characters
| import React, { useState } from 'react'; | |
| import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer, Cell } from 'recharts'; | |
| import { | |
| DropdownMenu, | |
| DropdownMenuContent, | |
| DropdownMenuItem, | |
| DropdownMenuLabel, | |
| DropdownMenuSeparator, | |
| DropdownMenuSub, | |
| DropdownMenuSubContent, | |
| DropdownMenuSubTrigger, | |
| DropdownMenuTrigger, | |
| } from '@/components/ui/dropdown-menu'; | |
| 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 [dropdownOpen, setDropdownOpen] = useState(false); | |
| const handleBarClick = (event, data, index) => { | |
| event.stopPropagation(); | |
| setContextMenu({ | |
| x: event.clientX, | |
| y: event.clientY, | |
| data: data, | |
| index: index | |
| }); | |
| setDropdownOpen(true); | |
| }; | |
| const handleContextMenuAction = (action, data) => { | |
| console.log(`${action} clicked for:`, data); | |
| alert(`${action} selected for ${data.name}: ${data.details}`); | |
| setContextMenu(null); | |
| setDropdownOpen(false); | |
| }; | |
| const handleClickOutside = () => { | |
| setContextMenu(null); | |
| setDropdownOpen(false); | |
| }; | |
| 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="fixed z-50" | |
| style={{ | |
| left: contextMenu.x, | |
| top: contextMenu.y, | |
| }} | |
| > | |
| <DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}> | |
| <DropdownMenuTrigger asChild> | |
| <div className="w-0 h-0" /> | |
| </DropdownMenuTrigger> | |
| <DropdownMenuContent className="w-56"> | |
| <DropdownMenuLabel> | |
| {contextMenu.data.name} - {contextMenu.data.value} | |
| </DropdownMenuLabel> | |
| <DropdownMenuSeparator /> | |
| <DropdownMenuItem | |
| onClick={() => handleContextMenuAction('View Details', contextMenu.data)} | |
| > | |
| View Details | |
| </DropdownMenuItem> | |
| <DropdownMenuSub> | |
| <DropdownMenuSubTrigger> | |
| Drill Down | |
| </DropdownMenuSubTrigger> | |
| <DropdownMenuSubContent> | |
| <DropdownMenuItem | |
| onClick={() => handleContextMenuAction('Daily Breakdown', contextMenu.data)} | |
| > | |
| Daily Breakdown | |
| </DropdownMenuItem> | |
| <DropdownMenuItem | |
| onClick={() => handleContextMenuAction('Weekly Analysis', contextMenu.data)} | |
| > | |
| Weekly Analysis | |
| </DropdownMenuItem> | |
| <DropdownMenuItem | |
| onClick={() => handleContextMenuAction('Product Categories', contextMenu.data)} | |
| > | |
| Product Categories | |
| </DropdownMenuItem> | |
| <DropdownMenuItem | |
| onClick={() => handleContextMenuAction('Regional Data', contextMenu.data)} | |
| > | |
| Regional Data | |
| </DropdownMenuItem> | |
| </DropdownMenuSubContent> | |
| </DropdownMenuSub> | |
| <DropdownMenuSub> | |
| <DropdownMenuSubTrigger> | |
| Export Data | |
| </DropdownMenuSubTrigger> | |
| <DropdownMenuSubContent> | |
| <DropdownMenuItem | |
| onClick={() => handleContextMenuAction('Export as CSV', contextMenu.data)} | |
| > | |
| CSV | |
| </DropdownMenuItem> | |
| <DropdownMenuItem | |
| onClick={() => handleContextMenuAction('Export as PDF', contextMenu.data)} | |
| > | |
| </DropdownMenuItem> | |
| <DropdownMenuItem | |
| onClick={() => handleContextMenuAction('Export as Excel', contextMenu.data)} | |
| > | |
| Excel | |
| </DropdownMenuItem> | |
| <DropdownMenuItem | |
| onClick={() => handleContextMenuAction('Export as JSON', contextMenu.data)} | |
| > | |
| JSON | |
| </DropdownMenuItem> | |
| </DropdownMenuSubContent> | |
| </DropdownMenuSub> | |
| <DropdownMenuSeparator /> | |
| <DropdownMenuItem | |
| onClick={() => handleContextMenuAction('Compare', contextMenu.data)} | |
| > | |
| Compare | |
| </DropdownMenuItem> | |
| </DropdownMenuContent> | |
| </DropdownMenu> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| }; | |
| export default BarChartWithContextMenu; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment