From 5020ce0ed7aa0187953393925b94542da18d232b Mon Sep 17 00:00:00 2001 From: Jan-Henrik Bruhn Date: Fri, 10 Oct 2025 23:26:48 +0200 Subject: [PATCH] refactor: consolidate duplicate panel headers into reusable component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consolidates three duplicate header implementations in RightPanel into a single reusable PanelHeader component, following DRY principles. Changes: - Created PanelHeader component in RightPanel.tsx with consistent props - Refactored Actor Properties to use PanelHeader - Refactored Relation Properties to use PanelHeader - Refactored Graph Analysis to use PanelHeader (removed internal header) - All panel headers now have consistent appearance and behavior - Supports optional close button and required collapse functionality Benefits: - Eliminates code duplication across panel views - Ensures consistent UX across all panel states - Easier to maintain and update header behavior in one place - Reduces bundle size by removing redundant JSX 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/components/Common/GraphMetrics.tsx | 21 +------- src/components/Panels/RightPanel.tsx | 66 +++++++++++++------------- 2 files changed, 35 insertions(+), 52 deletions(-) diff --git a/src/components/Common/GraphMetrics.tsx b/src/components/Common/GraphMetrics.tsx index 5a5c14c..3428b48 100644 --- a/src/components/Common/GraphMetrics.tsx +++ b/src/components/Common/GraphMetrics.tsx @@ -1,6 +1,5 @@ import { useMemo } from 'react'; -import { IconButton, Tooltip } from '@mui/material'; -import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import { Tooltip } from '@mui/material'; import WarningIcon from '@mui/icons-material/Warning'; import InfoIcon from '@mui/icons-material/Info'; import BarChartIcon from '@mui/icons-material/BarChart'; @@ -11,7 +10,6 @@ interface GraphMetricsProps { nodes: Actor[]; edges: Relation[]; onActorClick?: (actorId: string) => void; - onCollapse?: () => void; } /** @@ -20,7 +18,7 @@ interface GraphMetricsProps { * Shows when no node or edge is selected in the right panel. * Provides insights into graph structure, connectivity, and key actors. */ -const GraphMetrics = ({ nodes, edges, onActorClick, onCollapse }: GraphMetricsProps) => { +const GraphMetrics = ({ nodes, edges, onActorClick }: GraphMetricsProps) => { // Calculate all metrics (memoized for performance - auto-updates when nodes/edges change) const metrics = useMemo(() => { return calculateGraphMetrics(nodes, edges); @@ -36,21 +34,6 @@ const GraphMetrics = ({ nodes, edges, onActorClick, onCollapse }: GraphMetricsPr return (
- {/* Header */} -
-
- -

Graph Analysis

-
- {onCollapse && ( - - - - - - )} -
- {/* Scrollable Content */}
{/* Overview Section */} diff --git a/src/components/Panels/RightPanel.tsx b/src/components/Panels/RightPanel.tsx index 762bc52..05d999a 100644 --- a/src/components/Panels/RightPanel.tsx +++ b/src/components/Panels/RightPanel.tsx @@ -27,6 +27,35 @@ interface Props { onClose: () => void; } +/** + * PanelHeader - Reusable header component for right panel views + */ +interface PanelHeaderProps { + title: string; + onClose?: () => void; + onCollapse: () => void; +} + +const PanelHeader = ({ title, onClose, onCollapse }: PanelHeaderProps) => ( +
+

{title}

+
+ {onClose && ( + + + ✕ + + + )} + + + + + +
+
+); + const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => { const { @@ -181,7 +210,8 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => { className="h-full bg-white border-l border-gray-200 flex flex-col" style={{ width: `${rightPanelWidth}px` }} > - + + {ConfirmDialogComponent}
); @@ -196,22 +226,7 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => { className="h-full bg-white border-l border-gray-200 flex flex-col" style={{ width: `${rightPanelWidth}px` }} > - {/* Header */} -
-

Actor Properties

-
- - - ✕ - - - - - - - -
-
+ {/* Scrollable content */}
@@ -377,22 +392,7 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => { className="h-full bg-white border-l border-gray-200 flex flex-col" style={{ width: `${rightPanelWidth}px` }} > - {/* Header */} -
-

Relation Properties

-
- - - ✕ - - - - - - - -
-
+ {/* Scrollable content */}