All files / src/components/admin/monitoring SortableTableHeader.tsx

100% Statements 83/83
100% Branches 10/10
100% Functions 2/2
100% Lines 83/83

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 841x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 5x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 299x 83x 83x 83x 83x 83x 299x 216x 216x 216x 216x 216x 299x 299x 299x 299x 299x 299x 1x 1x  
'use client';
 
import React from 'react';
import { Icon } from '@/components/ui/icons';
import { cn } from '@/lib/core';
 
/**
 * Sort state for table
 */
export interface SortState {
  key: string;
  direction: 'asc' | 'desc';
}
 
export interface SortableTableHeaderProps {
  /** Column label */
  label: string;
  /** Sort key for this column */
  sortKey: string;
  /** Current sort state */
  currentSort: SortState;
  /** Callback when column header is clicked */
  onSort: (key: string) => void;
  /** Additional class names */
  className?: string;
}
 
/**
 * SortableTableHeader Component
 *
 * A clickable table header cell that shows sort direction
 * and triggers sort changes.
 */
export function SortableTableHeader({
  label,
  sortKey,
  currentSort,
  onSort,
  className,
}: SortableTableHeaderProps) {
  const isActive = currentSort.key === sortKey;
 
  const handleClick = () => {
    onSort(sortKey);
  };
 
  return (
    <th
      className={cn(
        'px-6 py-3 text-left text-xs font-medium uppercase tracking-wider',
        'cursor-pointer select-none',
        'text-gray-500 dark:text-gray-300',
        'hover:bg-gray-100 dark:hover:bg-gray-600',
        'transition-colors',
        className
      )}
      onClick={handleClick}
      role="columnheader"
      aria-sort={isActive ? (currentSort.direction === 'asc' ? 'ascending' : 'descending') : 'none'}
    >
      <div className="flex items-center gap-1">
        <span>{label}</span>
        <span className="flex flex-col">
          {isActive ? (
            <Icon
              name={currentSort.direction === 'asc' ? 'chevron-up' : 'chevron-down'}
              size={14}
              className="text-blue-500"
            />
          ) : (
            <Icon
              name="chevron-down"
              size={14}
              className="opacity-30"
            />
          )}
        </span>
      </div>
    </th>
  );
}
 
export default SortableTableHeader;