From d59ee5fd25007e18522e24f6f9e9adab45d9d28b Mon Sep 17 00:00:00 2001 From: eliav Date: Thu, 18 Sep 2025 01:07:40 +0300 Subject: [PATCH 1/4] better structure demos. bug fix when items.length==1 --- README.md | 2 +- demo/src/App.tsx | 315 +----------------- .../RadixVirtualizedOverflowList.tsx | 15 +- demo/src/examples/AdvancedOverflowList.tsx | 278 ---------------- demo/src/examples/BasicExample.tsx | 38 +++ demo/src/examples/ChildrenPatternExample.tsx | 31 ++ .../src/examples/CustomHostElementExample.tsx | 40 +++ demo/src/examples/FlushImmediatelyExample.tsx | 72 ++++ demo/src/examples/MaxRowsOverflowExample.tsx | 38 +++ demo/src/examples/MinVisibleItemsExample.tsx | 38 +++ demo/src/examples/MultiRowExample.tsx | 50 +++ demo/src/examples/OneItemWiderExample.tsx | 50 +++ .../examples/RadixVirtualizationExample.tsx | 95 ++++++ .../examples/VirtualizedRadixOverflowMenu.tsx | 1 + src/components/OverflowList.tsx | 8 +- 15 files changed, 487 insertions(+), 584 deletions(-) rename demo/src/{examples => components}/RadixVirtualizedOverflowList.tsx (96%) delete mode 100644 demo/src/examples/AdvancedOverflowList.tsx create mode 100644 demo/src/examples/BasicExample.tsx create mode 100644 demo/src/examples/ChildrenPatternExample.tsx create mode 100644 demo/src/examples/CustomHostElementExample.tsx create mode 100644 demo/src/examples/FlushImmediatelyExample.tsx create mode 100644 demo/src/examples/MaxRowsOverflowExample.tsx create mode 100644 demo/src/examples/MinVisibleItemsExample.tsx create mode 100644 demo/src/examples/MultiRowExample.tsx create mode 100644 demo/src/examples/OneItemWiderExample.tsx create mode 100644 demo/src/examples/RadixVirtualizationExample.tsx diff --git a/README.md b/README.md index 5f56d42..6bf9839 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ It’s **expected** you’ll wrap `OverflowList` for product needs (design syste - **Radix UI + Virtualization wrapper** (search, large datasets, a11y, perf): - **Demo:** see [Radix UI + Virtualization](https://eliav2.github.io/react-responsive-overflow-list/#radix-ui-virtualization-example) in the live site - - [**Source**](demo/src/examples/RadixVirtualizedOverflowList.tsx) + - [**Source**](demo/src/components/RadixVirtualizedOverflowList.tsx) - Uses `@tanstack/react-virtual` and the helper `createLimitedRangeExtractor(...)`. --- diff --git a/demo/src/App.tsx b/demo/src/App.tsx index 31c13a8..b21ba50 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -1,126 +1,17 @@ -import { useState } from "react"; -import { OverflowList } from "react-responsive-overflow-list"; -import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; -import { tomorrow } from "react-syntax-highlighter/dist/esm/styles/prism"; -import { Theme, Switch } from "@radix-ui/themes"; +import { Theme } from "@radix-ui/themes"; import { CustomOverflowExample } from "./examples/CustomOverflowExample"; -import { RadixVirtualizedOverflowList } from "./examples/RadixVirtualizedOverflowList"; +import { BasicExample } from "./examples/BasicExample"; +import { ChildrenPatternExample } from "./examples/ChildrenPatternExample"; +import { MultiRowExample } from "./examples/MultiRowExample"; +import { CustomHostElementExample } from "./examples/CustomHostElementExample"; +import { RadixVirtualizationExample } from "./examples/RadixVirtualizationExample"; +import { FlushImmediatelyExample } from "./examples/FlushImmediatelyExample"; +import { OneItemWiderExample } from "./examples/OneItemWiderExample"; +import { MinVisibleItemsExample } from "./examples/MinVisibleItemsExample"; +import { MaxRowsOverflowExample } from "./examples/MaxRowsOverflowExample"; import { Github } from "lucide-react"; import "./App.css"; -const fruits = ["Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig", "Grape", "Honeydew", "Kiwi", "Lemon"]; - -const tags = ["React", "TypeScript", "CSS", "HTML", "JavaScript", "Node.js", "Express", "MongoDB", "Vite", "ESLint"]; - -const menuItems = ["Home", "About", "Services", "Portfolio", "Blog", "Contact", "Careers", "Support"]; - -function MultiRowExample() { - const [maxRows, setMaxRows] = useState(2); - - return ( -
-

Multi-row Example

-

Allow up to {maxRows} rows before overflow

-
- - {` {item}} - maxRows={${maxRows}} - style={{ gap: "4px" }} -/>`} - -
-
- - setMaxRows(parseInt(e.target.value) || 1)} - className="max-rows-input" - /> -
- -
- {item}} - maxRows={maxRows} - style={{ gap: "4px" }} - /> -
-
- ); -} - -function FlushImmediatelyExample() { - const [flushImmediately, setFlushImmediately] = useState(false); - - return ( -
-

Flush Immediately Example

-

- Control how updates are applied when the container resizes. - flushImmediately={flushImmediately ? "true" : "false"} - (default: true) -

-
- - {` {item}} - flushImmediately={${flushImmediately}} - style={{ gap: "4px" }} -/>`} - -
-
-
- - - - {flushImmediately ? "Enabled (No flickering)" : "Disabled (better performance)"} - -
-
- -
-

Trade-offs:

-
    -
  • - flushImmediately=true: Updates are applied immediately using flushSync, avoiding flickering - but may impact performance -
  • -
  • - flushImmediately=false: Updates are applied in the requestAnimationFrame callback, avoiding - forced reflow and improving performance but may cause slight flickering -
  • -
  • - Default behavior: flushImmediately is true by default to prioritize smooth visual - experience -
  • -
- -
- Resize quickly below to observe the difference! -
-
- -
- {item}} - flushImmediately={flushImmediately} - style={{ gap: "4px" }} - /> -
-
- ); -} - function App() { return ( @@ -150,188 +41,16 @@ function App() {
-
-

Basic Example

-

Simple list with default overflow element

-
- - {` ( - - {item} - - )} - style={{ gap: "8px" }} -/>`} - -
-
- ( - - {item} - - )} - style={{ gap: "8px" }} - /> -
-
- -
-

Children Pattern

-

Using children instead of items array

-
- - {` - - - ... -`} - -
-
- - - - - - - - -
-
- + + - - -
-

Custom Host Element

-

Using the 'as' prop to render as different HTML elements

-
- - {` - Home - About - Contact -`} - -
- -
- -
-

Radix UI + Virtualization Example

-

- This is an EXAMPLE implementation showing how to wrap OverflowList with Radix UI dropdown and - virtualization. In real-world applications, it's expected that you'll wrap OverflowList with your own - components tailored to your specific needs, design system, and UI framework. -

-
- - {`import { RadixVirtualizedOverflowList } from "./examples/RadixVirtualizedOverflowList"; - -// Small dataset - uses simple dropdown - #{tag}} - style={{ gap: "6px" }} -/> - -// Large dataset - automatically uses virtualization - \`Item \${i + 1}\`)} - renderItem={(item) => #{item}} - virtualizationThreshold={50} - enableSearch={true} - style={{ gap: "6px" }} -/>`} - -
- -
-

Small Dataset (Simple Dropdown)

- #{tag}} - style={{ gap: "6px" }} - /> -
- -
-

- Large Dataset (Virtualized Dropdown with Search) -

- `Item ${i + 1}`)} - renderItem={(item) => #{item}} - virtualizationThreshold={50} - enableSearch={true} - searchPlaceholder="Search items..." - style={{ gap: "6px" }} - /> -
- -
- This example demonstrates: -
    -
  • - Automatic virtualization: Switches to virtualized dropdown when item count exceeds - threshold -
  • -
  • - Search functionality: Built-in search/filter for large datasets -
  • -
  • - Radix UI integration: Full accessibility and keyboard navigation support -
  • -
  • - Customizable: Configurable thresholds, styling, and behavior -
  • -
  • - Performance optimized: Efficient rendering for thousands of items -
  • -
-

- Note: This is just an example implementation. In real-world applications, it's expected - that you'll wrap OverflowList with your own components tailored to your specific needs and design - system. -
- Source:{" "} - - View implementation on GitHub - -

-
-
- + + - - {/*
*/} + + +