quantization-picker / components /SentenceSelect.tsx
stevhliu's picture
stevhliu HF Staff
Build the quantization picker
5ae37d4
Raw
History Blame Contribute Delete
1.84 kB
"use client";
interface Option {
id: string;
label: string;
}
interface Props {
value: string;
options: Option[];
onChange: (id: string) => void;
/** matches the 40px display type of the surrounding sentence */
size?: "display" | "inline";
ariaLabel: string;
}
/**
* A dropdown that reads as part of a sentence. The native <select> is layered
* transparently over the rendered text so it stays keyboard and screen-reader
* navigable while looking like body copy.
*/
export default function SentenceSelect({
value,
options,
onChange,
size = "display",
ariaLabel,
}: Props) {
const current = options.find((o) => o.id === value) ?? options[0];
const display = size === "display";
return (
<span
className={`relative inline-flex items-center gap-2.5 rounded-md bg-paper ring-raised ${
display ? "h-[52px] px-3.5" : "h-9 px-3"
}`}
>
<span
className={
display
? "text-[40px] font-medium leading-[44px] tracking-[-0.04em] text-obsidian"
: "font-mono text-[13px] text-obsidian"
}
>
{current.label}
</span>
<svg
width="12"
height="12"
viewBox="0 0 12 12"
fill="none"
aria-hidden
className="shrink-0"
>
<path
d="M3 4.5L6 7.5L9 4.5"
stroke="#8f8f8f"
strokeWidth="1.4"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
<select
aria-label={ariaLabel}
value={value}
onChange={(e) => onChange(e.target.value)}
className="absolute inset-0 cursor-pointer opacity-0"
>
{options.map((o) => (
<option key={o.id} value={o.id}>
{o.label}
</option>
))}
</select>
</span>
);
}