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:
| What | How |
|---|---|
| The WCAG 2.0, 2.1 and 2.2 AA rules that axe can measure | axe-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 tokens | Every text and background pair, in both themes, on every test run. |
| Keyboard, focus and motion | Tests in a real browser: the focus ring, focus returning when an overlay closes, keyboard dragging, prefers-reduced-motion and printing. |
| Touch targets | Geometry measured in the browser. |
In three engines
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/ui | react-aria-components | shadcn/ui | HeroUI | antd | MUI | Mantine |
|---|---|---|---|---|---|---|---|
Button | 6.9 KB | 14.6 KB | 15.7 KB | 34 KB | 122.4 KB | 45.6 KB | 23.7 KB |
Button + Select + DatePicker | 32.5 KB | 59.3 KB | 83.3 KB | 98.4 KB | 243.7 KB | 162.9 KB | 95.4 KB |
Table | 42.4 KB | 53.6 KB | 16.3 KB | 93.6 KB | 310.3 KB | 94.7 KB | 31.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):
| Screen | Total on load | Over React alone | JS | CSS | Hydration, median (min-max) | Run | axe failures |
|---|---|---|---|---|---|---|---|
| React without a library | 68.7 KB | — | 68.1 KB | 0.2 KB | 62 ms (51–95) | — | 0 |
| @amset/ui | 127.3 KB | +58.6 KB | 107.1 KB | 17.4 KB | 150 ms (122–352) | 6/6 | 0 |
| MUI | 219.6 KB | +150.9 KB | 210.8 KB | 0.2 KB | 242 ms (182–308) | 6/6 | 0 |
| Mantine | 175.7 KB | +107 KB | 156.6 KB | 15.1 KB | 149 ms (132–276) | 6/6 | 0 |
| antd | 390.6 KB | +321.9 KB | 343.9 KB | 0.2 KB | 352 ms (292–739) | 6/6 | 0 |
- It is not a feature comparison. The
@amset/uiTablesorts, 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.
| Library | Versions measured |
|---|---|
| @amset/ui | @amset/ui 0.16.0 |
| react-aria-components | react-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 |
| antd | antd 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 todas | react 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
sideEffectslimited to.cssfiles: 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:
Flagrequests 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
| What | What it does |
|---|---|
| Dependencies | None at runtime; React and React DOM are peers. CI audits security advisories and fails on a high or critical one. |
| HTML injection | No dangerouslySetInnerHTML, no innerHTML, no eval, no new Function in the code. |
javascript: links | Blocked by React 19. The editor toolbar also rejects data: and any scheme not on its list. |
| Links to another tab | Link and ButtonLink with target="_blank" always carry rel="noopener noreferrer". |
| Network | The only request the library makes is the one from Uploader, to the address you give it. |
| Storage | localStorage 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.
