sendou.ink/app/components/SortableTableHeader.tsx
Kalle 6e987d506f
Some checks are pending
E2E Tests / e2e (push) Waiting to run
Tests and checks on push / run-checks-and-tests (push) Waiting to run
Updates translation progress / update-translation-progress-issue (push) Waiting to run
Tournament layout refresh, improve admin experience (#3152)
2026-06-11 18:31:10 +03:00

58 lines
1.2 KiB
TypeScript

import clsx from "clsx";
import { ArrowDown, ArrowUp, ChevronsUpDown } from "lucide-react";
import styles from "./SortableTableHeader.module.css";
export type SortDirection = "asc" | "desc";
export type SortState<Key extends string = string> = {
key: Key;
dir: SortDirection;
} | null;
export function SortableTableHeader<Key extends string>({
label,
sortKey,
sort,
onChange,
}: {
label: string;
sortKey: Key;
sort: SortState<Key>;
onChange: (next: SortState<Key>) => void;
}) {
const active = sort?.key === sortKey;
return (
<th>
<button
type="button"
className={styles.sortHeader}
onClick={() => onChange(nextSortState(sort, sortKey))}
>
{label}
{active ? (
sort.dir === "asc" ? (
<ArrowUp className={styles.sortIcon} />
) : (
<ArrowDown className={styles.sortIcon} />
)
) : (
<ChevronsUpDown
className={clsx(styles.sortIcon, styles.sortIconInactive)}
aria-hidden
/>
)}
</button>
</th>
);
}
function nextSortState<Key extends string>(
current: SortState<Key>,
key: Key,
): SortState<Key> {
if (current?.key !== key) return { key, dir: "asc" };
if (current.dir === "asc") return { key, dir: "desc" };
return null;
}