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

84.61% Statements 11/13
66.66% Branches 14/21
100% Functions 2/2
100% Lines 9/9

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                                                                            9x                                                         1x                             10x     10x 10x 10x 10x   10x                                         1x  
import React, { forwardRef } from "react";
import { clsx } from "clsx";
import type { TriggerPosition, Severity } from "../../types";
import {
  DEFAULT_TRIGGER_POSITION,
  Z_INDEX,
} from "../../constants";
import styles from "./PanelTrigger.module.scss";
 
export interface PanelTriggerProps {
  /** Click handler */
  onClick: () => void;
  /** Position of the trigger button */
  position?: TriggerPosition;
  /** Z-index for the trigger */
  zIndex?: number;
  /** Current severity level */
  severity?: Severity;
  /** Custom content */
  children?: React.ReactNode;
  /** Custom class name */
  className?: string;
  /** Dark mode */
  isDark?: boolean;
  /** Accessible label */
  "aria-label"?: string;
}
 
/**
 * Memory icon SVG
 */
function MemoryIcon({
  className,
  style,
}: {
  className?: string;
  style?: React.CSSProperties;
}) {
  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}
      style={style}
    >
      <rect x="4" y="4" width="16" height="16" rx="2" />
      <rect x="9" y="9" width="6" height="6" />
      <path d="M9 1v3" />
      <path d="M15 1v3" />
      <path d="M9 20v3" />
      <path d="M15 20v3" />
      <path d="M20 9h3" />
      <path d="M20 14h3" />
      <path d="M1 9h3" />
      <path d="M1 14h3" />
    </svg>
  );
}
 
/**
 * Floating trigger button to open the panel
 */
export const PanelTrigger = forwardRef<HTMLButtonElement, PanelTriggerProps>(
  (
    {
      onClick,
      position = DEFAULT_TRIGGER_POSITION,
      zIndex = Z_INDEX.trigger,
      severity = "normal",
      children,
      className,
      isDark = false,
      "aria-label": ariaLabel = "Open Memory Monitor",
    },
    ref
  ) => {
    // Build position style
    const positionStyle: React.CSSProperties = {
      zIndex,
    };
    Iif (position.top !== undefined) positionStyle.top = position.top;
    Eif (position.bottom !== undefined) positionStyle.bottom = position.bottom;
    Iif (position.left !== undefined) positionStyle.left = position.left;
    Eif (position.right !== undefined) positionStyle.right = position.right;
 
    return (
      <button
        ref={ref}
        type="button"
        onClick={onClick}
        aria-label={ariaLabel}
        className={clsx(
          styles.trigger,
          severity === "warning" && styles.warning,
          severity === "critical" && styles.critical,
          isDark && "dark",
          className
        )}
        style={positionStyle}
      >
        {children || <MemoryIcon className={styles.icon} />}
      </button>
    );
  }
);
 
PanelTrigger.displayName = "PanelTrigger";