PSI Design System
Unified visual language for all Progressive Surface internal web apps. Covers design tokens (colors, type, spacing, density), 46 UI components, layout patterns, and 4 example app screens. Light-first, shop-floor optimized.
Overview
| Property | Value |
|---|---|
| Repo | C:\git\psi-design-system |
| Core file | assets/ps.css — design tokens + all component styles |
| Icons | assets/icons.js — call via <i data-icon="name"> |
| Tokens export | assets/tokens.json — reference export of every token |
| Fonts | assets/ps-fonts.css + assets/fonts/*.woff2 — self-hosted, no CDN |
| Version | 1.3.1 · 2026-06-02 |
| Stack | Vanilla HTML/CSS/JS prototypes; tokens consumable by any framework |
Changelog
| Version | Date | Notes |
|---|---|---|
| 1.3.1 | 2026-06-02 | Self-hosted fonts. Inter + JetBrains Mono vendored as .woff2 in assets/fonts/ and loaded via assets/ps-fonts.css (imported by ps.css) — no Google Fonts CDN, so the system works behind private endpoints with no public egress. Deploy the whole assets/ folder. |
| 1.3.0 | 2026-06-01 | Gap-closing release. Contextual density (--ps-scale + data-density modes) replaces the v1.2 global html { font-size: 150% } — dense desktop by default, data-density="floor" opts into 1.5x for gloved/distance use, and it no longer inflates consumer rem-based layouts. Success gets its own green (#16A34A), distinct from the brand/primary green, so “Complete” no longer looks like a button. Dark mode + accessibility: tokenized semantic -fg/-border (badges/alerts/toasts now adapt in dark mode), visible focus on every interactive element, offset focus ring (no more green-on-green), real role="switch" toggle, skip link. 14 new components (menu, tooltip, popover, spinner, empty state, banner, chip, avatar, key/value list, timeline, segmented control, date picker, combobox, pagination) plus an upgraded data table (sort, row select, sticky first column, zebra, loading/empty/error states, pagination footer). Data-viz palette (--ps-chart-1..8). Added tokens.json export. |
| 1.2.0 | 2026-05-12 | Global 1.5x scale baseline (superseded by 1.3 contextual density) |
| 1.1.0 | 2026-04-29 | Accessibility pass: 44px tap targets, reduced motion, auto dark mode via prefers-color-scheme, WCAG AA contrast fix, ARIA roles, skeleton loader, strengthened toast borders |
| 1.0.0 | 2026-04-23 | Initial release |
Why it exists
PSI had inconsistent UIs across apps — Process Services MES used one style, PSI Explorer another, new tools varied. This system unifies them around a modern SaaS aesthetic grounded in PSI’s actual brand (Pantone 348 green #027A54, near-black ink #1A1D1F).
Design tokens
Brand colors
| Token | Value | Use |
|---|---|---|
--ps-green-500 | #027A54 | Primary action, brand |
--ps-green-600 | #026647 | Hover state |
--ps-ink | #1A1D1F | Primary text |
--ps-ink-3 | #606770 | Muted / captions (passes WCAG AA on --ps-bg) |
--ps-bg | #F6F7F5 | Page background |
--ps-surface | #FFFFFF | Cards, panels |
--ps-border | #E4E6E2 | Default borders |
Semantic colors
| Role | Token | Hex |
|---|---|---|
| Success | --ps-success | #16A34A (v1.3 — distinct from brand green) |
| Warning | --ps-warning | #B7791F |
| Danger | --ps-danger | #C0392B |
| Info | --ps-info | #2563A8 |
Each role carries four tokens: base · -bg (tint) · -fg (text on tint) · -border. The -fg/-border tokens are overridden in dark mode, so badges, alerts, toasts, and banners stay legible in both themes — always use them rather than hard-coding hex. A categorical chart palette (--ps-chart-1 … --ps-chart-8) is derived from the brand + category accents.
Typography
- UI text: Inter →
var(--ps-font-sans) - Data/IDs/part numbers: JetBrains Mono →
var(--ps-font-mono) - Scale at 1× (each value is
× --ps-scale): 12/13/14/15/17/20/24/30/38/48px (--ps-text-xsthrough--ps-text-5xl) - Self-hosted (v1.3.1): fonts are vendored as
.woff2and loaded viaps-fonts.css— no Google Fonts CDN, so the system renders correctly behind private endpoints with no public egress.
Spacing
4px base grid, each step × --ps-scale: --ps-space-1 (4px) through --ps-space-20 (80px).
Density (v1.3)
One token — --ps-scale — drives type, spacing, control height, and chrome. Default is 1 (dense desktop). Opt into larger sizing per context with data-density on <html> or any container:
| Attribute | Scale | Use |
|---|---|---|
data-density="compact" | 0.92× | ultra-dense data desks |
| (default) | 1× | desktop — engineers, office, finance |
data-density="comfortable" | 1.2× | tablets (auto on pointer: coarse) |
data-density="floor" | 1.5× | gloves + distance viewing (operators, technicians) |
This replaced v1.2’s html { font-size: 150% }, which forced large sizing on everyone and inflated consumers’ rem-based layouts. The root font size is now untouched — rem stays predictable.
Radii
- Controls/inputs:
--ps-radius(6px) - Cards:
--ps-radius-lg(10px) - Modals:
--ps-radius-xl(14px)
Components (46 total)
| Category | Components |
|---|---|
| Layout | Topbar, Sidebar, Page scaffold, Breadcrumbs, Container |
| Actions | Button (5 variants, 3 sizes), Icon-only button, Segmented control |
| Forms | Input, Select, Textarea, Input group, Checkbox, Toggle (role="switch"), Combobox (typeahead), Date picker |
| Data | Table (sort / select / sticky column / zebra / states), Pagination, KPI card, Progress bar, Key/value list, Timeline, Chart palette + sparkbars |
| Feedback | Badge (5 states), Status pill (live dot), Alert, Toast (3 variants), Banner, Tooltip, Empty / error state |
| Overlays | Modal, Menu / dropdown, Popover, Spinner |
| Containers | Card, Launcher tile (category-accented) |
| Navigation | Tabs |
| Utilities | Avatar (+ group), Chip, Skip link, Monospace, Muted, Eyebrow label, Stack, Row |
Quick usage
<!-- Import -->
<link rel="stylesheet" href="assets/ps.css" />
<script src="assets/icons.js" defer></script>
<!-- Primary button -->
<button class="ps-btn ps-btn--primary">Save job</button>
<!-- Badge -->
<span class="ps-badge ps-badge--success">Complete</span>
<!-- Monospace ID (part numbers, job IDs) -->
<span class="ps-mono">J-84720-11</span>
<!-- Shop-floor density on a technician/operator screen -->
<html data-density="floor"> … </html>Full class reference: see AGENTS.md in the repo, or browse components.html.
Prototype pages
| File | Contents |
|---|---|
index.html | System overview, principles, changelog |
foundations.html | Color palette, type specimens, spacing, density, motion |
components.html | All 46 components with states and variants |
patterns.html | Page shell, list-detail, wizard, empty/error, mobile layouts |
examples.html | Launcher, job list, job detail, technician mobile |
Design principles
- 44px minimum tap targets — shop floor, gloves, distance; targets grow with
data-density="floor" - Density is contextual — one
--ps-scaletoken; dense desktop by default, larger on tablet/floor (not a global override) - Monospace for IDs — part numbers, job IDs, timestamps always use
ps-mono - Consistent chrome — same topbar, sidebar, table, badge palette across every app
- Copy voice — Direct: “Mark complete” not “Submit”; “48 orders waiting” not “Pending: 48”
Dark mode
Add data-theme="dark" to <html> (or rely on prefers-color-scheme). All --ps-* tokens auto-adapt — including the semantic -fg/-border tokens, so status colors on badges, alerts, toasts, and banners stay legible. No extra classes needed.
For AI agents
Read AGENTS.md in the repo root — it has a full token table, every component class name with HTML examples, the density model, and the design principles. This is the fastest path to building on-brand UIs without opening a browser.
The canonical source of truth for colors and spacing is assets/ps.css; assets/tokens.json is a generated reference export. When implementing in React or any other framework, import or mirror the CSS custom properties — don’t hardcode hex values.
Related
- Applications Overview — all PSI software
- Deploy to Azure — hosting new apps