import type { ReactNode } from "react";
import type { TableSortOrder } from "@/lib/table-sort";
import styles from "./SortableTh.module.css";
type SortableThAlign = "left" | "center" | "right";
const thAlignClass: Record<SortableThAlign, string> = {
left: styles.thSortableAlignLeft,
center: styles.thSortableAlignCenter,
right: styles.thSortableAlignRight,
};
const buttonAlignClass: Record<SortableThAlign, string> = {
left: styles.sortButtonAlignLeft,
center: styles.sortButtonAlignCenter,
right: styles.sortButtonAlignRight,
};
export type SortableThProps = {
label: string;
order: TableSortOrder | null;
onClick: () => void;
disabled?: boolean;
ariaLabel: string;
align: SortableThAlign;
children?: ReactNode;
};
/**
* 並べ替え可能な `<th>`(ボタン+印。`children` で同セルに別ボタンを並べられる)
*
* ★`children` があるときも th 自体は table-cell のまま★(指示書BH §11 R1)。
* 中身だけ `thInner`(inline-flex)で並べる。
*/
export function SortableTh({
label,
order,
onClick,
disabled,
ariaLabel,
align,
children,
}: SortableThProps) {
const hasChildren = children != null;
const button = (
<button
type="button"
className={`${styles.sortButton} ${buttonAlignClass[align]}${hasChildren ? ` ${styles.sortButtonWithChildren}` : ""}`}
aria-label={ariaLabel}
title={ariaLabel}
onClick={onClick}
disabled={disabled}
>
{label}
<span
className={order ? styles.sortMarkActive : styles.sortMark}
aria-hidden="true"
>
{order === "desc" ? "▼" : order === "asc" ? "▲" : "△"}
</span>
</button>
);
return (
<th
className={`${styles.thSortable} ${thAlignClass[align]}`}
aria-sort={
order === "desc" ? "descending" : order === "asc" ? "ascending" : undefined
}
>
{hasChildren ? (
<span className={styles.thInner}>
{button}
{children}
</span>
) : (
button
)}
</th>
);
}