File size: 2,124 Bytes
5ae37d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54513db
5ae37d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
"use client";

import {
  Combobox,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxInput,
  ComboboxItem,
  ComboboxList,
  ComboboxTrigger,
  ComboboxValue,
} from "@/components/ui/combobox";

export interface Option {
  id: string;
  label: string;
}

interface Props {
  value: string;
  options: Option[];
  onChange: (id: string) => void;
  ariaLabel: string;
  /** shown in the search field inside the popup */
  placeholder?: string;
  /** render the value in placeholder grey — a default nobody has confirmed yet */
  muted?: boolean;
}

/**
 * A type-ahead that reads as part of the sentence. Same chip as
 * SentenceSelect, but the list is long enough (316 hardware configurations)
 * that scrolling it is hopeless — so the popup opens on a search field.
 */
export default function SentenceCombobox({
  value,
  options,
  onChange,
  ariaLabel,
  placeholder = "Search",
  muted = false,
}: Props) {
  const current = options.find((o) => o.id === value) ?? options[0];

  return (
    <Combobox
      items={options}
      value={current}
      onValueChange={(o: Option | null) => o && onChange(o.id)}
      itemToStringLabel={(o: Option) => o.label}
    >
      <ComboboxTrigger
        aria-label={ariaLabel}
        className={`inline-flex h-[38px] lg:h-[52px] items-center gap-2.5 rounded-md bg-paper px-2.5 lg:px-3.5 text-[26px] font-medium leading-[30px] lg:text-[40px] lg:leading-[44px] tracking-[-0.04em] ring-raised [&_svg]:text-graphite ${
          muted ? "text-ash" : "text-obsidian"
        }`}
      >
        <ComboboxValue />
      </ComboboxTrigger>
      <ComboboxContent className="min-w-[280px] border-hairline bg-paper">
        <ComboboxInput placeholder={placeholder} showTrigger={false} />
        <ComboboxEmpty className="font-mono text-[13px] text-graphite">
          Nothing matches
        </ComboboxEmpty>
        <ComboboxList>
          {(o: Option) => (
            <ComboboxItem key={o.id} value={o} className="font-mono text-[13px]">
              {o.label}
            </ComboboxItem>
          )}
        </ComboboxList>
      </ComboboxContent>
    </Combobox>
  );
}