All files / memory-monitor/src/components/Controls ThresholdSlider.tsx

83.33% Statements 5/6
76.19% Branches 16/21
50% Functions 1/2
83.33% Lines 5/6

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                                                                                                3x   3x             3x   3x                                                                                                       1x  
import React, { useCallback, useId } from "react";
import clsx from "clsx";
import styles from "./ThresholdSlider.module.scss";
 
export interface ThresholdSliderProps {
  /** Slider label */
  label: string;
  /** Current value (0-100) */
  value: number;
  /** Callback when value changes */
  onChange: (value: number) => void;
  /** Minimum value */
  min?: number;
  /** Maximum value */
  max?: number;
  /** Step increment */
  step?: number;
  /** Accent color */
  color?: string;
  /** Show value badge */
  showValue?: boolean;
  /** Disabled state */
  disabled?: boolean;
  /** Helper text */
  helperText?: string;
  /** Custom class name */
  className?: string;
  /** Value suffix (e.g., '%', 'samples') */
  suffix?: string;
}
 
/**
 * Threshold slider component for adjusting memory thresholds
 */
export function ThresholdSlider({
  label,
  value,
  onChange,
  min = 0,
  max = 100,
  step = 1,
  color = "#3b82f6",
  showValue = true,
  disabled = false,
  helperText,
  className,
  suffix = "%",
}: ThresholdSliderProps) {
  const id = useId();
 
  const handleChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      onChange(Number(e.target.value));
    },
    [onChange]
  );
 
  const percentage = ((value - min) / (max - min)) * 100;
 
  return (
    <div className={clsx(styles.container, className)}>
      {/* Label and value */}
      <div className={styles.header}>
        <label
          htmlFor={id}
          className={clsx(styles.label, disabled && styles.disabled)}
        >
          {label}
        </label>
        {showValue && (
          <span
            className={clsx(styles.valueBadge, disabled && styles.disabled)}
          >
            {value}
            {suffix}
          </span>
        )}
      </div>
 
      {/* Slider */}
      <div className={styles.sliderWrapper}>
        <input
          id={id}
          type="range"
          min={min}
          max={max}
          step={step}
          value={value}
          onChange={handleChange}
          disabled={disabled}
          className={clsx(styles.slider, disabled && styles.disabled)}
          style={{
            background: disabled
              ? undefined
              : `linear-gradient(to right, ${color} 0%, ${color} ${percentage}%, transparent ${percentage}%, transparent 100%)`,
            // @ts-expect-error CSS custom property
            "--thumb-color": color,
          }}
        />
      </div>
 
      {/* Helper text */}
      {helperText && (
        <p className={clsx(styles.helperText, disabled && styles.disabled)}>
          {helperText}
        </p>
      )}
    </div>
  );
}
 
ThresholdSlider.displayName = "ThresholdSlider";