OverflowingList measures its available width, keeps fitting items in a compact row, and offers a +N button that opens the complete list in a popup. The count updates when the container, item content or ordered list changes. Empty lists and lists that fit have no overflow button or exposed popup.
Supply the complete ordered list as keyed elements. Your application owns each item’s content, actions and data. The compact row remains visible when the popup opens. The popup repeats the complete list, including the items that fit in the row.
Usage
Count visibility
The default mode keeps the current count visibility while an inline item is focused, so showing the count does not push that item out of the row. Focusing the count button makes the count visible.
Use
false when the surrounding interface provides another way to access the hidden items. Changing it to false hides the count without dismissing an already-open popup. open and defaultOpen can still expose the complete list when items overflow. Removing the overflow items or widening the list until everything fits closes the popup and removes the count button. The count always describes the items outside the compact row.
maxInlineCount caps the number of visible row items. Available width can reduce that number further. The popup still contains the complete list. It does not fetch missing items or virtualize the popup.
Popup state
The list owns its popup state whenopen is omitted. Use defaultOpen for its initial state. The default is false; an initially open popup still requires overflowing items.
Pass open and update it in onOpenChange to own the popup state. The callback receives the requested boolean and the installed Popover event details, including reason, event, trigger, cancel() and preventUnmountOnClose(). Calling cancel() prevents the requested state change. In controlled use, update your state only for changes you accept.
Pass actionsRef to receive the Popover close() and unmount() methods. close() requests closure through onOpenChange and respects cancellation. If your callback calls preventUnmountOnClose() to run a caller-owned exit, call actionsRef.current?.unmount() when that exit finishes. This releases the retained popup without removing the list and allows it to open again.
Native targets and composition
Nativediv attributes, handlers, styles, class names and refs on OverflowingList target the compact row root. Use triggerProps for the count button and popupProps for the popup content div. Both retain their Popover part’s native props, handlers, ref and element/function render composition.
Customize the trigger with triggerProps.render, as in the controlled example, or supply triggerProps.children to replace +N. Custom components must forward the supplied props and ref. Custom popup components must also render the supplied children; OverflowingList owns the item content. overflowLabel defaults to “Show all items”. The default button’s accessible name combines its count and that label, for example “+3 Show all teams”. Override triggerProps['aria-label'] or popupProps['aria-label'] when their content needs a different name.
OverflowingList stops click, mousedown, pointerdown, keydown and keyup propagation on the trigger and popup by default. This keeps opening the popup and interacting with its items from activating a surrounding field or picker. A handler supplied through triggerProps or popupProps replaces the default for that event. Call event.stopPropagation() in your handler to retain blocking, or omit it to allow that event to bubble. Other events keep their defaults. Handlers on a custom render element compose with the supplied props as usual.
When a popup click override allows bubbling, the installed Base UI portal can dispatch that click to a surrounding React ancestor twice with the same native event. This also occurs with a plain Popover. OverflowingList preserves that upstream behavior; it does not guarantee one ancestor callback per native popup event when bubbling is enabled.
Keyboard and focus
Enter, Space and pointer activation open a non-modal popup. Escape and outside interaction dismiss it. Ordinary dismissal restores focus to the count button. Focus already on a visible inline item or an outside control is preserved. The popup supports content, links and buttons with their native keyboard behavior; it does not turn them into menu items or add menu arrow navigation. UsepopupProps.initialFocus and popupProps.finalFocus to customize opening and dismissal focus through the installed Popover contract.
Each list owns its responsive measurements independently. Unmounting one list releases its observers and leaves other lists working.
Server rendering and hydration
Server markup includes the firstmaxInlineCount items, or all items when the cap is omitted. Width measurement and popup content become available after client mounting.
Hydration reuses the provisional row and applies responsive measurement after client mounting. Row and popup children are separate rendered instances. Keep state shared between those locations in the caller.
Migration
The popup continues to show the complete list and uses “Show all items” by default.showOverflowCount={false} preserves the clipped row and hides the count. It does not dismiss an already-open popup. The trigger and popup retain their default blocking for click, mousedown, pointerdown, keydown and keyup. Override an individual handler through triggerProps or popupProps when the surrounding interface should receive that event.
Props
RefObject<PopoverRootActions | null>
Ref exposing the Popover close() and unmount() methods. After preventUnmountOnClose(), call unmount() when the caller-owned exit finishes.
ReactElement<unknown, string | JSXElementConstructor<any>>[]
required
Complete ordered list of elements, each with a stable key. The popup contains the complete list, including items visible in the compact row.
boolean
default:"false"
Initial popup visibility when uncontrolled. Defaults to false.
number
Maximum number of items visible in the compact row. Available width can reduce this count further. The popup still contains the complete list.
((open: boolean, eventDetails: PopoverRootChangeEventDetails) => void)
Receives the requested open state and unchanged Base UI event details, including reason, event, trigger, cancel() and preventUnmountOnClose().
boolean
Controlled popup visibility. A popup can appear only when items overflow.
string
default:"Show all items"
Accessible label for the popup. The default overflow button is named by its visible count followed by this label. Defaults to Show all items.
Omit<PopoverPopupProps, "children">
Popover.Popup native props, handlers, ref, render composition and focus options for the overflow content. Click, mousedown, pointerdown, keydown and keyup stop propagation by default. Each supplied event handler replaces its default.
Ref<HTMLDivElement>
Ref forwarded to the compact row root div.
boolean
Shows the count on hover, keyboard focus or while open by default. Use true to keep it visible whenever items overflow, or false to hide the count and clip the row. An already-open popup stays open until dismissed. Empty lists and lists that fit have no trigger.
Omit<
ComponentPropsWithRef<typeof Popover.Trigger>,
'handle' | 'payload' | 'ref'
> & { ref?: Ref<HTMLElement> }
Popover.Trigger native props, handlers, ref, children and render composition for the count button. Click, mousedown, pointerdown, keydown and keyup stop propagation by default. Each supplied event handler replaces its default. Custom components must forward supplied props and ref.