diff --git a/README.md b/README.md
index 9309fb9..cd3de08 100644
--- a/README.md
+++ b/README.md
@@ -4,28 +4,17 @@

-`react-fit-list` is a small headless React utility for rendering a **single-line list that never wraps**.
-When the available width is too small, the list collapses extra items into an overflow affordance such as `+3`.
-
-It ships with:
-
-- a ready-to-use `` component
-- a headless `useFitList()` hook for custom renderers
-- TypeScript types for component and hook APIs
-
👉 **Live demo:** https://sincerelyfaust.github.io/react-fit-list/
📦 **npm:** https://www.npmjs.com/package/react-fit-list
-## Use cases
+`react-fit-list` is a headless React utility for rendering a single horizontal row of items, keeping what fits visible and collapsing the rest behind an overflow trigger.
-`react-fit-list` works well for interfaces where wrapping would break the layout, such as:
+It ships with:
-- tag and chip rows
-- recipient lists
-- breadcrumbs / metadata rows
-- inline filters
-- compact table or card cells
+- a ready-to-use `` component
+- a headless `useFitList()` hook for custom renderers
+- TypeScript types for component and hook APIs
## Installation
@@ -72,211 +61,92 @@ export function Example() {
}
```
-## How it works
-
-The package measures the container width and item widths, then determines how many items can fit in a single row.
-If not all items fit, the remainder is collapsed into an overflow element.
-
-By default:
-
-- the component keeps items on one row
-- overflow collapses from the end
-- the overflow trigger renders as `+N`
-- item widths are measured from the DOM in `live` mode
-
## Component API
### ``
-```tsx
-import { FitList } from 'react-fit-list'
-```
-
-#### Required props
-
-| Prop | Type | Description |
-| --- | --- | --- |
-| `items` | `readonly T[]` | Items to render. |
-| `getKey` | `(item: T, index: number) => React.Key` | Returns a stable key for each item. |
-| `renderItem` | `(item: T, index: number) => React.ReactNode` | Renders one item. |
-
-#### Optional props
-
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
-| `renderOverflow` | `(args) => React.ReactNode` | renders `+N` | Custom overflow renderer. Receives `{ hiddenCount, hiddenItems, visibleItems, isExpanded, setExpanded, toggle }`. |
-| `className` | `string` | — | Class for the root container. |
-| `listClassName` | `string` | — | Class for the visible-items wrapper. |
-| `itemClassName` | `string` | — | Class for each item wrapper. |
-| `overflowClassName` | `string` | — | Class for the overflow trigger wrapper. |
-| `measureClassName` | `string` | — | Class for hidden measurement nodes. Use when sizing depends on CSS classes. |
-| `emptyFallback` | `React.ReactNode` | `null` | Rendered when `items` is empty. |
-| `gap` | `number` | `8` | Pixel gap between items. |
-| `collapseFrom` | `'end' \| 'start'` | `'end'` | Collapse from the end or start of the list. |
-| `overflowPlacement` | `'end' \| 'closest'` | `'end'` | Keep the overflow pinned to the row end or place it next to the hidden segment. |
-| `reserveOverflowSpace` | `boolean` | `false` | Reserve room for the overflow element even when everything currently fits. |
-| `overflowWidth` | `number` | auto | Fixed overflow width in pixels. Useful when the trigger width is known. |
-| `estimatedItemWidth` | `number \| ((item, index) => number)` | fallback `96` | Used in `estimate` mode or before live measurements are available. |
-| `measurementMode` | `'live' \| 'estimate'` | `'live'` | `live` measures DOM nodes, `estimate` uses `estimatedItemWidth`. |
+| `items` | `readonly T[]` | — | Items to fit into a single row. |
+| `getKey` | `(item, index) => React.Key` | — | Returns a stable React key for each item. |
+| `renderItem` | `(item, index) => React.ReactNode` | — | Renders a single item. |
+| `renderOverflow` | `(args) => React.ReactNode` | `({ hiddenCount }) => +hiddenCount` | Renders the overflow trigger contents. |
+| `className` | `string` | — | Class applied to the root row. |
+| `itemsClassName` | `string` | — | Class applied to the visible-items wrapper. |
+| `itemClassName` | `string` | — | Class applied to each visible item wrapper. |
+| `overflowButtonClassName` | `string` | — | Class applied to the overflow button element. |
+| `measurementClassName` | `string` | `itemClassName` | Class applied to hidden measurement nodes when sizing depends on matching CSS. |
+| `emptyContent` | `React.ReactNode` | `null` | Content rendered when `items` is empty. |
+| `gap` | `number` | `8` | Space between items and the overflow trigger. |
+| `collapseFrom` | `'end' \| 'start'` | `'end'` | Which side of the list gets collapsed first. |
+| `overflowPosition` | `'edge' \| 'inline'` | `'edge'` | Keep the overflow trigger at the row edge or place it next to the hidden side. |
+| `preserveOverflowSpace` | `boolean` | `false` | Reserve room for the overflow trigger even when everything fits. |
+| `overflowWidth` | `number` | auto | Fixed overflow width in pixels. Useful when the trigger size is known. |
+| `itemWidthEstimate` | `number \| ((item, index) => number)` | fallback `96` | Width estimate used in `estimate` mode or before live measurements are available. |
+| `measurement` | `'live' \| 'estimate'` | `'live'` | Width calculation strategy. |
| `expanded` | `boolean` | uncontrolled | Controlled expanded state. |
| `defaultExpanded` | `boolean` | `false` | Initial expanded state for uncontrolled usage. |
| `onExpandedChange` | `(expanded: boolean) => void` | — | Called when expanded state changes. |
-| `as` | `keyof React.JSX.IntrinsicElements` | `'div'` | Root element tag name. |
-| `overflowAs` | `keyof React.JSX.IntrinsicElements` | `'button'` | Overflow element tag name. |
+| `onOverflowClick` | `(args, event) => void` | — | Called when the overflow button is clicked. |
+
+### Overflow render args
+
+`renderOverflow` and `onOverflowClick` receive the same overflow state object:
+
+```ts
+{
+ hiddenCount: number
+ hiddenItems: T[]
+ visibleItems: T[]
+ isExpanded: boolean
+ setExpanded: (expanded: boolean) => void
+ toggle: () => void
+}
+```
## Hook API
### `useFitList()`
-Use the hook when you want to own the markup but reuse the fitting logic.
-
```tsx
import { useFitList } from 'react-fit-list'
-```
-#### Hook options
+const fit = useFitList({
+ items,
+ getKey: (item) => item.id,
+ gap: 8,
+})
+```
-The hook accepts the same fitting-related options used by the component:
+#### Options
-- `items`
-- `getKey`
-- `reserveOverflowSpace`
-- `overflowWidth`
-- `gap`
-- `collapseFrom`
-- `estimatedItemWidth`
-- `measurementMode`
-- `expanded`
-- `defaultExpanded`
-- `onExpandedChange`
-- `measureOverflowWidth`
+| Option | Type | Default | Description |
+| --- | --- | --- | --- |
+| `items` | `readonly T[]` | — | Items to measure. |
+| `getKey` | `(item, index) => React.Key` | — | Returns a stable React key for each item. |
+| `gap` | `number` | `8` | Space between items and overflow. |
+| `collapseFrom` | `'end' \| 'start'` | `'end'` | Which side collapses first. |
+| `preserveOverflowSpace` | `boolean` | `false` | Reserve space for overflow even when all items fit. |
+| `overflowWidth` | `number` | auto | Fixed overflow width in pixels. |
+| `itemWidthEstimate` | `number \| ((item, index) => number)` | fallback `96` | Width estimate for `estimate` mode. |
+| `measurement` | `'live' \| 'estimate'` | `'live'` | Width calculation strategy. |
+| `expanded` | `boolean` | uncontrolled | Controlled expanded state. |
+| `defaultExpanded` | `boolean` | `false` | Initial expanded state. |
+| `onExpandedChange` | `(expanded: boolean) => void` | — | Called whenever expanded state changes. |
+| `measureOverflowWidth` | `(hiddenCount: number) => number` | — | Custom overflow width measurement callback. |
#### Return value
| Field | Type | Description |
| --- | --- | --- |
-| `containerRef` | `RefObject` | Attach to the outer container whose width should be measured. |
-| `registerItem(key)` | `(node) => void` | Attach to each visible item wrapper. |
-| `registerMeasureItem(key)` | `(node) => void` | Attach to hidden measurement nodes for accurate width calculation. |
-| `registerOverflow(node)` | `(node) => void` | Attach to the overflow element. |
-| `visibleItems` | `T[]` | Items currently visible. |
-| `hiddenItems` | `T[]` | Items currently hidden. |
-| `hiddenCount` | `number` | Count of hidden items. |
+| `containerRef` | `RefObject` | Attach to the outer container. |
+| `registerItem` | `(key) => (node) => void` | Registers visible item nodes for measurement. |
+| `registerMeasureItem` | `(key) => (node) => void` | Registers hidden measurement nodes. |
+| `registerOverflow` | `(node) => void` | Registers the overflow node. |
+| `visibleItems` | `T[]` | Items currently visible in the collapsed row. |
+| `hiddenItems` | `T[]` | Items currently hidden behind overflow. |
+| `hiddenCount` | `number` | Number of hidden items. |
| `isExpanded` | `boolean` | Whether the list is expanded. |
-| `setExpanded` | `(expanded: boolean) => void` | Manually set expanded state. |
-| `toggleExpanded` | `() => void` | Toggle expanded state. |
-| `recompute` | `() => void` | Force a recalculation. |
-
-## Examples
-
-### Custom overflow label
-
-```tsx
- item.id}
- renderItem={(item) => {item.label}}
- renderOverflow={({ hiddenCount }) => (
-
- )}
-/>
-```
-
-### Collapse from the start
-
-Useful when the most recent or most important items are at the end.
-
-```tsx
- item.id}
- renderItem={(item) => {item.label}}
- collapseFrom="start"
-/>
-```
-
-### Overflow placement
-
-By default, the overflow affordance stays pinned to the far end of the row.
-Set `overflowPlacement="closest"` to make it hug the hidden segment instead.
-This is especially useful with `collapseFrom="start"`.
-
-```tsx
- item.id}
- renderItem={(item) => {item.label}}
- collapseFrom="start"
- overflowPlacement="closest"
-/>
-```
-
-### Estimate mode
-
-Estimate mode avoids relying on live measurement for every item and can be useful when item widths are predictable.
-
-```tsx
- item.id}
- renderItem={(item) => {item.label}}
- measurementMode="estimate"
- estimatedItemWidth={(item) => Math.max(72, item.label.length * 8)}
-/>
-```
-
-### Controlled expanded state
-
-`FitList` does not impose any default click behavior for the overflow trigger. Use `renderOverflow` to define interactions such as opening a popover, modal, or expanding the list.
-
-Use `expanded` / `onExpandedChange` only when you intentionally want to control expansion behavior.
-
-```tsx
-function ControlledExample() {
- const [expanded, setExpanded] = useState(false)
-
- return (
- item.id}
- renderItem={(item) => {item.label}}
- expanded={expanded}
- onExpandedChange={setExpanded}
- />
- )
-}
-```
-
-## Styling guidance
-
-The package is intentionally headless. You control the appearance of the item contents.
-
-For best results:
-
-- keep each rendered item visually compact
-- ensure item content does not wrap internally (`white-space: nowrap` is usually correct)
-- use `measureClassName` when your measurement nodes need the same CSS as your visible nodes
-- provide `overflowWidth` when you know the trigger width and want more predictable calculations
-
-## Accessibility notes
-
-- By default the overflow trigger renders as a `