Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| "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> | |
| ); | |
| } | |