A reusable React component can make ten screens consistent and make all ten screens slow in the same way. Choose a design system for the interactions your product depends on, then test those interactions with realistic data. A component catalog tells you what is available; it does not tell you what happens when a user opens a long selector or changes a dense table.
Reuse solves consistency, not interaction latency
Design systems earn their place by standardizing behavior, accessibility decisions and visual language. They also concentrate implementation choices. If a commonly used control does unnecessary work on every interaction, adoption spreads that cost across the product.
That does not make reuse the problem. It makes performance part of the component’s contract. Before choosing a kit, identify the controls that carry consequential journeys: perhaps a long searchable selector, a table with bulk selection, or a form that validates as people type. Then ask whether those controls remain responsive with your data, on your target devices, inside your application.
Feature coverage and styling flexibility still matter; they are useful starting points for comparing React UI libraries. Bundle-size checks matter too, because users must load the product before using it. But neither a component count nor a bundle figure establishes how quickly an already-loaded selector opens. Treat loading and interaction as separate acceptance criteria.
What the October 2026 comparison actually shows
Den Odell’s October 2026 comparison tested ten design systems on two tasks: opening a 249-option country selector and selecting 100 checkboxes. The setup used production builds, Chrome 155, 4× CPU throttling and the median of three runs on an M1 Pro MacBook Pro. Among the React libraries were Mantine 9.7.1, Ant Design 6.6.5, Material UI 9.5.0 and React Spectrum 3.47.6.
For the selector, measured main-thread busy time was 84 ms for Mantine, 134 ms for Ant Design, 208 ms for Material UI and 227 ms for React Spectrum. For the checkbox task, the order changed: Material UI took 70 ms, Mantine 227 ms, React Spectrum 298 ms and Ant Design 421 ms. Material UI and Ant Design reversed their relative positions across the two tasks.
That reversal is the useful result. It argues against buying a design system on the strength of one chart. It does not establish a universal ranking, or predict what a differently configured control will do in your application. These were two implementations of two tasks on one machine, browser and throttling profile. Application state, option rendering, device mix and later library releases can change the result.
It is also important not to rename the measurements. Accumulated main-thread busy time for a task is not the duration of its longest frame, and neither is field Interaction to Next Paint (INP). Those figures answer related questions, but substituting one for another produces bad budgets and misleading comparisons.
The comparison is more valuable as a template than as a verdict. Its published test repository describes how to add a design system by copying a test folder and configuring the selector and checkbox setup. Its default checks include selector opening under 300 ms, no measured frame over 100 ms, and a 250-versus-125-option scaling comparison. Those are the author’s test budgets, not Web Vitals thresholds. The README advises calibrating absolute limits on the CI machine.
Turn product journeys into acceptance tests
Start with an inventory, not a benchmark suite. Ask product and engineering which interactions users repeat, which block a task when they stall, and which handle the largest datasets. Record representative option and row counts, target device classes, keyboard paths and accessibility requirements. An open-only selector test misses search and keyboard navigation; a single-checkbox test misses the cost of selecting a whole table.
Build a production-mode comparison page for shortlisted controls with equivalent data and behavior. Keep hardware, browser and test setup fixed across runs. Look at the distribution, not one unusually good trace. Retain both total main-thread work and the slowest observed frame: a control can do substantial work without putting it all in one frame, or produce a noticeable pause despite modest total work.
Then run the same control in the journey that ships. In a Next.js product, an isolated component story can hide surrounding loading, hydration and other main-thread work. Test the client-side path on which users actually encounter the control. Keep its loading criteria separate from its post-load interaction criteria so an improvement to one cannot mask a regression in the other.

Use field data to choose which journeys deserve investigation. INP measures latency from a click, tap or keyboard interaction until the browser can next paint; its published good threshold is at most 200 ms at the 75th percentile of field page views. Field INP can include input delay before your handler starts, while an isolated control test may not. Attribute slow interactions by route or control where possible, then reproduce the relevant journey. INP also does not describe every later effect of an interaction, so keep a behavioral test for work that appears after the next paint.
For CI, establish a baseline from repeated runs in the CI environment rather than copying another team’s limit. Performance-budget guidance recommends using a representative worst value, such as P90 or P95 of a recent measurement series, instead of letting one anomalous maximum justify a loose budget. Do not combine measurements from unlike devices or test populations into one reassuring number. Revisit the budget when the runner, browser or user population changes.
Profile the cause before changing libraries
A slow interaction does not automatically mean React rendered too much. Start with a Chrome Performance trace and distinguish scripting, style and layout, painting, and animation work. Chrome’s Long Animation Frames API reports frames over 50 ms, including frame duration, blockingDuration and script attribution. A long frame’s entire duration is not necessarily time spent blocking input.
If React renders look suspicious, add React’s Profiler. Its actualDuration and baseDuration describe rendering in a component tree. They do not measure the complete browser interaction. Check the browser trace before prescribing memoization: caching renders will not, by itself, remove repeated layout reads or expensive animations.
Odell’s examples show why diagnosis matters. Ant Design rendered only the visible portion of the tested selector list, while the tested Material UI selector added roughly one DOM element per option on opening. That suggests list rendering is worth examining for long selectors. It does not prove Material UI cannot virtualize them: its documentation provides a separate virtualized Autocomplete example.
Virtualization is not a free pass either. A React Spectrum Picker issue documents repeated visibility checks and size reads for visible virtualized options. Its reproduction recorded 133 layouts while rendering 17 visible options, with a 227 ms opening time under 4× CPU throttling. A proposed change exists; do not assume the issue is fixed in a version you plan to use without checking its release status. Reducing the rendered list did not eliminate the measured layout work in that reproduction.
For the checkbox task, Odell attributed much of Ant Design’s cost to simultaneous animations. Disabling them on his test page cut the measured selection time to less than one-third. That is a useful diagnostic intervention, not a promised speedup for every Ant Design application. Inspect what your bulk action animates, whether that feedback is necessary, and what happens when selection changes many rows at once.

Fix the control, then protect the improvement
Act at the smallest scope supported by evidence. For an oversized list, evaluate a virtualized implementation. For layout thrashing, examine the pattern of reads and writes. For bulk animations, reconsider what needs to animate. If a control cannot meet the product’s interaction and accessibility requirements after targeted work, replace that control rather than treating the entire design system as disposable.
Every such change needs a behavior check. A faster selector that loses keyboard navigation, focus management or screen-reader usability is not an improvement. Test those paths with the performance path, especially when changing list rendering. Put interaction regression checks alongside the design system’s other release checks; design-system governance and migration work should account for performance as well as consistency and accessibility.
Decision checklist for the next component review
Name the journey. Which selector, table action or form interaction matters, and what data size and device class represent its real use?
Compare equivalent behavior. Use production builds and repeated tests on the same setup; record total work, the slowest frame and the spread of results.
Check the shipped path. In Next.js, include surrounding client-side work rather than relying only on an isolated story.
Find the cause. Trace browser work first; use React Profiler to investigate rendering, not as a substitute for layout and paint evidence.
Change one thing at a time. Configure, optimize or replace the problem control; retest keyboard, focus and screen-reader behavior.
Set separate safeguards. Maintain CI interaction budgets calibrated to your runner, monitor field INP, and retain distinct loading checks.
If a team needs help applying that process to an existing component system, React and Next.js development support is most useful when it starts with the problematic journeys and traces—not a plan to rebuild every component.