All files / src/components/admin TaxonomyTypeSelector.tsx

100% Statements 4/4
100% Branches 2/2
100% Functions 3/3
100% Lines 4/4

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                                                                95x             1056x 1056x         6x                            
import type {
	TaxonomyType,
	TaxonomyConfig,
} from "../../pages/admin/taxonomy.config";
 
interface TaxonomyTypeSelectorProps {
	configs: TaxonomyConfig[];
	activeTab: TaxonomyType;
	onTabChange: (tab: TaxonomyType) => void;
}
 
/**
 * `.tabrail` — the Job Book's 2px underline rail.
 *
 * This used to be a row of filled `rounded-md` buttons inside a boxed card:
 * the selected one went solid `primary-600`, which reads as a pill and spends
 * a filled block on something that is navigation, not state. The mockups print
 * a tab as a label over a 2px bottom rule (`.tabrail` / `.tabrail-tab` in
 * `.context/mockups/_base.css` §7.8); the current tab carries the rule, hovers
 * tint, and the whole thing sits on a hairline rather than in a box.
 *
 * `aria-pressed` is what carries the selection to a screen reader, so the
 * state is never in the colour alone. It is deliberately NOT `role="tab"`:
 * a real tablist owes the user arrow-key navigation and a matching tabpanel,
 * and these buttons swap the page's data rather than reveal a panel. Same
 * decision as `components/admin/FacetRow.tsx`.
 */
export function TaxonomyTypeSelector({
	configs,
	activeTab,
	onTabChange,
}: TaxonomyTypeSelectorProps) {
	return (
		// `fieldset` rather than `div role="group"`: native grouping semantics,
		// which Biome's useSemanticElements rightly prefers. The resets undo the
		// UA stylesheet so the rail stays a hairline.
		<fieldset className="m-0 flex min-w-0 items-stretch gap-0.5 overflow-x-auto border-0 border-b border-border-default p-0">
			<legend className="sr-only">Taxonomy type</legend>
			{configs.map((config) => {
				const isActive = activeTab === config.key;
				return (
					<button
						key={config.key}
						type="button"
						aria-pressed={isActive}
						onClick={() => onTabChange(config.key)}
						className={`-mb-px inline-flex min-h-10 items-center whitespace-nowrap border-b-2 px-3 text-sm font-semibold transition-colors hover:bg-foreground-default/7 ${
							isActive
								? "border-secondary-600 text-foreground-default"
								: "border-transparent text-foreground-muted hover:text-foreground-default"
						}`}
					>
						{config.label}
					</button>
				);
			})}
		</fieldset>
	);
}