remix-demo

react router (remix) demo

git clone https://9o.is/git/remix-demo.git

InputCombobox.tsx

(1865B)


      1 import { useControlField, useField } from "remix-validated-form";
      2 import {
      3   Combobox,
      4   ComboboxInput,
      5   ComboboxPopover,
      6   ComboboxList,
      7   ComboboxOption,
      8 } from "@reach/combobox";
      9 import { getInputStyles } from "./Input";
     10 import InputError from "./InputError";
     11 
     12 interface InputComboboxProps {
     13   label: string;
     14   name: string;
     15   options: string[];
     16   onInputChange?: (input: string) => void;
     17   onSelect?: (input: string) => void;
     18   required?: boolean;
     19 }
     20 
     21 export default function InputCombobox(props: InputComboboxProps) {
     22   const { label, name, options, onInputChange, onSelect, required } = props;
     23   const { error, getInputProps, validate } = useField(name);
     24   const [, setValue] = useControlField<string>(name);
     25 
     26   function handleChange(value: string) {
     27     if (onInputChange) onInputChange(value);
     28     setValue(value);
     29     validate();
     30   }
     31 
     32   function handleSelect(value: string) {
     33     if (onSelect) onSelect(value);
     34     setValue(value);
     35     validate();
     36   }
     37 
     38   return (
     39     <div>
     40       <label htmlFor={name} className={getInputStyles("label", error)}>
     41         {label}
     42       </label>
     43       <Combobox onSelect={handleSelect} aria-label={`choose a ${label}`}>
     44         <ComboboxInput
     45           {...getInputProps({
     46             type: "text",
     47             onChange: (e) => handleChange(e.target.value),
     48           })}
     49           id={name}
     50           name={name}
     51           required={required}
     52           className={getInputStyles("input", error)}
     53           aria-invalid={Boolean(error)}
     54           aria-describedby={`${name}-error`}
     55         />
     56         <ComboboxPopover className="rounded">
     57           <ComboboxList>
     58             {options.map((option) => (
     59               <ComboboxOption key={option} value={option} />
     60             ))}
     61           </ComboboxList>
     62         </ComboboxPopover>
     63       </Combobox>
     64       <InputError error={error} id={`${name}-error`} />
     65     </div>
     66   );
     67 }