Accent

UI

Accent UI — the admin’s finished skin: stock Bootstrap markup, one control height, colour as state.


Every control

Buttons

One height, stock weight, one ring — ink for the decision, outline for the workhorse.

Menus

The panel, its rows, and CmsSelectMenu — the select an admin surface actually reaches for.

Field rows

Label, control, hint — one height, one voice, one ring on focus.

Checks & switches

Booleans in the accent — and the control side of the Toggle family’s argument.

Tables

The list a CMS lives in — sortable headers, row selection, row actions, and the empty state that stops a blank list reading as a failure.

Accent has two design surfaces, and only one of them is designed. Mark Design is the design system for the web — the sites Accent renders — authored, opinionated, and worth a designer's whole attention. The admin is the opposite kind of surface: professional, quiet, and finished. It stays that way by refusing to be a design project — a refusal with a name, Accent UI, and a shape: one stylesheet over stock Bootstrap markup.

Each page in this section is a control the skin has claimed. Together they are the catalog: what an admin surface writes, and what it gets back.

The contract

An admin surface writes plain Bootstrap 5 and stops. The skin (src/accentUi.css) claims each control centrally — geometry, density, focus, state — so no call site carries any of it.

The skin owns The markup owns
One control height, one radius, one type size Which control it is
Focus — the same ring everywhere Labels, structure, order
Colour, and when it appears Nothing about how things look

Three rules keep the contract honest:

  • No size suffixes. btn-sm, form-control-sm, form-select-sm, and the small class on labels and menu rows are deliberate no-ops — the app has one control height and one control voice. Write the bare class.
  • No utility styling on controls. Bootstrap utilities are !important: a stray py-1, px-2, or shadow-sm on a control beats the skin and forks the app's density at that one call site.
  • No boldness. The skin does not hand out weight, and neither should markup — semibold text reads as a design change, and this app does not get designed.

Colour means the app is speaking

Ink does the work. Colour appears when the app has something to say about a thing — never as brand and never as decoration. Four colours, four jobs:

Colour Means
Blue The app's own voice — the primary action, selection, focus.
Red Destructive — delete, discard, revoke.
Green A good state — published, live, succeeded. Never a button.
Amber A warning — unsaved, awaiting review.

Everything else is ink, and a surface spends colour sparingly. Two primary buttons side by side means neither is the path.

Blue does double duty without ambiguity, because action and state never wear the same treatment: a solid fill acts, a soft tint with blue ink is merely selected.

The blue is a single accent, seeded once from Mark Design and inlined; there is no runtime coupling between the app and the design system, on purpose. The app would build and look identical on a machine that has never heard of Mark — it simply reads as family.

When Bootstrap runs out

If a control's behavior outgrows Bootstrap — a command palette, a true combobox — reach for a headless primitive for that one control and let the skin dress it. That is an engineering call, not a design one, and it does not reopen the design question.