Files
cve-dashboard/docs/design-system-redesign/README.md
root 27192dd69f WIP: Dashboard redesign — design system overhaul and component updates
Frontend redesign in progress: updated styles, layout, and components
across all pages to align with new design system. Includes Jira API
compliance specs, property tests, and load test script.
2026-04-29 14:20:23 +00:00

18 KiB
Raw Permalink Blame History

STEAM Security Design System

A design system for the STEAM Security Dashboard — a self-hosted vulnerability management workbench used by the NTS-AEO-STEAM and NTS-AEO-ACCESS-ENG business units. This repo captures the visual language, content patterns, tokens, and UI kit needed to extend or rebuild the product without drifting from its established look.

What the product is

The STEAM Security Dashboard centralises:

  • CVE tracking — searchable, filterable, vendor-aware CVE list with NVD auto-fill, document attachment, and group-based ownership
  • Ivanti / RiskSense host findings — live remediation queue with FP / Archer / CARD workflows, inline editing, per-finding notes, and a personal "Ivanti Queue" staging list
  • AEO compliance posture — weekly xlsx upload with drift detection, diff preview, per-team metric health cards, device-level violation tracking, and timestamped notes
  • Archer EXC tickets — risk-acceptance ticket tracking linked to CVE / vendor pairs
  • Knowledge base — internal document library (PDF, Markdown, Office, etc.) for runbooks, advisories, and policies
  • Admin panel — user / group management, audit log, system info — all gated behind an Admin group

Four user groups (Admin, Standard_User, Leadership, Read_Only) define every permission boundary, and every state-changing action is audit-logged.

The 6 pages

  1. Home / Dashboard — CVE list, filters, calendar widget for due dates
  2. Reporting — Ivanti host findings, charts, queue, export
  3. Compliance — AEO posture, metric health cards, device drill-in
  4. Knowledge Base — document library
  5. Exports — bulk export tools (group-gated)
  6. Admin Panel — user management, audit log, system info (Admin only)

Sources

  • Codebase: https://vulcan.apophisnetworking.net/jramos/cve-dashboard (Gitea, master branch). Auth required; raw file fetch is gated. The repo's own README.md (fetched via the source viewer) is the most accurate functional spec we had access to and is the basis for this system.
  • Existing design ref: DESIGN_SYSTEM.md (290 lines, in-repo) — referenced in the audit but not directly accessible from the host.
  • Component audit provided in the project brief: 29 components, 5 primitives, 14 composites, 5 pages, 1 context provider.
  • Stack: React 19, lucide-react, recharts, react-markdown + rehype-sanitize, mermaid, xlsx. Backend Express 5 / SQLite3.

Index — what's in this folder

Path What it is
README.md This file — context, content + visual foundations, iconography
SKILL.md Agent Skill manifest for Claude Code compatibility
colors_and_type.css Source-of-truth tokens — color, type, spacing, radii, elevation
fonts/ Font references (Outfit + JetBrains Mono via Google Fonts CDN)
assets/ Logo mark, brand SVGs, severity icons
preview/ Design System tab cards — registered as assets
ui_kits/cve-dashboard/ High-fidelity recreation of the dashboard, focused on Knowledge Base

CONTENT FUNDAMENTALS

The product is a tactical operations console for security engineers. Copy is dense, terse, and assumes a reader who already knows what a CVE, EXC ticket, FP workflow, and BU filter are. There is no marketing voice, no onboarding nudges, and no exclamation marks.

Voice & tone

  • Operational, not editorial. Buttons say "Sync", "Confirm Upload", "Reconcile Config", "Add to Queue". Never "Let's get started" or "You're all set".
  • Imperative for actions, declarative for state. "Save", "Delete", "Hide Selected" — never "Saving your changes…" with three dots and a heart.
  • No emoji. Status is communicated through colour-coded badges and short text labels.
  • Title Case for navigation and headers, Sentence case for body and inline labels. Tabs and buttons: User Management, Audit Log, System Info. Helper text: Filter tickets by CVE ID, vendor, or status.

Person & address

  • Second-person sparingly — only when the system is talking about the user's data: "your login", "your filtered view", "your queue". Never "Welcome back, {name}".
  • First-person plural never. No "We've updated" or "Let us know".
  • Errors are direct, no apology. "SESSION_SECRET environment variable must be set." "Login rate limited — wait 15 minutes." Never "Oops! Something went wrong."

Casing

  • CVE IDs: uppercase with hyphen — CVE-2024-12345. Validated against /^CVE-\d{4}-\d{4,}$/.
  • EXC numbers: uppercase — EXC-12345. Validated /^EXC-\d+$/.
  • Severity labels: Title Case — Critical, High, Medium, Low. Status labels: Open, Addressed, In Progress, Resolved.
  • Workflow state badges: SHOUT CASE for SLA states only — OVERDUE, AT_RISK, WITHIN_SLA. Everything else is Title Case.
  • Group names: snake_case in code (Standard_User), Title Case in UI (Standard User).

Density and units

  • Numerical metrics are bare integers ("12 findings", "47 devices"). Percentages always carry the % sign with no space.
  • Dates are explicit, no relative time except "Last sync: 4h ago" patterns.
  • Column headers are short — Host, IP Address, DNS, BU, SLA — never Host Name (Editable).

Specific copy conventions seen in product

  • "— empty —" as a filter option for empty cells
  • "Hidden (N)" pattern for counted UI states
  • "+N" badge for overflow (e.g., 2 CVEs shown, "+5" badge)
  • "↻" revert glyph next to overridden cells, with a small amber dot ● for the overridden state
  • Tooltips appear after a 300ms delay and are session-cached
  • "View in Reporting →" inline link pattern with a literal arrow

What NOT to write

  • No motivational copy ("Great work!", "You're crushing it")
  • No question-mark headlines ("Need help?")
  • No marketing CTAs ("Upgrade now", "Try premium")
  • No mascot or persona — the system is the system

VISUAL FOUNDATIONS

The dashboard reads as a dark tactical intelligence console — slate / graphite backgrounds, sky-blue as the primary accent and ambient glow, severity colours used like signal flags, animated pulse-glow status dots, and information density prioritised over breathing room. The aesthetic is closer to a SOC / NOC mission display than to a flat enterprise SaaS.

Colour vibe

  • Dark slate base. #0F172A (deep slate) for the page, #1E293B for surfaces, #334155 for elevated surfaces and borders. Almost black, never pure black. The cool tone is consistent — no warm shadows.
  • Sky blue is the brand accent#38BDF8 is the primary action / link / focused state colour. It appears in buttons, active nav items, link text, and the "create" badge in the audit log.
  • Severity is a fixed semantic system — the colours below MUST mean what they mean and nothing else.
    • Critical → Red #EF4444
    • High → Amber #F59E0B
    • Medium → Sky #38BDF8
    • Low → Emerald #10B981
  • Neutral text scale#F1F5F9 (primary fg), #CBD5E1 (secondary), #94A3B8 (muted), #64748B (placeholder / disabled). Never pure white.
  • Group badges — Admin red, Standard_User accent blue, Leadership amber, Read_Only muted grey. The same severity language reappears here for status urgency.

Typography

  • Outfit for all UI (headers, body, buttons, navigation). Geometric sans, friendly but precise; weights 400 / 500 / 600 / 700.
  • JetBrains Mono for data — CVE IDs, IP addresses, hostnames, EXC numbers, finding IDs, code blocks. Anything you'd grep for.
  • Scale is compact. Page titles 2428px / 600 weight; section headers 1618px / 600; body 14px / 400; data table cells 13px / 400 mono. Line-height stays tight (1.4) to preserve density.

Spacing

  • 4 / 8 / 12 / 16 / 24 / 32 / 48 — a roughly 4px grid. Cards have 1620px internal padding; rows in dense tables have 810px vertical padding; modals have 24px internal padding.
  • Section gaps are 2432px. Between siblings, 1216px is the dominant rhythm.

Backgrounds

  • No imagery. No hero photographs, illustrations, or marketing visuals. The page is solid #0F172A.
  • Subtle sky-blue grid is allowed. A 20×20px grid at rgba(14,165,233,0.025) (.grid-bg utility) sits behind hero / empty regions. It is barely visible and never dominates.
  • Surfaces use diagonal gradients, not flat fills — linear-gradient(135deg, rgba(30,41,59,0.95), rgba(51,65,85,0.9)) is the canonical card surface.

Cards and surfaces (intel-card)

  • Background: diagonal gradient 135deg, rgba(30,41,59,0.95) 0%, rgba(51,65,85,0.9) 50%, rgba(30,41,59,0.95) 100%
  • Border: 1.5px solid rgba(14,165,233,0.30) — sky-blue at low alpha, not slate grey
  • Radius: 8px (default) / 12px (modals) / 4px (chips)
  • Internal padding: 1620px
  • Resting shadow: 0 4px 12px rgba(0,0,0,0.4) + 0 2px 6px rgba(0,0,0,0.3) + inset 0 1px 0 rgba(14,165,233,0.10) (sky highlight on top edge)
  • Hover: border opacity climbs to 0.50, the card lifts translateY(-2px), and gains a 0 0 30px rgba(14,165,233,0.10) ambient glow. A ::after shimmer sweeps left→right on entry.
  • Stat cards add a 2px linear-gradient(90deg, transparent, #0EA5E9, transparent) rail on the top edge.

Borders

  • Sky-blue at low alpha is the dominant border treatment — rgba(14,165,233,0.15) for subtle dividers, 0.25 for default, 0.40 for strong / hover. Pure slate #334155 borders appear only on tables and inputs at rest.
  • Focus state: 2px sky-blue ring 0 0 0 2px rgba(14,165,233,0.15) plus the border swaps to solid #0EA5E9.
  • Severity-tinted left borders are NOT a pattern — colour is carried by badges, dots, and glow.

Animation

  • Pulse-glow on status dots is canonical. Every severity / SLA badge has an 8px circle that pulses box-shadow: 0 0 5px → 15px currentColor on a 2s ease-in-out loop (@keyframes pulse-glow).
  • Card hover lift is 300ms cubic-bezier(0.4,0,0.2,1) with a ::after shimmer sweep — linear-gradient(90deg, transparent, rgba(14,165,233,0.08), transparent) translating from left:-100% to 100% over 500ms.
  • Buttons have a circular ripple ::before that scales from 0×0 to 300×300 on hover (500ms).
  • Modal entry: 200ms fade + slight translate. Slide-out panels: 240ms ease-out from the right.
  • Tooltips have a deliberate 300ms hover delay before appearing.
  • A .scan-line utility (3s loop) is available for hero / loading affordances — used sparingly.

Hover states

  • Cards lift -2px, border opacity climbs from 0.300.50, and a sky-blue ambient glow 0 0 30px rgba(14,165,233,0.10) appears.
  • Buttons brighten their gradient fill from 0.15/0.10 to 0.25/0.20 alpha, gain a 0 0 20px brand-color glow, and lift -1px.
  • Text links lighten from #38BDF8 to #7DD3FC and the bottom border brightens to match.
  • Table rows get a rgba(0,217,255,0.06) wash plus 0 2px 8px rgba(0,217,255,0.10) sub-shadow.
  • The audit notes a current anti-pattern: hover states implemented via onMouseEnter / onMouseLeave JS handlers. The design system standard is CSS :hover pseudo-classes — JS hover is a defect to migrate away from.

Press / active states

  • Button: shifts to #0EA5E9 (slightly darker than hover), no shrink, no shadow change. Press is a colour signal, not a physics signal.
  • Rows / interactive cards: #475569 background on :active.

Transparency & blur

  • Modal backdrops: rgba(10, 14, 39, 0.97) with backdrop-filter: blur(12px). The blur is heavy and the backdrop is near-opaque — modals fully obscure the background.
  • Tooltips: gradient linear-gradient(135deg, #334155, #475569) with a sky-blue border and 0 4px 12px + 0 0 16px rgba(14,165,233,0.15) glow.
  • Inputs: translucent rgba(30,41,59,0.6) background with inset 0 2px 4px rgba(0,0,0,0.2) for a subtle recessed feel.

Inner / outer shadows

  • Both are used. Cards combine outer drop + inner sky-blue highlight: 0 4px 12px rgba(0,0,0,0.4), inset 0 1px 0 rgba(14,165,233,0.10).
  • Inputs are recessedinset 0 2px 4px rgba(0,0,0,0.2) plus a 0 1px 0 rgba(255,255,255,0.03) top sheen.
  • Document items (within KB / vendor lists) use a stronger inset inset 0 2px 4px rgba(0,0,0,0.3) to read as nested / pressed-in.
  • Modals lift on 0 20px 60px rgba(0,0,0,0.6) + 0 10px 30px rgba(14,165,233,0.10) — heavier than most enterprise products, but the brand glow is the signature.

Layout rules

  • Full-width fluid above 1024px — the dashboard fills the viewport, with content max-width capping at ~1600px on very wide displays.
  • Top app bar is fixed — height 56px, contains brand mark, page nav, and UserMenu. Sits above all content with z-index: 50.
  • Side nav drawer (NavDrawer) slides from the left on icon click; it does not push content (overlay model).
  • Slide-out panels (Atlas, Compliance Detail) come from the right, ~480px wide on desktop, full-width on narrow viewports.
  • Modals are centered, max-width 640px (small) or 960px (wizard / upload), with the standard backdrop.

Severity language

This is the most important visual rule in the product. Severity badges use the status-badge pattern:

  • 2px solid border at 0.6 alpha
  • Diagonal gradient fill at 0.20 / 0.15 alpha
  • Lighter text for legibility — #FCA5A5 (critical), #FCD34D (high), #7DD3FC (medium), #6EE7B7 (low) — not the raw severity colour
  • Text-shadow 0 0 8px brand-color at 0.4 alpha
  • 8px filled circle dot with a pulsing box-shadow: 0 0 12px / 0 0 6px glow on a 2s loop
  • 0 4px 8px rgba(0,0,0,0.4) outer shadow
  • Always JetBrains Mono, uppercase, 0.5px letter-spacing

Secondary references can use simpler tinted pills (rgba(brand,0.12) background + brand text, no border, no glow). Single coloured dots next to numeric scores are also valid. The colour-to-severity mapping is fixed across every component.

Headings — the brand glow

Page titles and section headers are JetBrains Mono, uppercase, sky-blue #38BDF8, with text-shadow: 0 0 16px rgba(14,165,233,0.30), 0 0 32px rgba(14,165,233,0.15). This is the most identifiable single signal in the product — every page header reads as a glowing terminal title. Outfit is reserved for body, helper, and table cell text. The Knowledge Base markdown viewer continues this language: h1 sky-blue, h2 emerald, h3 amber — a deliberate severity-coloured hierarchy.


ICONOGRAPHY

The product uses lucide-react as its sole icon system. Lucide is a 1.5px-stroke, geometric, open-source icon set — clean, restrained, and perfectly aligned with the dark tactical aesthetic.

Rules

  • All icons are line / stroke style — never filled glyphs (with one exception: the calendar's red due-date dot is a filled circle, but it's a status indicator, not an icon).
  • Stroke width: 1.52px (lucide default). 1.5px on small icons (≤16px), 2px on larger icons.
  • Sizes: 14px (inline with text), 16px (default UI), 20px (nav items, prominent buttons), 24px (page-header icons).
  • Colour: inherits currentColor — text-foreground for default, #38BDF8 for active / accent, severity colours when used as a status indicator.
  • No emoji anywhere. Status, severity, and category use icons + colour; never 🔴 or ⚠️.
  • No unicode-as-icon shortcuts beyond (status dot), (revert / cycle), (redirect), (filter handle), (inline link), +N (count badge). These are part of the typography, not stand-ins for missing icons.

Brand mark

The product has no published logo file in the repo (the audit references AtlasIcon as a custom SVG brand icon — Atlas appears to be the action-plan integration, not the dashboard's own brand). For this design system the brand mark is a typographic stack: STEAM in Outfit 700 with a sky-blue underline accent and a small shield glyph (lucide Shield) to the left. See assets/logo.svg and assets/atlas-shield.svg.

Substitutions flagged

  • Atlas action-plan brand icon is recreated as a generic shield (lucide Shield) tinted sky-blue. If you have the real AtlasIcon SVG, please attach it — the in-product version is custom and not available from the repo URL.
  • Fonts (Outfit, JetBrains Mono) load from Google Fonts CDN. If you need offline font files, attach the woff2s and we'll bundle them into fonts/.

Icons used per page (from README)

  • Home: Calendar (CalendarWidget), Search, Filter, Plus, Upload, Edit, Trash, X (close)
  • Reporting: RefreshCw (Sync), Eye / EyeOff (row visibility), Check, Filter (⊙ in column header), Columns, Download (Export), MoreHorizontal
  • Compliance: Upload, AlertTriangle (drift breaking), AlertCircle (drift silent-miss), Info, ChevronRight, FileText
  • Knowledge Base: FileText, FilePlus, Folder, Download, Eye
  • Admin: Users, ScrollText (audit log), Activity (system info), Shield (admin badge)
  • Universal: ChevronDown, ChevronUp, Check, X, Loader, ExternalLink

When picking an icon, prefer the lucide-react name from this list before introducing a new one.


UI Kits

Kit Path What it covers
cve-dashboard ui_kits/cve-dashboard/ App shell (top bar, nav drawer, user menu), Knowledge Base page + viewer, primitives (Button, Badge, Pill, Input, Select, Modal shell, SlideOutPanel, DataTable, GroupBadge, SeverityBadge, EmptyState, LoadingState)

The Knowledge Base page is the focused recreation. Other surfaces (Reporting, Compliance, Admin) are intentionally not built out — the primitives + shell are sufficient to compose them.


How to use this system

  1. Tokens first. Import colors_and_type.css into the root of any HTML file. All colour, type, radius, shadow, and spacing decisions should pull from these CSS custom properties.
  2. Pick a primitive before inventing. Severity badges, group badges, status pills, table row, modal shell, slide-out panel — they all live in ui_kits/cve-dashboard/.
  3. Match the density. When in doubt, tighter is more on-brand than airier.
  4. Lucide for icons. Use the lucide-react CDN or copy individual SVGs from the lucide site. Do not draw your own.
  5. No emoji, no gradients, no illustration, no marketing copy. The product is a console.