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.
236 lines
18 KiB
Markdown
236 lines
18 KiB
Markdown
# 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 24–28px / 600 weight; section headers 16–18px / 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 16–20px internal padding; rows in dense tables have 8–10px vertical padding; modals have 24px internal padding.
|
||
- **Section gaps** are 24–32px. Between siblings, 12–16px 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:** 16–20px
|
||
- **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.30` → `0.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 recessed** — `inset 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.5–2px (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.
|