Skip to content

Principles

Operators sit in these screens all day, so the defaults favour density over padding and keep the variant count low. Keyboard affordances and predictable focus count for more than chrome does. When in doubt: would this make a 12-row form easier or prettier? Pick easier. Use a different system for customer-facing surfaces.

Behaviour HTML and CSS can express declaratively is not written in JavaScript. A dialog is <dialog> and an accordion is <details>; animation stays in CSS. There is no legacy budget and no polyfills. Where behaviour is genuinely stateful, the React package wraps Base UI rather than rolling its own, and each component’s Reference names the primitive.

@aortl/admin-css defines .btn, .input, .field; @aortl/admin-react emits those same classes. Vanilla HTML and React render identical DOM, so adopting one flavor doesn’t lock out the other — mix them on the same page. The CSS is the source of truth and React inherits visual changes from it.

Class names are therefore public API: renaming .btn-primary is a breaking change. They read <base> + <base>-<variant> + (optional) <base>-<size> + (optional) <base>-<modifier>, with sizes sm / md (default, omitted) / lg.

A Flexoki palette (--color-blue-600, --color-base-50) holds absolute tones, identical in light and dark mode. Semantic roles (--color-primary, --color-surface, --color-danger) alias them through light-dark(). Components reference only the semantic layer, so one override moves everything using that role. Spacing, radii, and shadows use Tailwind’s built-in scales.

See Colors for the catalog, Theming for overrides, and Conventions for the props and classes every component shares.