Aropixel AdminBundle — Design system

Every component of the admin, rendered on the real bundle CSS. Generated from /admin/_catalog.

Static export · themable via CSS tokens

Colours Typography Spacing & radii Buttons Button group & split Badges & status Avatar Cards Stat Grid list List Accordion Dialog Modal sizes Toast Alerts Form controls Radio cards File upload Icons

Colours

Action hierarchy — the one rule the catalogue exists to state

Three levels, and a stylesheet cannot enforce them. Coral is one per screen — the thing the user came to do. Two corals on a page and neither means anything.

CTA · coral --aro-color-cta One per screen: save, publish
Primary · teal --aro-color-primary Ordinary actions: create, add
Secondary · slate --aro-color-secondary Structural / neutral-dark
Semantic & surfaces
--aro-color-success
--aro-color-danger
--aro-color-warning
--aro-color-info
--aro-color-bg
--aro-color-surface
--aro-color-border
--aro-color-text

Typography

Poppins, self-hosted. Sizes in rem (scale with browser zoom).

The quick brown fox — 2xl · 22px · page titles
The quick brown fox — xl · 18px
The quick brown fox — lg · 16px · subheadings
The quick brown fox — base · 14px · body
The quick brown fox — sm · 13px · secondary
The quick brown fox — xs · 12px · labels
Aa 300 Aa 400 Aa 500 Aa 600 Aa 700

Spacing & radii

1
2
3
4
6
8
12
xs
sm
input
card
pill

Buttons

Variants carry the action hierarchy. Sizes shrink text with padding.

<button class="btn btn-cta">Save</button> <button class="btn btn-primary btn-small">Add</button>

Button group & split button

Bootstrap .btn-group joins the buttons; our variants carry the state. A segmented view-switcher, and a primary action with a dropdown of alternatives. Any button content works — text, or ux_icon().

<div class="btn-group" role="group"> <button class="btn btn-primary active">List</button> <button class="btn btn-default">Grid</button> </div> <div class="btn-group"> <button class="btn btn-primary">Save</button> <button class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown"></button> <ul class="dropdown-menu dropdown-menu-end">…</ul> </div>

Badges & status

Badge Online Scheduled
online scheduled offline

Avatar

<span class="aro-avatar"><span class="aro-avatar__placeholder">{{ ux_icon('lucide:image') }}</span></span>

Cards

Card header
A card with a header, separated by a hairline.
A .card-primary with the teal top accent.

Stat

Key figures for dashboards. Atoms (label / value / trend) compose into a bare grid, a bordered card with divided cells, or a grey panel of icon cards. The figure uses the --aro-text-3xl scale step.

Simple
Deployments
405
Avg. time
3.65min
Servers
3
Success rate
98.5%
Trending — bordered
Revenue↑ 4.75%
€405,091
Overdue↑ 54.0%
€12,787
Pending↓ 1.39%
€245,988
Expenses↑ 10.2%
€30,156
Brand — panel of icon cards
Last 30 days
Subscribers
71,897 ↑ 122
View all
Open rate
58.16% ↑ 5.4%
View all
Click rate
24.57% ↓ 3.2%
View all
<div class="aro-stat aro-stat--bordered" style="--aro-stat-cols:4"> <div class="aro-stat__cell"> <div class="aro-stat__head"><span class="aro-stat__label">Revenue</span> <span class="aro-stat__trend">↑ 4.75%</span></div> <div class="aro-stat__value">€405,091</div> </div> </div>

Grid list

Records on a responsive grid of cards (vs. List's single vertical stack). Tiles reuse avatars and badges — here the centered card shape with a split action footer, and the simple initials row.

Card
Camille Lefebvre
Administrator
Online
Nicolas Roy
Editor
Away
Sarah Marchand
Reader
Offline
Simple
CL
Camille Lefebvre
Administrator
NR
Nicolas Roy
Editor
SM
Sarah Marchand
Reader
<div class="aro-grid-list" style="--aro-grid-min:220px"> <div class="aro-grid-card"> <div class="aro-grid-card__body">…avatar, title, subtitle, badge…</div> <div class="aro-grid-card__foot"> <a class="aro-grid-card__action">View</a> <a class="aro-grid-card__action">Edit</a> </div> </div> </div>

List

A stacked list of records — lighter than the DataTable when there are no columns to sort. Avatar + primary/secondary text, with meta / status / chevron / actions on the right, rows on the dashed hairline. Add aro-list--dark for the slate panel.

Members — meta & status
  • Camille Lefebvrecamille@aropixel.com AdministratorJust now
  • Nicolas Roynicolas@aropixel.com Editor1 h ago
  • Julien Petitjulien@aropixel.com Reader6 d ago
<ul class="aro-list"> <li><div class="aro-list__row"> <span class="aro-avatar aro-avatar--sm">…</span> <span class="aro-list__body"> <span class="aro-list__name">Camille Lefebvre</span> <span class="aro-list__secondary">camille@aropixel.com</span> </span> <span class="aro-list__meta">…role / last seen…</span> </div></li> </ul>

Accordion

Bootstrap .accordion, themed. Stacked collapsible panels for FAQs, grouped settings and dense forms. data-bs-parent keeps one open at a time.

From the article form, fill in the content then click “Save and publish”. The article becomes visible immediately.

Yes — pick a future publish date in the side panel. The article stays “Scheduled” until then.

Roles (Admin, Editor, Reader) are set in the Users section. Each role opens a different set of permissions.
<div class="accordion" id="faq"> <div class="accordion-item"> <h2 class="accordion-header"> <button class="accordion-button" data-bs-toggle="collapse" data-bs-target="#q1">Question</button> </h2> <div id="q1" class="accordion-collapse collapse show" data-bs-parent="#faq"> <div class="accordion-body">Answer</div> </div> </div> </div>

Dialog

A confirmation pattern on Bootstrap's .modal: an intent icon chip, a title, a message and confirm/cancel actions. Shown here as static content — in use it sits inside a .modal. Intents: --danger --warning --success --info (default primary); --centered stacks it.

<div class="modal-content aro-dialog aro-dialog--danger"> <div class="modal-body"> <div class="aro-dialog__head"> <span class="aro-dialog__icon">{{ ux_icon('lucide:triangle-alert') }}</span> <div><h2 class="aro-dialog__title">Delete this?</h2> <p class="aro-dialog__text">This is irreversible.</p></div> </div> </div> <div class="modal-footer"> <button class="btn btn-default">Cancel</button> <button class="btn btn-danger">Delete</button> </div> </div>

Toast

Floating flash notifications — white card, coloured left accent + icon, title/message, close. Shown with window.aroToast({type, title, message}); they stack top-right and auto-hide. Built on Bootstrap's native .toast (no plugin).

Article saved
Your changes were published.
Deletion failed
This item could not be removed.
Unsaved changes
Leaving now will discard your edits.
Heads up
The export is being prepared.
window.aroToast({ type: 'success', // success · danger · warning · info · primary title: 'Article saved', message: 'Your changes were published.', });

Alerts

Inline notices that live in the page flow (unlike the floating Toast) — a soft tinted panel, no border by default, with a leading icon and composable slots: description, error list, text-link actions, a right-aligned link, an --accent left bar and a --close dismiss. One accent per variant drives the tint and the darker text ink.

With description
Attention requise

Certains champs du formulaire sont incomplets. Vérifiez les informations avant d’enregistrer.

With list
2 erreurs avec votre soumission
  • Le titre de partage est obligatoire.
  • L’URL du réseau social n’est pas valide.
With actions
Article publié

L’article est désormais visible sur le site.

With link on the right

Une nouvelle version de l’administration est disponible (2.0.4).

Détails
With accent border

Vous n’avez plus de crédits d’export disponibles.

Mettre à niveau
With dismiss button

Import terminé avec succès.

Solid tone — the accent fills the panel

Maintenance planifiée ce dimanche de 2h à 4h.

<div class="aro-alert aro-alert--warning"> <span class="aro-alert__icon">{{ ux_icon('lucide:triangle-alert') }}</span> <div class="aro-alert__content"> <div class="aro-alert__main"> <div class="aro-alert__body"> <div class="aro-alert__title">Attention requise</div> <p class="aro-alert__text">…</p> </div> </div> </div> </div> Variants: --success · --danger · --warning · --info · --primary Modifiers: --accent (left bar) · --solid (filled). Dismiss: add .alert + data-bs-dismiss="alert".

Form controls

Radio cards

Mutually-exclusive options as selectable cards — the edge and wash follow the checked radio via :has(), so the whole card is the target and no JS is needed. Plain stacked/inline choices stay on Bootstrap .form-check.

<label class="aro-radio-card"> <input class="form-check-input" type="radio" name="plan" checked> <span class="aro-radio-card__body"> <span class="aro-radio-card__title">Pro</span> <span class="aro-radio-card__desc">Priority support.</span> </span> <span class="aro-radio-card__price">€29/mo</span> </label>

File upload

A dropzone with native click-to-browse (a <label> over a hidden input); add .is-dragover from a few drag handlers for the teal highlight. The preview row shows a chosen file.

poster-2026.jpg 1.2 MB
<label class="aro-fileupload"> <input type="file" class="aro-fileupload__input" accept="image/*"> <span class="aro-fileupload__icon">{{ ux_icon('lucide:image') }}</span> <span class="aro-fileupload__label">Drag a file or <span class="aro-fileupload__browse">browse</span></span> <span class="aro-fileupload__hint">PNG, JPG — max 2 MB</span> </label>

Icons — Lucide via ux-icons

Rendered inline as SVG in currentColor, so they take the surrounding text colour.

{{ ux_icon('lucide:plus') }}