All files / memory-monitor/src/components/Panel PanelHeader.tsx

80% Statements 4/5
63.63% Branches 7/11
66.66% Functions 2/3
80% Lines 4/5

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129                                                  30x                                                                                                     30x   30x                                                                                                 1x  
import React from "react";
import { clsx } from "clsx";
import type { Severity } from "../../types";
import { SEVERITY_COLORS } from "../../constants";
import styles from "./PanelHeader.module.scss";
 
export interface PanelHeaderProps {
  /** Panel title */
  title?: string;
  /** Current severity level */
  severity?: Severity;
  /** Whether monitoring is active */
  isMonitoring?: boolean;
  /** Close button handler */
  onClose: () => void;
  /** Minimize button handler */
  onMinimize?: () => void;
  /** Custom class name */
  className?: string;
}
 
/**
 * Close icon SVG
 */
function CloseIcon({ className }: { className?: string }) {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
      strokeLinecap="round"
      strokeLinejoin="round"
      className={className}
    >
      <path d="M18 6L6 18" />
      <path d="M6 6l12 12" />
    </svg>
  );
}
 
/**
 * Minimize icon SVG
 */
function MinimizeIcon({ className }: { className?: string }) {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
      strokeLinecap="round"
      strokeLinejoin="round"
      className={className}
    >
      <path d="M8 3v3a2 2 0 0 1-2 2H3" />
      <path d="M21 8h-3a2 2 0 0 1-2-2V3" />
      <path d="M3 16h3a2 2 0 0 1 2 2v3" />
      <path d="M16 21v-3a2 2 0 0 1 2-2h3" />
    </svg>
  );
}
 
/**
 * Panel header component with title and controls
 */
export function PanelHeader({
  title = "Memory Monitor",
  severity = "normal",
  isMonitoring = false,
  onClose,
  onMinimize,
  className,
}: PanelHeaderProps) {
  const severityColor = SEVERITY_COLORS[severity];
 
  return (
    <div className={clsx(styles.header, className)}>
      {/* Title and status */}
      <div className={styles.titleSection}>
        <h2 className={styles.title}>{title}</h2>
 
        {/* Monitoring status indicator */}
        <div className={styles.statusIndicator}>
          <span
            className={clsx(
              styles.statusDot,
              isMonitoring ? styles.active : styles.paused
            )}
            style={{
              backgroundColor: isMonitoring ? severityColor.accent : undefined,
            }}
          />
          <span className={styles.statusText}>
            {isMonitoring ? "Live" : "Paused"}
          </span>
        </div>
      </div>
 
      {/* Control buttons */}
      <div className={styles.controls}>
        {onMinimize && (
          <button
            type="button"
            onClick={onMinimize}
            aria-label="Minimize panel"
            className={styles.controlButton}
          >
            <MinimizeIcon className={styles.icon} />
          </button>
        )}
 
        <button
          type="button"
          onClick={onClose}
          aria-label="Close panel"
          className={styles.controlButton}
        >
          <CloseIcon className={styles.icon} />
        </button>
      </div>
    </div>
  );
}
 
PanelHeader.displayName = "PanelHeader";