Skip to content

feat: number input page for performance#22128

Open
devadula-nandan wants to merge 7 commits intocarbon-design-system:mainfrom
devadula-nandan:pagination-number-input-feature
Open

feat: number input page for performance#22128
devadula-nandan wants to merge 7 commits intocarbon-design-system:mainfrom
devadula-nandan:pagination-number-input-feature

Conversation

@devadula-nandan
Copy link
Copy Markdown
Contributor

@devadula-nandan devadula-nandan commented Apr 27, 2026

Closes #5546
Closes #6884
Closes #16895

Closes/Contributes to

#6836
#5129
#6146
#21661
#4365
#21053

Renders a number input instead of a select when there are more than 30 pages to navigate, which significantly improves performance and holds up under extreme stress tests.

More Notes

Having two different UIs may raise concerns about design inconsistency. For example, imagine a dataset with 300 items, resulting in 30 pages (with a page size of 10). If a new item is added, the component flips from a select to a number input—and vice versa if the 301st item is removed.

Now consider two pages, each rendering data tables. The first has 12 items in total, while the second has 12,345,678 items. Page 1 will render a select, whereas page 2 will render a number input.

If we consider this an inconsistency, the performance benefits outweigh the design concerns. Our goal is to build usable components—not ones that block user flow or hang the browser.

Based on these findings (observed since 2019), the select component is not the right choice for large datasets. If we want consistent rendering across all screens, we should choose a number input over a select.

Safer Approach

A safer approach is to provide a configurable prop for the threshold, allowing users to choose between a select and a number input. This behavior would not be enabled by default but offered as an optional enhancement.

  • threshold == 0 → always render a number input
  • threshold == Infinity → always render a select

This change may break some tests for adopters that rely on page count behavior, unless we provide this prop and set the default to Infinity. Adopters would then need to manually opt in for the performance improvement.

Conclusion

We should prioritize practicality and usability. Components must be battle-tested for extreme use cases, remain performant, and avoid lagging or freezing the browser due to excessive resource consumption, which negatively impacts UX.

If consistency in design is required, the correct approach is to standardize on number input from the start. The select component is inherently non-scalable and should be treated as such.

TODO: contribute to WC once react design/behavior/a11y is finalized

Changelog

New

  • {{new thing}}

Changed

  • {{changed thing}}

Removed

  • {{removed thing}}

Testing / Reviewing

  1. Open the default pagination story from the deploy preview
  2. In totalItems add 300 and notice it renders select. make it 301 and notice it renders number input.
  3. Add a very high unrealistic number in totalItems and notice it doesnt effect the performance & observe there is no load on browser resources

PR Checklist

As the author of this PR, before marking ready for review, confirm you:

  • Reviewed every line of the diff
  • Updated documentation and storybook examples
  • Wrote passing tests that cover this change
  • Addressed any impact on accessibility (a11y)
  • Tested for cross-browser consistency
  • Validated that this code is ready for review and status checks should pass

More details can be found in the pull request guide

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 27, 2026

Deploy Preview for v11-carbon-react ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 76d79e2
🔍 Latest deploy log https://app.netlify.com/projects/v11-carbon-react/deploys/69efa1377c8d580008a069d5
😎 Deploy Preview https://deploy-preview-22128--v11-carbon-react.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 27, 2026

Deploy Preview for v11-carbon-web-components ready!

Name Link
🔨 Latest commit 76d79e2
🔍 Latest deploy log https://app.netlify.com/projects/v11-carbon-web-components/deploys/69efa1372b1a7a0008670edc
😎 Deploy Preview https://deploy-preview-22128--v11-carbon-web-components.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 27, 2026

Deploy Preview for v11-carbon-react ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 6511940
🔍 Latest deploy log https://app.netlify.com/projects/v11-carbon-react/deploys/69f34ab7524c19000822f26a
😎 Deploy Preview https://deploy-preview-22128--v11-carbon-react.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 27, 2026

Deploy Preview for v11-carbon-web-components ready!

Name Link
🔨 Latest commit 6511940
🔍 Latest deploy log https://app.netlify.com/projects/v11-carbon-web-components/deploys/69f34ab73348aa0008b84332
😎 Deploy Preview https://deploy-preview-22128--v11-carbon-web-components.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.88%. Comparing base (046c448) to head (6511940).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #22128      +/-   ##
==========================================
+ Coverage   95.09%   97.88%   +2.79%     
==========================================
  Files         541      196     -345     
  Lines       45239    30668   -14571     
  Branches     6511     1579    -4932     
==========================================
- Hits        43018    30018   -13000     
+ Misses       2092      641    -1451     
+ Partials      129        9     -120     
Flag Coverage Δ
main-packages ?
web-components 97.88% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Member

@tay1orjones tay1orjones left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking a look at this! A few loosely held opinions come to mind:

If there's a clear UX benefit to direct entry via a text/number input, I think we should consider making that the default and doing away with select entirely. We could do that with a feature flag. Maybe do away with preview__Pagination

On the other hand, if we have reason to believe it should switch, would there be a benefit to trying a more composable approach like preview__Pagination?

If we use a type="number" input, I think the stepper buttons should be hidden.

To me, visually, the text/number input does not immediately appear to be editable. This might need some design exploration?

I think it makes sense to update onChange instead of onKeyDown. Feels like better UX, no page thrashing if you type numbers one at a time. With onKeyDown you'd have like 324 -> Page 3, Page 32, Page 324

@devadula-nandan
Copy link
Copy Markdown
Contributor Author

devadula-nandan commented Apr 30, 2026

After reviewing preview pagination and patterns from the references today, here are the key observations:

  1. Developer experience
    The preview pagination approach introduces additional boilerplate, which may negatively impact DX.

  2. Breaking API change
    Requiring PageSelector to be passed explicitly as a child is a breaking change and would likely require a codemod.

    export const WithAPageSelector = () => (
      <Pagination {...props()} totalItems={350} pageSizes={[10, 20, 30]}>
        {({ currentPage, onSetPage, totalPages }) => (
          <PageSelector
            currentPage={currentPage}
            id="select-1"
            onChange={(event) => onSetPage(event.target.value)}
            totalPages={totalPages}
          />
        )}
      </Pagination>
    );
  3. Component scope
    Pagination is inherently atomic. its role is to display and update page state. Introducing children/slots adds complexity without clear value. Most references favor a simple number input for page navigation. rendered internally.

  4. Input behavior from references

    • Enter → triggers page change
    • Blur → reverts value
      Given the simplicity, error state may be unnecessary as the input is internally controlled with guardrails for min/max.
  5. Feature gaps in preview pagination

    • Lacks container query support, making responsive behavior harder to guarantee. especially if arbitrary children are allowed.
    • Contains some visual inconsistencies/bugs.
  6. Alternative approach
    The original problem could be addressed by introducing a pageNumberRenderer callback within the existing component. This allows customization (e.g., replacing the select) without introducing a new children-based API, which feels excessive for this use case.


Design challenge

The number input needs a clear visual affordance to indicate editability.

  • Carbon-style inputs rely on bottom borders/backgrounds for affordance
  • Removing these (for pagination styling) removes visual distinction
  • Steppers are too large and need to be hidden, further reducing clarity

Possible indicators:

  • Compact up/down arrows that can be kept internal.
  • Subtle visual cue (e.g., border, triangular indicator similar to toolbar patterns)
Screenshot 2026-04-30 at 9 58 26 PM

The toolbar-style triangular indicator is a potential option, though its suitability here is uncertain.


New Acceptance criteria to move forward

  • 1. Ship number input behind a feature flag: enableV12Pagination (using carbon number input)
  • 2. Finalize a clear visual indicator (can be async):
    • Compact steppers
    • Border or subtle visual cue
    • Triangular indicator
  • 3. Enter for updating the page. blur to revert previous value.
  • 4. Ensure the solution is a11y compatible.
  • 5. Tests
  • 6. Validate via telemetry and deprecate preview pagination if appropriate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants