Files
cve-dashboard/docs/design-system-redesign/ui_kits/home/KitDocs.jsx

444 lines
23 KiB
React
Raw Normal View History

// KitDocs.jsx — browseable docs page for the Home kit.
// Sections: Overview · Tokens · Components · Assemblies · Reference page.
const { useState: useDocsHomeState } = React;
const {
COLORS: DHC, StatCard: DStatCard, HomeCard: DHomeCard, CardTitle: DCardTitle,
HomeButton: DBtn, SeverityBadge: DSev, StatusBadge: DStatus,
HomeInput: DInput, HomeSelect: DSelect, FieldLabel: DLabel, ResultBanner: DBanner,
BigStat: DBigStat, MiniTicket: DMini, CVERow: DCVERow, VendorEntry: DVendor,
HomeIcon: DIcon, CalendarMini: DCal, ArchiveSummary: DArchive, ScrollList: DScroll,
EmptyState: DEmpty, withAlpha: dAlpha,
} = window.HOME;
const { HomePage: DHomePage } = window.HOME_PAGE;
/* ── Layout primitives (same vocabulary as the Reporting kit docs) ── */
function HSection({ id, eyebrow, title, blurb, children }) {
return (
<section id={id} style={{ paddingTop: 32, scrollMarginTop: 120 }}>
<div style={{ marginBottom: 16 }}>
{eyebrow && (
<div style={{
fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 700,
color: DHC.sky, textTransform: 'uppercase', letterSpacing: '0.18em',
marginBottom: 6,
}}>{eyebrow}</div>
)}
<h2 style={{
fontFamily: 'var(--font-mono)', fontSize: 22, fontWeight: 700,
color: 'var(--fg-1)', margin: 0, letterSpacing: '0.02em',
}}>{title}</h2>
{blurb && (
<p style={{
fontFamily: 'var(--font-display)', fontSize: 14, lineHeight: 1.6,
color: 'var(--fg-muted)', maxWidth: 660, margin: '8px 0 0 0',
}}>{blurb}</p>
)}
</div>
{children}
</section>
);
}
function HSpec({ label, children }) {
return (
<div style={{
display: 'grid', gridTemplateColumns: '160px 1fr', gap: 16,
padding: '10px 0', borderBottom: '1px solid rgba(255,255,255,0.04)',
fontFamily: 'var(--font-mono)', fontSize: 12,
}}>
<div style={{ color: 'var(--fg-disabled)', textTransform: 'uppercase', letterSpacing: '0.06em', fontSize: 10, fontWeight: 600 }}>{label}</div>
<div style={{ color: 'var(--fg-2)' }}>{children}</div>
</div>
);
}
function HCode({ children }) {
return (
<code style={{
display: 'inline-block', padding: '2px 6px', borderRadius: 3,
background: 'rgba(14,165,233,0.10)', border: '1px solid rgba(14,165,233,0.18)',
fontFamily: 'var(--font-mono)', fontSize: 11, color: DHC.skySoft,
}}>{children}</code>
);
}
function HSwatch({ name, value, role }) {
return (
<div style={{
display: 'grid', gridTemplateColumns: '52px 1fr auto', alignItems: 'center', gap: 14,
padding: '8px 0', borderBottom: '1px solid rgba(255,255,255,0.04)',
}}>
<div style={{ height: 36, borderRadius: 6, background: value, border: '1px solid rgba(255,255,255,0.08)' }} />
<div>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-1)', fontWeight: 600 }}>{name}</div>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-disabled)' }}>{role}</div>
</div>
<HCode>{value}</HCode>
</div>
);
}
function HSpecimen({ children, padding = 24, dark = true, style }) {
return (
<div style={{
padding,
background: dark ? 'rgba(15,23,42,0.5)' : 'transparent',
border: '1px solid rgba(255,255,255,0.05)', borderRadius: 8,
...style,
}}>{children}</div>
);
}
/* ── Sticky tab strip ─────────────────────────────────────────── */
const TABS = [
{ id: 'overview', label: 'Overview' },
{ id: 'tokens', label: 'Tokens' },
{ id: 'components', label: 'Components' },
{ id: 'assemblies', label: 'Assemblies' },
{ id: 'reference', label: 'Reference Page' },
];
function HKitDocs() {
const [active, setActive] = useDocsHomeState('overview');
const handle = (id) => {
setActive(id);
const el = document.getElementById(id);
if (el) {
const top = el.getBoundingClientRect().top + window.scrollY - 80;
window.scrollTo({ top, behavior: 'smooth' });
}
};
return (
<div style={{ minHeight: '100vh', background: 'var(--bg-page)' }}>
{/* Header */}
<header style={{
padding: '40px 48px 0 48px', maxWidth: 1280, margin: '0 auto',
}}>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700, color: DHC.sky, textTransform: 'uppercase', letterSpacing: '0.18em', marginBottom: 8 }}>
STEAM Security · UI Kit
</div>
<h1 style={{
margin: 0, fontFamily: 'var(--font-mono)', fontSize: 36, fontWeight: 700,
color: DHC.green, textTransform: 'uppercase', letterSpacing: '0.08em',
textShadow: '0 0 24px rgba(16,185,129,0.30)',
}}>
Home
</h1>
<p style={{
margin: '12px 0 0 0', maxWidth: 720, fontSize: 15, lineHeight: 1.6,
color: 'var(--fg-muted)', fontFamily: 'var(--font-display)',
}}>
The "command center" landing view of the CVE Dashboard. Pulls four signals into one screen:
a top metric strip, a CVE feed with vendor sub-rows, and a right-rail stack of
Calendar · JIRA · Archer · Ivanti. Built from the same chrome and tokens as the Reporting kit.
</p>
</header>
{/* Tab strip */}
<nav style={{
position: 'sticky', top: 0, zIndex: 10,
marginTop: 28,
background: 'rgba(2,6,23,0.85)', backdropFilter: 'blur(8px)',
borderBottom: '1px solid rgba(14,165,233,0.15)',
}}>
<div style={{ maxWidth: 1280, margin: '0 auto', padding: '0 48px', display: 'flex', gap: 4 }}>
{TABS.map(t => {
const on = active === t.id;
return (
<button key={t.id} onClick={() => handle(t.id)} style={{
padding: '14px 16px',
background: 'transparent', border: 'none',
borderBottom: `2px solid ${on ? DHC.sky : 'transparent'}`,
color: on ? DHC.sky : 'var(--fg-2)',
fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 600,
textTransform: 'uppercase', letterSpacing: '0.08em',
cursor: 'pointer', transition: 'all 160ms ease',
}}>{t.label}</button>
);
})}
</div>
</nav>
{/* Body */}
<main style={{ maxWidth: 1280, margin: '0 auto', padding: '0 48px 96px 48px' }}>
{/* OVERVIEW */}
<HSection id="overview" eyebrow="01 — Overview" title="Why this kit exists" blurb="Documents the visual + behavioral vocabulary of the home view so other dashboards in the suite can re-use the right-rail stack, the CVE row pattern, and the four-up stat strip without re-deriving them.">
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
<HSpecimen>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: DHC.sky, textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 12, fontWeight: 600 }}>Identity</div>
<p style={{ margin: 0, fontSize: 13, color: 'var(--fg-1)', lineHeight: 1.6, fontFamily: 'var(--font-display)' }}>
Green appears in exactly one place: the page title in the chrome. Sky is the workhorse borders,
section titles, neutral buttons. Amber, red, purple, teal are reserved for specific data domains
(tickets, critical, Archer, Ivanti) and never used decoratively.
</p>
</HSpecimen>
<HSpecimen>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: DHC.sky, textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 12, fontWeight: 600 }}>Layout</div>
<p style={{ margin: 0, fontSize: 13, color: 'var(--fg-1)', lineHeight: 1.6, fontFamily: 'var(--font-display)' }}>
Top: 4-up stat strip. Body: 12-column grid, left 9 / right 3. Left holds the lookup filter CVE
feed flow. Right is a vertical stack of color-rail panels, each with a left-border identity color
and a centered big-number metric.
</p>
</HSpecimen>
</div>
</HSection>
{/* TOKENS */}
<HSection id="tokens" eyebrow="02 — Tokens" title="Color, type, and the right-rail palette" blurb="The four data domains on the home view each have an owned color used as: card left-rail border, card title color + glow, big-number value color, and badge tint.">
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 32 }}>
<div>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-disabled)', textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 8, fontWeight: 600 }}>Right-rail identity</div>
<HSwatch name="sky" value={DHC.sky} role="Calendar · neutral surfaces · default" />
<HSwatch name="amber" value={DHC.amber} role="Open Tickets · 'needs attention'" />
<HSwatch name="purple" value={DHC.purple} role="Archer Risk Tickets" />
<HSwatch name="teal" value={DHC.teal} role="Ivanti Workflows" />
</div>
<div>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-disabled)', textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 8, fontWeight: 600 }}>Severity / status</div>
<HSwatch name="green" value={DHC.green} role="Page identity glow · Low · success" />
<HSwatch name="red" value={DHC.red} role="Critical · destructive" />
<HSwatch name="amber" value={DHC.amber} role="High · in-progress" />
<HSwatch name="sky" value={DHC.sky} role="Medium · neutral status" />
</div>
</div>
<div style={{ marginTop: 32 }}>
<HSpec label="Card chrome">background <HCode>linear-gradient(135deg, rgba(30,41,59,.95) 0%, rgba(15,23,42,.98) 100%)</HCode></HSpec>
<HSpec label="Card border">resting <HCode>1.5px solid rgba(14,165,233,0.12)</HCode> · hover <HCode>0.35</HCode></HSpec>
<HSpec label="Card radius"><HCode>8px</HCode></HSpec>
<HSpec label="Title type"><HCode>var(--font-mono)</HCode> · 14 / 600 · uppercase · 0.1em tracking · 12px text-shadow glow in title color</HSpec>
<HSpec label="Big stat type"><HCode>var(--font-mono)</HCode> · 32 / 700 · 16px text-shadow glow at 0.4 alpha</HSpec>
<HSpec label="Stat label type"><HCode>var(--font-mono)</HCode> · 10 / 600 · uppercase · 0.12em tracking · fg-2</HSpec>
</div>
</HSection>
{/* COMPONENTS */}
<HSection id="components" eyebrow="03 — Components" title="The pieces" blurb="Every primitive used by the page assembly. All are exported on window.HOME so other pages in the dashboard can pull from the same vocabulary.">
{/* StatCard */}
<h3 style={subhead}>StatCard</h3>
<p style={subblurb}>Top-of-page metric tile. Color tone drives the 2px border, top-edge glow line, value color, and the inset highlight. Use <HCode>tone="neutral"</HCode> to suppress the colored treatment.</p>
<HSpecimen>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 12 }}>
<DStatCard label="Total CVEs" value="247" tone="sky" />
<DStatCard label="Vendor Entries" value="412" tone="neutral" />
<DStatCard label="Open Tickets" value="18" tone="amber" />
<DStatCard label="Critical" value="6" tone="red" />
</div>
</HSpecimen>
{/* Buttons */}
<h3 style={subhead}>HomeButton</h3>
<p style={subblurb}>Five variants. <strong style={{ color: DHC.green }}>Primary</strong> is reserved for the lone green CTA on each card. <strong style={{ color: DHC.sky }}>Neutral</strong> is the default for table-row + view actions. <strong style={{ color: DHC.amber }}>Warning</strong> = edit, <strong style={{ color: DHC.red }}>Danger</strong> = delete.</p>
<HSpecimen>
<div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
<DBtn variant="primary" icon="search">Scan</DBtn>
<DBtn variant="neutral" icon="eye">View</DBtn>
<DBtn variant="subtle" icon="download">Export</DBtn>
<DBtn variant="warning" icon="edit">Edit</DBtn>
<DBtn variant="danger" icon="trash">Delete</DBtn>
</div>
</HSpecimen>
{/* Badges */}
<h3 style={subhead}>SeverityBadge · StatusBadge</h3>
<p style={subblurb}>Severity is heavy: 2px solid border + glow + dot. Status is light: 1px border, smaller, used inside dense list cards.</p>
<HSpecimen>
<div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', marginBottom: 16 }}>
<DSev level="Critical" /><DSev level="High" /><DSev level="Medium" /><DSev level="Low" />
</div>
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
<DStatus tone="amber">In Progress</DStatus>
<DStatus tone="red">Open</DStatus>
<DStatus tone="green">Closed</DStatus>
<DStatus tone="purple">Pending Review</DStatus>
<DStatus tone="teal">Approved</DStatus>
</div>
</HSpecimen>
{/* Inputs */}
<h3 style={subhead}>HomeInput · HomeSelect · FieldLabel</h3>
<HSpecimen>
<div style={{ display: 'grid', gap: 16 }}>
<div>
<DLabel icon="search">Search CVEs</DLabel>
<DInput placeholder="CVE ID or description…" />
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
<div>
<DLabel icon="filter">Vendor</DLabel>
<DSelect value="All Vendors" onChange={() => {}} options={['All Vendors', 'Red Hat', 'Cisco', 'Ubuntu']} />
</div>
<div>
<DLabel icon="alert">Severity</DLabel>
<DSelect value="All Severities" onChange={() => {}} options={['All Severities', 'Critical', 'High', 'Medium', 'Low']} />
</div>
</div>
</div>
</HSpecimen>
{/* ResultBanner */}
<h3 style={subhead}>ResultBanner</h3>
<p style={subblurb}>Sub-card surfaced inside the Quick CVE Lookup card after a scan. Three tones map to the three terminal states.</p>
<HSpecimen>
<div style={{ display: 'grid', gap: 12 }}>
<DBanner tone="success" title="✓ CVE Addressed (3 vendors)">
<div style={{ fontFamily: 'var(--font-display)', fontSize: 12, color: 'var(--fg-2)' }}>
Red Hat (Open · 4 docs) · Ubuntu (In Progress · 2 docs) · SUSE (Resolved · 3 docs)
</div>
</DBanner>
<DBanner tone="warning" title="Not Found">
<div style={{ fontFamily: 'var(--font-display)', fontSize: 12, color: 'var(--fg-2)' }}>This CVE has not been addressed yet. No entry exists in the database.</div>
</DBanner>
<DBanner tone="error" title="Error">
<div style={{ fontFamily: 'var(--font-display)', fontSize: 12, color: 'var(--fg-2)' }}>NVD lookup failed: rate-limited (429). Retry in 30s.</div>
</DBanner>
</div>
</HSpecimen>
{/* BigStat */}
<h3 style={subhead}>BigStat</h3>
<p style={subblurb}>The centered "active count + label" shown at the top of every right-rail panel. Color follows panel identity.</p>
<HSpecimen>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 16 }}>
<DBigStat value="3" label="Active" color={DHC.amber} />
<DBigStat value="2" label="Active" color={DHC.purple} />
<DBigStat value="78" label="Total Workflows" color={DHC.teal} />
<DBigStat value="—" label="Never Synced" color={DHC.sky} />
</div>
</HSpecimen>
{/* MiniTicket */}
<h3 style={subhead}>MiniTicket</h3>
<p style={subblurb}>Compact card used inside right-rail scroll lists. Tone tints the border + status pill to match its parent panel's identity color.</p>
<HSpecimen>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 12 }}>
<DMini keyText="SEC-4821" cveId="CVE-2025-1014" vendor="Red Hat" status="In Progress" tone="amber" onEdit={() => {}} />
<DMini keyText="EXC-08291" cveId="CVE-2025-1014" vendor="SUSE" status="Pending Review" tone="purple" onEdit={() => {}} />
<DMini keyText="WF-1042" cveId="—" vendor="Compliance scan" status="In Review" tone="teal" />
</div>
</HSpecimen>
{/* Calendar */}
<h3 style={subhead}>CalendarMini</h3>
<p style={subblurb}>Right-rail calendar surface. Day cells accept a marker color so SLA / due-date dots can be projected onto the month.</p>
<HSpecimen>
<div style={{ maxWidth: 280 }}>
<DCal today={26} markedDays={{ 14: 'red', 18: 'amber', 22: 'sky', 24: 'amber' }} />
</div>
</HSpecimen>
{/* ArchiveSummary */}
<h3 style={subhead}>ArchiveSummary</h3>
<p style={subblurb}>State-pill bar that lives at the top of the Ivanti card. Each pill is a click target that filters the workflows below.</p>
<HSpecimen>
<div style={{ maxWidth: 320 }}>
<DArchive items={[
{ label: 'In Review', count: 12, tone: 'amber' },
{ label: 'In Progress', count: 8, tone: 'sky' },
{ label: 'Approved', count: 17, tone: 'green' },
{ label: 'Closed', count: 41, tone: 'neutral' },
]} activeFilter="In Review" />
</div>
</HSpecimen>
{/* CVERow + VendorEntry */}
<h3 style={subhead}>CVERow · VendorEntry</h3>
<p style={subblurb}>The collapsible CVE feed cards. Collapsed = chevron + ID + truncated description + meta row. Expanded = vendor sub-cards, optionally with a doc inset and a JIRA inset under each vendor.</p>
<HSpecimen padding={16}>
<DCVERow
cveId="CVE-2025-1014" severity="Critical"
description="Heap-based buffer overflow in libnetfilter_queue permits remote code execution via crafted ICMP traffic."
vendorCount={3} docCount={9} statuses={['Open', 'In Progress']}
expanded={true} onToggle={() => {}}
>
<DVendor vendor="Red Hat" severity="Critical" status="Open" docCount={4} onView={() => {}} />
<DVendor vendor="Ubuntu" severity="Critical" status="In Progress" docCount={2} onEdit={() => {}} />
</DCVERow>
</HSpecimen>
{/* EmptyState */}
<h3 style={subhead}>EmptyState</h3>
<HSpecimen>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: 16 }}>
<DEmpty>No open tickets</DEmpty>
<DEmpty icon="alert" tone="amber">Click Sync to load workflow data</DEmpty>
</div>
</HSpecimen>
</HSection>
{/* ASSEMBLIES */}
<HSection id="assemblies" eyebrow="04 — Assemblies" title="How the parts compose" blurb="Three patterns that other dashboards in the suite should reuse verbatim.">
<h3 style={subhead}>Right-rail panel</h3>
<p style={subblurb}>HomeCard with a colored left-rail + matching CardTitle + BigStat + ScrollList of MiniTickets. The identity color owns all four.</p>
<HSpecimen>
<div style={{ maxWidth: 320 }}>
<DHomeCard padding={20} leftRail={DHC.amber}>
<DCardTitle color={DHC.amber} icon="alert" action={<DBtn variant="warning" icon="plus" size="sm" />}>Open Tickets</DCardTitle>
<DBigStat value="3" label="Active" color={DHC.amber} />
<DScroll maxHeight={220}>
<DMini keyText="SEC-4821" cveId="CVE-2025-1014" vendor="Red Hat" status="In Progress" tone="amber" onEdit={() => {}} onDelete={() => {}} summary="Patch netfilter ingress" />
<DMini keyText="SEC-4794" cveId="CVE-2025-0944" vendor="Cisco" status="Open" tone="amber" onEdit={() => {}} summary="Roll admin-console hotfix" />
</DScroll>
</DHomeCard>
</div>
</HSpecimen>
<h3 style={subhead}>Quick lookup result banner</h3>
<HSpecimen>
<DHomeCard>
<DCardTitle color={DHC.sky} icon="search">Quick CVE Lookup</DCardTitle>
<div style={{ display: 'flex', gap: 12 }}>
<DInput placeholder="Enter CVE ID (e.g., CVE-2025-1014)" />
<DBtn variant="primary" icon="search">Scan</DBtn>
</div>
<div style={{ marginTop: 16 }}>
<DBanner tone="success" title="✓ CVE Addressed (3 vendors)">
<div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-2)' }}>Red Hat · Ubuntu · SUSE</div>
</DBanner>
</div>
</DHomeCard>
</HSpecimen>
<h3 style={subhead}>4-up stat strip</h3>
<HSpecimen>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 16 }}>
<DStatCard label="Total CVEs" value="247" tone="sky" />
<DStatCard label="Vendor Entries" value="412" tone="neutral" />
<DStatCard label="Open Tickets" value="18" tone="amber" />
<DStatCard label="Critical" value="6" tone="red" />
</div>
</HSpecimen>
</HSection>
{/* REFERENCE */}
<HSection id="reference" eyebrow="05 — Reference" title="Full Home page" blurb="Every primitive on this kit, composed exactly as App.js renders the home view. The frame below is a faithful reproduction — you can scroll inside it.">
<div className="sample-frame" style={{
border: '1px solid rgba(14,165,233,0.20)', borderRadius: 12,
overflow: 'hidden', maxHeight: 900, overflowY: 'auto',
background: 'var(--bg-page)',
}}>
<DHomePage />
</div>
</HSection>
</main>
</div>
);
}
const subhead = {
margin: '32px 0 6px 0',
fontFamily: 'var(--font-mono)', fontSize: 13, fontWeight: 700,
color: 'var(--fg-1)', textTransform: 'uppercase', letterSpacing: '0.08em',
};
const subblurb = {
margin: '0 0 12px 0',
fontFamily: 'var(--font-display)', fontSize: 13, lineHeight: 1.55,
color: 'var(--fg-muted)', maxWidth: 720,
};
window.HOME_DOCS = { HKitDocs };