Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Created November 7, 2018 17:55
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ryanflorence/669e04f4ee833555a16aae649cb8d2ae to your computer and use it in GitHub Desktop.
Save ryanflorence/669e04f4ee833555a16aae649cb8d2ae to your computer and use it in GitHub Desktop.
import React, { Suspense, useState } from "react";
import { unstable_createResource as createResource } from "react-cache";
import {
Autocomplete as Combobox,
Input as ComboboxInput,
List as ComboboxList,
Option as ComboboxOption
} from "./Combobox";
function App({ tabIndex, navigate }) {
let [searchTerm, setSearchTerm] = useState(null);
function handleSelect(value) {
console.log("SELECTED!", value);
}
return (
<div>
<h1 style={{ textAlign: "center" }}>Combobox</h1>
<p>
<b>Features / Keyboard events</b>
</p>
<ul style={{ lineHeight: 1.5 }}>
<li>Autocompletes first suggestion</li>
<li>ArrowDown/Up navigate the list</li>
<li>
When navigating with arrow keys
<ul>
<li>The input's value changes to the item</li>
<li>
Enter
<ul>
<li>Selects an item (calls onSelect prop)</li>
<li>List closes</li>
<li>Text is selected</li>
</ul>
</li>
<li>
Escape
<ul>
<li>Puts the value back to what it was before</li>
<li>Including autocompleted portion</li>
</ul>
</li>
</ul>
</li>
<li>
Escape while typing (not navigating)
<ul>
<li>Closes the list</li>
<li>Selects the text</li>
</ul>
</li>
</ul>
<Combobox onSelect={handleSelect}>
<ComboboxInput
onChange={async event => {
let value = event.target.value;
await Promise.resolve();
setSearchTerm(value);
}}
/>
<Suspense maxDuration={2000} fallback={<div>Loading...</div>}>
<AsyncList searchTerm={searchTerm} />
</Suspense>
</Combobox>
<div style={{ height: 400 }} />
</div>
);
}
function AsyncList({ searchTerm }) {
let options = SearchResource.read(searchTerm);
return options ? (
<ComboboxList>
{options.map(option => (
<ComboboxOption key={option} value={option}>
{option}
</ComboboxOption>
))}
</ComboboxList>
) : null;
}
let rando = () =>
Math.random()
.toString(16)
.substr(2, 8);
let SearchResource = createResource(value => {
return new Promise(resolve => {
setTimeout(() => {
resolve(
value
? [
`${value}${rando()}`,
`${value}${rando()}`,
`${value}${rando()}`,
`${value}${rando()}`,
`${value}${rando()}`,
`${value}${rando()}`,
`${value}${rando()}`,
`${value}${rando()}`,
`${value}${rando()}`,
`${value}${rando()}`
]
: null
);
}, Math.random() * 1000);
});
});
export default () => (
<Suspense maxDuration={5000} fallback={<div>Loading...</div>}>
<App />
</Suspense>
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment