Skip to content
EspañolEnglish

Quality, measured

What this page claims has been checked and can be repeated: each figure says when it is from and what it was measured with, and what has not been measured is stated as such.

Accessibility

The library does not claim a conformance level: that is signed off by an external audit of a specific application, and none exists yet. What is public is what runs on every change:

WhatHow
The WCAG 2.0, 2.1 and 2.2 AA rules that axe can measureaxe-core with Playwright on the interactive story of each component page and the review pages, in light, in dark and on mobile. In CI it blocks the merge with the light theme; dark and mobile are run before pushing.
The contrast of the colour tokensEvery text and background pair, in both themes, on every test run.
Keyboard, focus and motionTests in a real browser: the focus ring, focus returning when an overlay closes, keyboard dragging, prefers-reduced-motion and printing.
Touch targetsGeometry measured in the browser.
What has not been measured
Real screen readers (NVDA, JAWS, VoiceOver, TalkBack) with a test matrix; 200 % and 400 % zoom as a systematic test; the AAA level; and a third-party audit. The editor guide already includes the script for the manual pass with NVDA and VoiceOver on the components that need it most. Anyone who has to meet a specific level has to audit their application: this is the starting point.

The behaviour tests (focus, overlays, keyboard, dragging, printing, motion) run in Chromium, and also in Firefox and WebKit: that is where two bugs that Chromium did not show came up (the focus Safari lost when closing a dropdown, and dialogs that vanished abruptly in Firefox and Safari). CI has a fast gate with both.

Size

Measured on October 19, 2026 with the benchmark in the library's repository: the same bundler (Vite, in production) and the same settings for all of them, with React left out of the count. It is the weight in the bundle, gzip-compressed, of what is requested and used:

What is requested@amset/uireact-aria-componentsshadcn/uiHeroUIantdMUIMantine
Button6.9 KB14.6 KB15.7 KB34 KB122.4 KB45.6 KB23.7 KB
Button + Select + DatePicker32.5 KB59.3 KB83.3 KB98.4 KB243.7 KB162.9 KB95.4 KB
Table42.4 KB53.6 KB16.3 KB93.6 KB310.3 KB94.7 KB31.6 KB

And the same screen (a form with validation, an orders table with sorting and pagination, and a confirmation dialog) built with four libraries, rendered on the server and hydrated in Chromium with the CPU throttled four times (median of 15 loads):

ScreenTotal on loadOver React aloneJSCSSHydration, median (min-max)Runaxe failures
React without a library68.7 KB—68.1 KB0.2 KB62 ms (51–95)—0
@amset/ui127.3 KB+58.6 KB107.1 KB17.4 KB150 ms (122–352)6/60
MUI219.6 KB+150.9 KB210.8 KB0.2 KB242 ms (182–308)6/60
Mantine175.7 KB+107 KB156.6 KB15.1 KB149 ms (132–276)6/60
antd390.6 KB+321.9 KB343.9 KB0.2 KB352 ms (292–739)6/60
  • It is not a feature comparison. The @amset/ui Table sorts, filters, groups, virtualises and edits in cell; the MUI and Mantine ones do none of that on their own. What is measured is size.
  • The CSS of HeroUI and shadcn is not included in the individual pieces: Tailwind generates it in each application. That is why those two, and react-aria-components, which ships no styles, have no equivalent screen. shadcn is not a library: what is measured is what its pieces pull in.
  • MUI and antd put the CSS inside the JavaScript, and their HTML is heavier because they render it inside.
  • The Mantine and antd screens change their theme: with the default one they fail AA contrast. It is corrected with their own settings.
  • Hydration time depends on the machine: it is valid for comparing the libraries with each other in the same run, not as an absolute figure. The machine was not idle; that is why the median and the range are given. The sizes do not depend on that.
  • Not measured: build time, memory, performance when typing or sorting thousands of rows, or the size with other bundlers.
LibraryVersions measured
@amset/ui@amset/ui 0.16.0
react-aria-componentsreact-aria-components 1.22.1
shadcn/ui@radix-ui/react-slot 1.5.0, @radix-ui/react-select 2.4.1, @radix-ui/react-popover 1.3.1, class-variance-authority 0.7.1, clsx 2.1.1, tailwind-merge 3.7.0, react-day-picker 10.0.2, date-fns 4.4.0, @tanstack/react-table 8.21.3
HeroUI@heroui/react 3.2.6, framer-motion 14.3.0
antdantd 6.6.6, @ant-design/cssinjs 2.1.2
MUI@mui/material 9.5.0, @mui/x-date-pickers 9.0.0-rc.0, @emotion/react 11.14.0, @emotion/styled 11.14.1, dayjs 1.11.23
Mantine@mantine/core 9.7.3, @mantine/dates 9.7.3, @mantine/hooks 9.7.3, dayjs 1.11.23
Común a todasreact 19.3.1, react-dom 19.3.1, vite 6.4.4, playwright 1.63.0, axe-core 4.13.0

Lightweight by default

  • One file per component and sideEffects limited to .css files: the bundler takes the JavaScript and CSS of what you import, nothing more.
  • Each component imports its own stylesheet: there is no global stylesheet loading the whole library on every page.
  • Languages are loaded on demand: with seven configured, one is downloaded.
  • Flags are split by region: Flag requests the drawings for the region of the flag it renders, not those of the whole world.
  • Icons are imported one by one: there are 2,134 and only the ones you use add weight.
  • Overlays that are not open do not mount their content: a closed date picker does not render its calendar.

Server, client and hydration

Components without interaction can be used from a server component; those with interaction carry 'use client' as far down as possible. No component reads "today" or "now" while rendering, and the spaces Intl writes are normalised: that way the server HTML and the browser HTML match even when they are rendered on different days, in different time zones or with different ICU versions. One test renders each component page on one day and hydrates it on another.

Security

WhatWhat it does
DependenciesNone at runtime; React and React DOM are peers. CI audits security advisories and fails on a high or critical one.
HTML injectionNo dangerouslySetInnerHTML, no innerHTML, no eval, no new Function in the code.
javascript: linksBlocked by React 19. The editor toolbar also rejects data: and any scheme not on its list.
Links to another tabLink and ButtonLink with target="_blank" always carry rel="noopener noreferrer".
NetworkThe only request the library makes is the one from Uploader, to the address you give it.
StoragelocalStorage stores the theme and, if requested with persistKey, the columns of a table. Nothing else; no cookies.

What is up to you: check addresses that come from a user before using them as href, and sanitise the HTML from an editor on the server. A vulnerability is reported with a confidential issue in the amset/amset-ui project on gitlab.amset.tech, never in a public one. Only the latest minor version receives fixes.

Licence

MIT: it can be used in personal and commercial projects, modified and redistributed, keeping the copyright notice.