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.
| Token |
Value |
Purpose |
--bg |
#f4f6f8 |
Page background |
--panel |
#ffffff |
Card and panel background |
--text |
#17212c |
Primary text |
--muted |
#5e6b78 |
Secondary / muted text |
--line |
#d8dee5 |
Borders and dividers |
--accent |
#0d5c63 |
Brand accent (links, focus rings) |
--accent-soft |
#e6f4f2 |
Soft accent background |
--sidebar-bg |
#15202b |
Sidebar background |
--sidebar-text |
rgba(255,255,255,0.9) |
Sidebar primary text |
--sidebar-muted |
rgba(255,255,255,0.80) |
Sidebar muted labels |
--topbar-bg |
#0f1720 |
Topbar background |
--button-primary-bg |
#0d5c63 |
Primary button background |
--button-primary-text |
#ffffff |
Primary button text |
--danger |
#c0392b |
Destructive actions, validation errors |
| Token |
Value |
Purpose |
--bg |
#0f1317 |
Page background |
--panel |
#171d23 |
Card and panel background |
--text |
#edf2f7 |
Primary text |
--muted |
#9eabb8 |
Secondary / muted text |
--sidebar-muted |
rgba(158,171,184,0.95) |
Sidebar muted labels |
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).
| Pairing |
Light ratio |
Dark ratio |
AA 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.
| Element |
Source |
Purpose |
<ap-html-editor> |
web-components/html-editor.ts |
Rich text editor with toolbar, media library dialog, URL dialog |
<ap-confirm-dialog> |
web-components/confirm-dialog.ts |
Modal confirmation with showModal() focus trap |
<ap-admin-nav> |
web-components/admin-nav.ts |
Mobile sidebar toggle logic |
<ap-theme-toggle> |
web-components/theme-toggle.ts |
Light/dark mode toggle, persists to localStorage |
<ap-notice> |
web-components/notice.ts |
Dismissable info/warning/error notice |
| Pattern |
HTML structure |
Notes |
| Admin layout |
AdminLayout.astro |
Provides 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 |
- 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.
- Use
AdminLayout.astro as the shell — pass title, heading, currentPath, role, userName.
- Use
safeAdminData() from src/admin-page-data.ts for data loading with error boundaries.
- Use
withAdminFormAction() from src/admin-action-utils.ts for action handlers.
- Add the route to
src/admin-routes.ts so audit:arch can verify route inventory shape.
- Add a BDD scenario to
features/ and a verification group to scripts/bdd-test.ts.
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.