Skip to content

Design system

All admin styles are served from packages/astropress/public/admin.css and cached with Cache-Control: public, max-age=31536000, immutable. The file is extracted from AdminLayout.astro so the browser can reuse it across all admin pages.


CSS custom properties

Light theme (:root)

TokenValuePurpose
--bg#f4f6f8Page background
--panel#ffffffCard and panel background
--text#17212cPrimary text
--muted#5e6b78Secondary / muted text
--line#d8dee5Borders and dividers
--accent#0d5c63Brand accent (links, focus rings)
--accent-soft#e6f4f2Soft accent background
--sidebar-bg#15202bSidebar background
--sidebar-textrgba(255,255,255,0.9)Sidebar primary text
--sidebar-mutedrgba(255,255,255,0.80)Sidebar muted labels
--topbar-bg#0f1720Topbar background
--button-primary-bg#0d5c63Primary button background
--button-primary-text#ffffffPrimary button text
--danger#c0392bDestructive actions, validation errors

Dark theme (html[data-theme="dark"])

TokenValuePurpose
--bg#0f1317Page background
--panel#171d23Card and panel background
--text#edf2f7Primary text
--muted#9eabb8Secondary / muted text
--sidebar-mutedrgba(158,171,184,0.95)Sidebar muted labels

WCAG AA contrast ratios

All text-on-background pairings in the admin UI meet WCAG 2.2 AA (minimum 4.5:1 for normal text, 3:1 for large text).

PairingLight ratioDark ratioAA pass?
--text on --panel (#17212c / #fff)~14.0:1~12.1:1
--text on --bg (#17212c / #f4f6f8)~10.9:1~15.8:1
--muted on --bg (#5e6b78 / #f4f6f8)~4.6:1~10.2:1
--accent on --bg (#0d5c63 / #f4f6f8)~5.8:1~9.0:1
white on --button-primary-bg (#fff / #0d5c63)~5.8:1
white on --danger (#fff / #c0392b)~5.3:1
--sidebar-text on --sidebar-bg~14.4:1

The color-contrast axe rule is enabled in CI (bun run test:accessibility). Any future token change that introduces a failing contrast ratio will fail the accessibility gate.


Component inventory

Web components (custom elements)

ElementSourcePurpose
<ap-html-editor>web-components/html-editor.tsRich text editor with toolbar, media library dialog, URL dialog
<ap-confirm-dialog>web-components/confirm-dialog.tsModal confirmation with showModal() focus trap
<ap-admin-nav>web-components/admin-nav.tsMobile sidebar toggle logic
<ap-theme-toggle>web-components/theme-toggle.tsLight/dark mode toggle, persists to localStorage
<ap-notice>web-components/notice.tsDismissable info/warning/error notice

Admin UI patterns

PatternHTML structureNotes
Admin layoutAdminLayout.astroProvides topbar, sidebar, main, skip-link
Form fields<label> + <input> + optional <span class="field-error">aria-describedby wired by inline validation JS
Action errors<div role="alert" aria-live="assertive" data-action-error>Populated from sessionStorage on page load
Confirm dialogs<ap-confirm-dialog>Use instead of window.confirm() — keyboard and screen-reader accessible
Data tables<table class="admin-table">Responsive via overflow-x: auto wrapper
Status chips<span class="status-chip status-{value}">Colour-coded by publish status
Pagination<nav class="pagination">?page=N query param, X-Total-Count header

Usage guidelines

  • Body text: --text on --bg or --panel
  • Secondary labels, help text: --muted
  • Borders and dividers: --line
  • Interactive elements, links, focus rings: --accent
  • Destructive actions and validation errors: --danger
  • Never use a hard-coded hex in admin component styles — always reference a CSS custom property so dark mode works automatically.

Adding a new admin page

  1. Use AdminLayout.astro as the shell — pass title, heading, currentPath, role, userName.
  2. Use safeAdminData() from src/admin-page-data.ts for data loading with error boundaries.
  3. Use withAdminFormAction() from src/admin-action-utils.ts for action handlers.
  4. Add the route to src/admin-routes.ts so audit:arch can verify route inventory shape.
  5. Add a BDD scenario to features/ and a verification group to scripts/bdd-test.ts.

RTL limitation

The admin CSS uses physical direction properties (margin-left, padding-left, text-align: left) in several places rather than logical properties (margin-inline-start, padding-inline-start). Right-to-left (RTL) scripts are not currently supported for the admin UI.