58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
import type { DigitCompletion } from "../state/gameplayHelpers";
|
|
import { symbolFor } from "../state/session";
|
|
|
|
function completionLabel(item: DigitCompletion, size: number): string {
|
|
const symbol = symbolFor(item.digit, size);
|
|
if (item.status === "done")
|
|
return `Digit ${symbol}: complete, ${String(item.placed)} of ${String(item.target)} placed`;
|
|
if (item.status === "overdone")
|
|
return `Digit ${symbol}: overdone by ${String(item.excess)}, ${String(item.placed)} of ${String(item.target)} placed`;
|
|
return `Digit ${symbol}: ${String(item.remaining)} remaining, ${String(item.placed)} of ${String(item.target)} placed`;
|
|
}
|
|
|
|
export function DigitCompletionBar({
|
|
size,
|
|
completions,
|
|
highlightedDigit,
|
|
highlightingEnabled,
|
|
onHighlight,
|
|
}: {
|
|
size: number;
|
|
completions: readonly DigitCompletion[];
|
|
highlightedDigit: number | null;
|
|
highlightingEnabled: boolean;
|
|
onHighlight: (digit: number) => void;
|
|
}) {
|
|
return (
|
|
<section className="digit-completion" aria-label="Digit completion">
|
|
<div className="digit-completion__heading">
|
|
<span>Digit progress</span>
|
|
<small>muted = complete · red = too many</small>
|
|
</div>
|
|
<div
|
|
className={`digit-completion__bar${size > 9 ? " digit-completion__bar--wide" : ""}`}
|
|
role="group"
|
|
aria-label="Highlight matching digits"
|
|
>
|
|
{completions.map((item) => (
|
|
<button
|
|
key={item.digit}
|
|
type="button"
|
|
className={`digit-completion__digit is-${item.status}${highlightedDigit === item.digit ? " is-highlighted" : ""}`}
|
|
aria-label={completionLabel(item, size)}
|
|
aria-pressed={highlightedDigit === item.digit}
|
|
disabled={!highlightingEnabled}
|
|
title={completionLabel(item, size)}
|
|
onClick={() => onHighlight(item.digit)}
|
|
>
|
|
<strong>{symbolFor(item.digit, size)}</strong>
|
|
<span>
|
|
{item.placed}/{item.target}
|
|
</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|