# الإكمال التلقائي: القوائم الافتراضية

> Show thousands of options in the slotsmith Autocomplete with the virtual prop, which renders only the options in view.

For long option lists, pass `virtual` to `Autocomplete` with the virtualizer hook as `use` (`useVirtualizer` from `@tanstack/react-virtual`): it renders only the options in view, inside a scroll area. `VirtualAutocomplete` from `slotsmith/virtual` is the same with the hook passed in.

```tsx
import { useState } from "react";
import type { OptionValue } from "slotsmith/autocomplete";
import { VirtualAutocomplete } from "slotsmith/virtual";

const names = ["Ashford", "Brookfield", "Clearwater", "Dunmore", "Easton", "Fairview", "Glenwood", "Harbor City", "Ivydale", "Kingsbridge", "Lakeside", "Millbrook", "Northgate", "Oakridge", "Pinecrest", "Riverton", "Stonebridge", "Thornbury"];

// 5,000 options, built from their index so every render gets the same ones.
const cities = Array.from({ length: 5000 }, (_, index) => ({ id: index + 1, label: `${names[index % names.length]} ${index + 1}` }));

export default function Virtual() {
  const [city, setCity] = useState<OptionValue | null>(null);

  return (
    <div style={{ display: "grid", gap: "1rem", maxWidth: 360 }}>
      <VirtualAutocomplete
        options={cities}
        value={city}
        onChange={setCity}
        // Rows are 34px tall; the list scrolls inside 280px and renders only what is in view.
        virtual={{ estimateSize: 34, maxHeight: 280 }}
        aria-label="City"
      />
      <p>{city === null ? "Nothing selected." : `Selected: city #${city}`}</p>
    </div>
  );
}
```

The picker holds 5,000 cities. Open it and scroll, or type a number: only the options on screen exist in the page.

## Install

`@tanstack/react-virtual` is an optional peer: you pass its hook in, so slotsmith itself never imports it, and a project that never windows a list does not need it.

```sh
pnpm add @tanstack/react-virtual
```

## The virtual option

`virtual` takes the hook as `use` (`VirtualAutocomplete` passes it for you), and three numbers:

- `estimateSize`: the height of one option, in pixels. Defaults to 36. Set it to the height your option rows have.
- `maxHeight`: the height of the scroll area, in pixels. Defaults to 320.
- `overscan`: how many options to render beyond the visible ones, so a fast scroll shows no blank space. Defaults to 8.

Everything else works as in `Autocomplete`: the keyboard, search, single and [multiple](https://slotsmith.dev/ar/components/autocomplete/guides/multiple/) values, [remote options](https://slotsmith.dev/ar/components/autocomplete/guides/remote-options/) with paging, the [states](https://slotsmith.dev/ar/components/autocomplete/guides/states/), the create row and every slot. Options outside the window are stood in for by empty spacer rows, hidden from assistive technology, so the scroll bar matches the whole list. Naming props such as `aria-label` go to the combobox, as in `Autocomplete`.

Paging and windowing solve different problems, how much has been fetched and how much is rendered, and they work together.

## Your own layout

In a [compound layout](https://slotsmith.dev/ar/components/autocomplete/guides/compound-parts/), render `AutocompleteVirtualList` from `slotsmith/virtual` where `Autocomplete.List` would go. It takes the same three options as props.
