Skip to content

Commit

Permalink
Feat/virtualization for autocomplete (#4094)
Browse files Browse the repository at this point in the history
* feat: add react-window virtualization for autocomplete

* fix: wrong imports and wrong sizing

* fix: update pnpm lock

* chore: add test cases for large dataset (1000 and 10000 items)

* chore: move virtualized-listbox to listbox components folder, implement isVirtualized conditional

* feat: implement dynamic listboxheight n item height, add story

* chore: rename props, remove unnecessary line changes

* fix: maxHeight style 256px for default, conditional usage of virtualizer

* feat: migrate to tan-stack virtual. (todo: fix scroll shadow)

* feat: virtualization support

---------

Co-authored-by: Vincentius Roger Kuswara <[email protected]>
  • Loading branch information
jrgarciadev and vinroger authored Nov 16, 2024
1 parent f81ad5e commit b9d5d49
Show file tree
Hide file tree
Showing 16 changed files with 717 additions and 98 deletions.
7 changes: 7 additions & 0 deletions .changeset/proud-chicken-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@nextui-org/autocomplete": patch
"@nextui-org/listbox": patch
"@nextui-org/theme": patch
---

Virtualization support added to Listbox & Autocomplete
2 changes: 1 addition & 1 deletion apps/docs/components/docs/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ function TreeItem<T>(props: TreeItemProps<T>) {
</span>
{isUpdated && (
<Chip
className="ml-1 py-1 text-tiny text-default-400 bg-default-100/50"
className="ml-1 py-1 text-tiny text-default-500 dark:text-default-400 bg-default-100 dark:bg-default-100/50"
color="default"
size="sm"
variant="flat"
Expand Down
40 changes: 15 additions & 25 deletions apps/docs/config/routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@
"key": "autocomplete",
"title": "Autocomplete",
"keywords": "autocomplete, auto suggest, search, typeahead",
"path": "/docs/components/autocomplete.mdx"
"path": "/docs/components/autocomplete.mdx",
"updated": true
},
{
"key": "alert",
Expand All @@ -162,8 +163,7 @@
"key": "badge",
"title": "Badge",
"keywords": "badge, markers, status indication, count display",
"path": "/docs/components/badge.mdx",
"updated": true
"path": "/docs/components/badge.mdx"
},
{
"key": "breadcrumbs",
Expand All @@ -175,14 +175,14 @@
"key": "button",
"title": "Button",
"keywords": "button, interactive, action trigger, click events",
"path": "/docs/components/button.mdx"
"path": "/docs/components/button.mdx",
"updated": true
},
{
"key": "calendar",
"title": "Calendar",
"keywords": "calendar, date picker, month picker, year picker",
"path": "/docs/components/calendar.mdx",
"newPost": true
"path": "/docs/components/calendar.mdx"
},
{
"key": "card",
Expand All @@ -194,8 +194,7 @@
"key": "checkbox",
"title": "Checkbox",
"keywords": "checkbox, binary choice, selection control, toggle",
"path": "/docs/components/checkbox.mdx",
"updated": true
"path": "/docs/components/checkbox.mdx"
},
{
"key": "checkbox-group",
Expand Down Expand Up @@ -225,22 +224,18 @@
"key": "date-input",
"title": "Date Input",
"keywords": "date-input, time, input, timezone",
"path": "/docs/components/date-input.mdx",
"newPost": true
},
"path": "/docs/components/date-input.mdx" },
{
"key": "date-picker",
"title": "Date Picker",
"keywords": "date-picker, time, input, timezone",
"path": "/docs/components/date-picker.mdx",
"newPost": true
"path": "/docs/components/date-picker.mdx"
},
{
"key": "date-range-picker",
"title": "Date Range Picker",
"keywords": "date-range-picker, date-picker, time, input, timezone",
"path": "/docs/components/date-range-picker.mdx",
"newPost": true
"path": "/docs/components/date-range-picker.mdx"
},
{
"key": "divider",
Expand Down Expand Up @@ -332,8 +327,7 @@
"key": "range-calendar",
"title": "Range Calendar",
"keywords": "range calendar, date picker, month picker, year picker",
"path": "/docs/components/range-calendar.mdx",
"newPost": true
"path": "/docs/components/range-calendar.mdx"
},
{
"key": "scroll-shadow",
Expand All @@ -351,8 +345,7 @@
"key": "skeleton",
"title": "Skeleton",
"keywords": "skeleton, loading state, placeholder, content preview",
"path": "/docs/components/skeleton.mdx",
"updated": true
"path": "/docs/components/skeleton.mdx"
},
{
"key": "slider",
Expand Down Expand Up @@ -394,8 +387,7 @@
"key": "tabs",
"title": "Tabs",
"keywords": "tabs, section navigation, categorized content, tabbed interface",
"path": "/docs/components/tabs.mdx",
"updated": true
"path": "/docs/components/tabs.mdx"
},
{
"key": "textarea",
Expand All @@ -407,15 +399,13 @@
"key": "time-input",
"title": "Time Input",
"keywords": "timeinput, time, input, timezone",
"path": "/docs/components/time-input.mdx",
"newPost": true
"path": "/docs/components/time-input.mdx"
},
{
"key": "tooltip",
"title": "Tooltip",
"keywords": "tooltip, hint, descriptive message, hover info",
"path": "/docs/components/tooltip.mdx",
"updated": true
"path": "/docs/components/tooltip.mdx"
},
{
"key": "user",
Expand Down
8 changes: 8 additions & 0 deletions apps/docs/content/components/autocomplete/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ import customSectionsStyle from "./custom-sections-style";
import customStyles from "./custom-styles";
import customEmptyContentMessage from "./custom-empty-content-message";
import readOnly from "./read-only";
import virtualization from "./virtualization";
import virtualizationTenThousand from "./virtualization-ten-thousand";
import virtualizationMaxListboxHeight from "./virtualization-max-listbox-height";
import virtualizationCustomItemHeight from "./virtualization-custom-item-height";

export const autocompleteContent = {
usage,
Expand Down Expand Up @@ -56,4 +60,8 @@ export const autocompleteContent = {
customStyles,
customEmptyContentMessage,
readOnly,
virtualization,
virtualizationTenThousand,
virtualizationMaxListboxHeight,
virtualizationCustomItemHeight,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const App = `import {Autocomplete, AutocompleteItem} from "@nextui-org/react";
const generateItems = (n) => {
const items = [
"Cat",
"Dog",
"Elephant",
"Lion",
"Tiger",
"Giraffe",
"Dolphin",
"Penguin",
"Zebra",
"Shark",
"Whale",
"Otter",
"Crocodile",
];
const dataset = [];
for (let i = 0; i < n; i++) {
const item = items[i % items.length];
dataset.push({
label: \`\${item}\${i}\`,
value: \`\${item.toLowerCase()}\${i}\`,
description: "Sample description",
});
}
return dataset;
};
export default function App() {
const items = generateItems(1000);
return (
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
<Autocomplete
isVirtualized
label="Search from 1000 items"
className="max-w-xs"
defaultItems={items}
placeholder="Search..."
maxListboxHeight={400}
itemHeight={40}
>
{(item) => (
<AutocompleteItem key={item.value}>
{item.label}
</AutocompleteItem>
)}
</Autocomplete>
</div>
);
}`;

const react = {
"/App.jsx": App,
};

export default {
...react,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const App = `import {Autocomplete, AutocompleteItem} from "@nextui-org/react";
const generateItems = (n) => {
const items = [
"Cat",
"Dog",
"Elephant",
"Lion",
"Tiger",
"Giraffe",
"Dolphin",
"Penguin",
"Zebra",
"Shark",
"Whale",
"Otter",
"Crocodile",
];
const dataset = [];
for (let i = 0; i < n; i++) {
const item = items[i % items.length];
dataset.push({
label: \`\${item}\${i}\`,
value: \`\${item.toLowerCase()}\${i}\`,
description: "Sample description",
});
}
return dataset;
};
export default function App() {
const items = generateItems(1000);
return (
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
<Autocomplete
isVirtualized
label="Search from 1000 items"
className="max-w-xs"
defaultItems={items}
placeholder="Search..."
maxListboxHeight={400}
>
{(item) => (
<AutocompleteItem key={item.value}>
{item.label}
</AutocompleteItem>
)}
</Autocomplete>
</div>
);
}`;

const react = {
"/App.jsx": App,
};

export default {
...react,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const App = `import {Autocomplete, AutocompleteItem} from "@nextui-org/react";
const generateItems = (n) => {
const items = [
"Cat",
"Dog",
"Elephant",
"Lion",
"Tiger",
"Giraffe",
"Dolphin",
"Penguin",
"Zebra",
"Shark",
"Whale",
"Otter",
"Crocodile",
];
const dataset = [];
for (let i = 0; i < n; i++) {
const item = items[i % items.length];
dataset.push({
label: \`\${item}\${i}\`,
value: \`\${item.toLowerCase()}\${i}\`,
description: "Sample description",
});
}
return dataset;
};
export default function App() {
const items = generateItems(10000);
return (
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
<Autocomplete
isVirtualized
label="Search from 1000 items"
className="max-w-xs"
defaultItems={items}
placeholder="Search..."
>
{(item) => (
<AutocompleteItem key={item.value}>
{item.label}
</AutocompleteItem>
)}
</Autocomplete>
</div>
);
}`;

const react = {
"/App.jsx": App,
};

export default {
...react,
};
Loading

0 comments on commit b9d5d49

Please sign in to comment.