Skip to content

About

Why it exists

Abilian builds and maintains a range of business applications. They share a server stack and share nothing visually: each one accumulated its own Bootstrap fork, its own spacing habits, its own idea of what a "card" is. The cost is not aesthetic. It is that a fix in one is a fix in one, and a developer moving between them starts over.

The usual answer is to adopt an off-the-shelf kit. The usual result is that the kit's opinions leak into the product and its 300 independent values cannot be retuned as a set — so "make it denser for this client" becomes a fork.

The position

Tabler provides the taste; we provide the implementation.

Tabler is a mature, well-proportioned admin design language, and reproducing its judgement is cheaper than inventing one. But consuming it means inheriting Bootstrap, a build step, and a vocabulary nobody here controls.

So this is not a Tabler wrapper. It is an independent implementation, held to Tabler's measurements by a calibration harness that renders 78 elements side by side against the real thing and compares them property by property. It reports zero differences.

That separation is the whole point. Tabler decides how it looks; we decide how it is built. When the two goals diverge — and they do, on accessibility — we can take the divergence deliberately instead of forking.

Where the reference is not enough

Tabler's success green measures 2.48:1 as text on its own tint. The floor for body text is 4.5:1. Rather than silently ship the failure or silently diverge, that became a knob: --ads-contrast: 0 is the reference's own palette, 1 moves every intent to a readable ink without touching a single fill, border or tint. Both ends are asserted by tests.

Status

Usable and in use by one reference application. Not yet proven across a second, which is the current priority.

Stylesheet 16 files, 3,034 lines
Vocabulary 27 knobs, 128 derived tokens, 256 classes
Reference application 50 routes, 4 shell layouts, 6 live islands, 6 languages, RTL
Visual parity 0 properties differ across 78 elements vs Tabler
Linter 18 rules, 0 findings
Automated checks 88 passing — 32 library, 25 application, 31 in a real browser

Roadmap

  1. A second application. The reference demo proves the system can build the reference demo. Nothing yet proves it survives a different domain and a developer who did not write it. In progress.
  2. A real screen-reader pass. Everything tested so far is what a browser can be asked about the DOM, which catches absent semantics but not wrong ones.
  3. Density tuning. The knobs sit at Tabler's values so parity can be measured. Abilian's applications are dense tools and may well want a smaller base type and a sub-1 space scale — a product decision to take once there is a second application to take it against.
  4. Package and publish, so "vendored and hashed" becomes a real guarantee rather than a local convention.

Design principles

  • The menu is closed. A value you cannot name does not exist. Needing one is a signal to add a token, never to reach for a literal.
  • Derive, do not enumerate. If two values must move together, one is computed from the other.
  • Enforcement is the linter, not the document. A document is a probability; most-of-the-time is not a design system.
  • The look cannot exist without the meaning. State a person can perceive is an attribute — aria-current, aria-pressed, aria-invalid — and the stylesheet keys off that attribute, so there is nothing for an author to remember.

Licence and credits

Built by Abilian. Visual language after Tabler by Paweł Kuna. Icons are Tabler Icons. Interactive islands use situ.