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

PropertyValue
RepoC:\git\psi-design-system
Core fileassets/ps.css — design tokens + all component styles
Iconsassets/icons.js — call via <i data-icon="name">
Tokens exportassets/tokens.json — reference export of every token
Fontsassets/ps-fonts.css + assets/fonts/*.woff2 — self-hosted, no CDN
Version1.3.1 · 2026-06-02
StackVanilla HTML/CSS/JS prototypes; tokens consumable by any framework

Changelog

VersionDateNotes
1.3.12026-06-02Self-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.02026-06-01Gap-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.02026-05-12Global 1.5x scale baseline (superseded by 1.3 contextual density)
1.1.02026-04-29Accessibility 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.02026-04-23Initial 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

TokenValueUse
--ps-green-500#027A54Primary action, brand
--ps-green-600#026647Hover state
--ps-ink#1A1D1FPrimary text
--ps-ink-3#606770Muted / captions (passes WCAG AA on --ps-bg)
--ps-bg#F6F7F5Page background
--ps-surface#FFFFFFCards, panels
--ps-border#E4E6E2Default borders

Semantic colors

RoleTokenHex
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-xs through --ps-text-5xl)
  • Self-hosted (v1.3.1): fonts are vendored as .woff2 and loaded via ps-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:

AttributeScaleUse
data-density="compact"0.92×ultra-dense data desks
(default)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)

CategoryComponents
LayoutTopbar, Sidebar, Page scaffold, Breadcrumbs, Container
ActionsButton (5 variants, 3 sizes), Icon-only button, Segmented control
FormsInput, Select, Textarea, Input group, Checkbox, Toggle (role="switch"), Combobox (typeahead), Date picker
DataTable (sort / select / sticky column / zebra / states), Pagination, KPI card, Progress bar, Key/value list, Timeline, Chart palette + sparkbars
FeedbackBadge (5 states), Status pill (live dot), Alert, Toast (3 variants), Banner, Tooltip, Empty / error state
OverlaysModal, Menu / dropdown, Popover, Spinner
ContainersCard, Launcher tile (category-accented)
NavigationTabs
UtilitiesAvatar (+ 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

FileContents
index.htmlSystem overview, principles, changelog
foundations.htmlColor palette, type specimens, spacing, density, motion
components.htmlAll 46 components with states and variants
patterns.htmlPage shell, list-detail, wizard, empty/error, mobile layouts
examples.htmlLauncher, job list, job detail, technician mobile

Design principles

  1. 44px minimum tap targets — shop floor, gloves, distance; targets grow with data-density="floor"
  2. Density is contextual — one --ps-scale token; dense desktop by default, larger on tablet/floor (not a global override)
  3. Monospace for IDs — part numbers, job IDs, timestamps always use ps-mono
  4. Consistent chrome — same topbar, sidebar, table, badge palette across every app
  5. 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.