diff --git a/README.md b/README.md index 5f56d42..7cadc96 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,6 @@ See the **Flush Immediately** example in the live demo. | `as` | `React.ElementType` | `"div"` | Polymorphic root element. | | `maxRows` | `number` | `1` | Visible rows before overflow. | | `maxVisibleItems` | `number` | `100` | Hard cap on visible items. | -| `minVisibleItems` | `number` | `0` | Keep at least N visible. | | `renderOverflow` | `(hidden: T[]) => ReactNode` | default chip | Custom overflow UI. | | `renderOverflowItem` | `(item: T, i: number) => ReactNode` | `renderItem` | For expanded lists/menus. | | `renderOverflowProps` | `Partial>` | — | Props for default overflow. | @@ -138,7 +137,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(...)`. --- @@ -155,7 +154,7 @@ It’s **expected** you’ll wrap `OverflowList` for product needs (design syste ### Edge cases handled - Single wide item exceeding container width -- `minVisibleItems` / `maxVisibleItems` respected +- `maxRows` / `maxVisibleItems` respected - Varying item widths, responsive content - Multi-row overflow detection diff --git a/demo/package.json b/demo/package.json index f4fbd00..84ce5b9 100644 --- a/demo/package.json +++ b/demo/package.json @@ -1,7 +1,7 @@ { "name": "demo", "private": true, - "version": "0.1.0", + "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", diff --git a/demo/src/App.tsx b/demo/src/App.tsx index 31c13a8..285641b 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -1,126 +1,16 @@ -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 { 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 +40,15 @@ 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 - -

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