npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-priority-overflow-row

v1.1.0

Published

A measured React row layout primitive that coordinates responsive child variants by priority before wrapping groups.

Readme

react-priority-overflow-row

A measured React layout primitive for rows where siblings have their own responsive representations and must coordinate before wrapping.

It is useful for headers, toolbars, filter bars, and dense application UI where each child can become smaller in a different way:

  • breadcrumbs can switch from full text to compact text;
  • filters can switch from full labels to short labels to icon-only;
  • action buttons can switch from button to icon button;
  • one group can move to its own line after lower-cost compaction is exhausted.

Workspace header priority overflow demo

Install

npm install react-priority-overflow-row

Install peer dependencies if your app does not already provide them:

npm install react react-dom

Quick Start

import { PriorityOverflowRow } from 'react-priority-overflow-row';

export function Header() {
  return (
    <PriorityOverflowRow gap={12}>
      <PriorityOverflowRow.Group>
        <PriorityOverflowRow.Variant
          modes={[
            { value: 'full' },
            { value: 'compact', priority: 10 },
          ] as const}
        >
          {(mode) => <Breadcrumbs mode={mode} />}
        </PriorityOverflowRow.Variant>
        <ItemBadge />
      </PriorityOverflowRow.Group>

      <PriorityOverflowRow.Group align="end" wrapPriority={100}>
        <PriorityOverflowRow.Variant
          modes={[
            { value: 'full' },
            { value: 'short', priority: 20 },
            { value: 'icon', priority: 80 },
          ] as const}
        >
          {(mode) => <FilterChips mode={mode} />}
        </PriorityOverflowRow.Variant>

        <PriorityOverflowRow.Variant
          modes={[
            { value: 'full' },
            { value: 'icon', priority: 40 },
          ] as const}
        >
          {(mode) => <HeaderActions mode={mode} />}
        </PriorityOverflowRow.Variant>
      </PriorityOverflowRow.Group>
    </PriorityOverflowRow>
  );
}

Mental Model

PriorityOverflowRow makes the parent own the negotiation. You describe the real row structure, and each responsive child declares its own modes.

The row then:

  1. Measures every group in every possible local mode state.
  2. Starts with every variant in its first mode.
  3. If the line does not fit, applies the lowest-priority available compaction.
  4. Wraps a group only when wrapping is cheaper than any remaining compaction.
  5. Re-solves each wrapped line independently.

Lower priority numbers compact earlier. Mode order is still meaningful: list modes from most expansive to most compact.

API

PriorityOverflowRow

| Prop | Type | Description | | --- | --- | --- | | gap | number \| string | Gap between groups and wrapped lines. Numbers are CSS pixels. | | layout | 'ordered' \| 'packed' | Layout strategy. Defaults to ordered; use packed for dense multi-line rows that should fill wrapped lines with later groups. | | children | ReactNode | Use PriorityOverflowRow.Group children. | | className | string | Optional root class name. | | style | CSSProperties | Optional root inline style. |

PriorityOverflowRow.Group

| Prop | Type | Description | | --- | --- | --- | | align | 'start' \| 'end' | end pins the group to the end of its current line. | | gap | number \| string | Gap between children inside the group. Defaults to the row gap. | | wrapPriority | number \| false | Cost to move the group to its own line. In ordered layout, omit to prevent independent wrapping. In packed layout, omit for default priority 100; use false to prevent wrapping. | | children | ReactNode | Fixed children and Variant children. |

PriorityOverflowRow.Variant

| Prop | Type | Description | | --- | --- | --- | | modes | non-empty mode array | Modes ordered from most expansive to most compact. | | children | (mode) => ReactNode | Render prop that receives the selected mode. |

Each mode is:

type PriorityOverflowMode<Mode extends string> = {
  value: Mode;
  priority?: number;
};

The first mode should not need a priority because it is the starting state. Later modes use priority as the cost to enter that smaller representation.

Tutorial

1. Split the row into meaningful groups

Groups should match visual units that should stay together.

<PriorityOverflowRow.Group>
  <Breadcrumbs />
  <ItemBadge />
</PriorityOverflowRow.Group>

<PriorityOverflowRow.Group align="end" wrapPriority={100}>
  <Avatars />
  <FilterChips />
  <Actions />
</PriorityOverflowRow.Group>

2. Wrap only the children that can change representation

Raw children are measured as fixed content. Use Variant only when a child has multiple representations.

<PriorityOverflowRow.Variant
  modes={[
    { value: 'full' },
    { value: 'short', priority: 20 },
    { value: 'icon', priority: 80 },
  ] as const}
>
  {(mode) => <FilterChips mode={mode} />}
</PriorityOverflowRow.Variant>

3. Tune priorities by product intent

The numbers do not need to be contiguous. Leave room between them.

// Breadcrumbs compact before filters lose labels.
{ value: 'compact', priority: 10 }

// Filters shorten before action buttons become icons.
{ value: 'short', priority: 20 }

// Actions become icons before filters become icon-only.
{ value: 'icon', priority: 40 }

4. Let wrapping re-expand the new line

Set wrapPriority on the group that may move to its own line. After wrapping, that line starts from expansive modes again and compacts only if its own line is too narrow.

Use layout="packed" for dense multi-line toolbars where later groups should fill partially empty wrapped lines:

<PriorityOverflowRow layout="packed" gap={12}>
  <PriorityOverflowRow.Group>
    <DateField />
  </PriorityOverflowRow.Group>
  <PriorityOverflowRow.Group>
    <DrawingStatus />
  </PriorityOverflowRow.Group>
  <PriorityOverflowRow.Group align="end">
    <PriorityOverflowRow.Variant
      modes={[
        { value: 'full' },
        { value: 'short', priority: 20 },
        { value: 'icon', priority: 80 },
      ] as const}
    >
      {(mode) => <FormButtons mode={mode} />}
    </PriorityOverflowRow.Variant>
  </PriorityOverflowRow.Group>
</PriorityOverflowRow>

Toolbar priority overflow demo

Running This Repository

npm install
npm run dev
npm test
npm run typecheck
npm run build

Regenerate README GIFs:

npm run docs:gifs

Examples

The Vite demo lives in examples/basic.

npm run dev

Open the printed local URL and resize the demo frames.

More examples are documented in docs/examples.md.

Notes

  • This library does not move items into an overflow menu.
  • It does not invent aggregate mode names like compact-actions or wrapped.
  • It measures real rendered DOM widths, so translations, fonts, and content length are part of the decision.
  • If the final compact modes still cannot fit, the line is allowed to overflow normally. The library does not hide content to fake a fit.