abaabil

Abaabil

abaabil dialog/a11y580 B
@radix-ui/react-dialog13,493 B

Both gzipped, JS only, measured the same way: a dialog you can actually open, imported with every part it needs, bundled with esbuild, React external, minified. Radix ships no stylesheet of its own (this comparison leaves CSS out entirely) and it bundles positioning and portal logic that abaabil does not attempt, so it is not solving exactly the same problem. Full method, caveats, and five more components against nine libraries are on the Why page.

Abaabil is a small React component library: eight components (button, dialog, combobox, input, checkbox, radio, select, accordion), plain CSS in cascade layers instead of a CSS-in-JS runtime, and zero runtime dependencies. React 19 is the only peer. New here? Start at setup.

Eight components, three tiers each

Every component ships as three import entry points, so you pay only for what you use:

normal (e.g. abaabil/button): structure only, no styles, no ARIA logic. Several of these entries have no hooks at all, so they render in a Server Component tree with no client JavaScript.
styled (e.g. abaabil/button/styled): adds the component's CSS. Still hook-free where the component allows it.
a11y (e.g. abaabil/button/a11y): adds the keyboard handling, ARIA attributes and focus management the component needs. This is the tier most apps should reach for.

The three tiers of a component share one class name, so loading any one tier's stylesheet styles all of them on the page. Shipping no CSS is not the same as rendering unstyled: it means the page hasn't loaded that stylesheet yet.

Live theming

The controls below write --color-primary, --radius-md and --control-height-md onto a scope element. Every button underneath reads those same custom properties, live, because that is literally what the CSS says.

Delivered cost per entry point

Gzipped, each entry bundled with its own module graph, React treated as external (it is a peer dependency, not bundled). Grouped by component, since all 24 entries in one table stopped being readable a while ago. The CSS column is what that entry imports: the normal tier imports none, which is the whole point of it. Measured against the published abaabil@1.1.0 by the same script that produces the comparison tables on the Why page, so a component reads the same number on both. A styled entry sometimes measures a byte or two below its normal entry: that is compression noise, not a saving. styled is normal plus a stylesheet import, so the JavaScript is the same code and the CSS column is where its real cost is.

Button

EntryJSCSS
abaabil/button199 B
abaabil/button/styled198 B551 B
abaabil/button/a11y557 B551 B

Dialog

EntryJSCSS
abaabil/dialog168 B
abaabil/dialog/styled169 B371 B
abaabil/dialog/a11y580 B371 B

Combobox

EntryJSCSS
abaabil/combobox455 B
abaabil/combobox/styled455 B615 B
abaabil/combobox/a11y1,097 B615 B

Input

EntryJSCSS
abaabil/input166 B
abaabil/input/styled166 B497 B
abaabil/input/a11y501 B497 B

Checkbox

EntryJSCSS
abaabil/checkbox168 B
abaabil/checkbox/styled168 B651 B
abaabil/checkbox/a11y534 B651 B

Radio

EntryJSCSS
abaabil/radio165 B
abaabil/radio/styled166 B542 B
abaabil/radio/a11y444 B542 B

Select

EntryJSCSS
abaabil/select209 B
abaabil/select/styled210 B771 B
abaabil/select/a11y530 B771 B

Accordion

EntryJSCSS
abaabil/accordion320 B
abaabil/accordion/styled320 B528 B
abaabil/accordion/a11y364 B528 B

dialog/a11y, input/a11y, checkbox/a11y, radio/a11y, select/a11y, and every combobox entry, carry 'use client'. Every other entry point, including all three accordion entries and the three button entries, carries none, so those render in Server Components.

Browser floor

Chrome 99+, Firefox 98+, Safari 15.4+. Set by @layer and by Firefox's <dialog> support. CSS anchor positioning (used by the combobox listbox) is progressive enhancement behind @supports, not something the library depends on being available.