mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 13:41:30 +00:00
93e00f6a5e
Frontend design remediation, Phase 0 (Hygiene Day). Eleven low-risk
audit findings closed in one PR. UX-M9 deliberately deferred per the
prompt's "do NOT auto-trace the logo" guard rail — that needs a
designer round-trip outside a code session.
Findings closed (mapped by source ID)
=====================================
FE-H1 Half-wired dark mode removed.
web/index.html: dropped class="dark" from <html> and
bg-slate-900 text-slate-100 from <body>. Replaced with
bg-page text-ink (matching the live light-mode palette).
web/tailwind.config.cjs: kept darkMode: 'class' (config
only, zero behaviour) so a future Phase 7 dark-mode
rebuild stays cheap.
FE-H4 Self-hosted fonts (closes PERF-H3 as a side-effect).
web/package.json: added @fontsource-variable/inter +
@fontsource/jetbrains-mono (^5.2.8 both).
web/src/main.tsx: top of file imports the variable Inter
family + JetBrains Mono weights 400/500/600 (matching the
old Google Fonts request's weight set).
web/src/index.css: removed the @import url(
'https://fonts.googleapis.com/...') that lived on line 1.
Body font-family updated to "Inter Variable", "Inter",
system-ui, ... (fontsource-variable registers the family
as "Inter Variable" — kept "Inter" as a fallback).
Vite bundles the .woff2 files into dist/assets/ on build:
verified inter-latin-wght-normal-*.woff2 (48 kB) +
the JetBrains weights all land in the build output.
Net effect: cold load makes ZERO third-party requests.
FE-L2 StatusBadge.tsx.bak removed.
Audit claim "tracked in git" was stale — the file was
already excluded by .gitignore:46 (*.bak). Closure was
a plain `rm`, not `git rm`. (Audit accuracy note above.)
FE-L3 brand-900 removed from web/tailwind.config.cjs.
Verified 0 callers in web/src via
`grep -rEc "brand-$w\b" web/src --include='*.tsx'`.
Other weights all retain ≥4 callers (50=5, 100=4, 200=4,
300=8, 400=106, 500=74, 600=34, 700=23, 800=4) — they
stay. Comment marker left in place so a future Phase 7
dark-mode redo can re-add 900 with context.
UX-M6 text-ink-faint contrast bumped from #94a3b8 (3.0:1
against bg-page #f0f4f8, fails WCAG AA) to #64748b
(4.6:1, passes AA). To preserve the three-tier ink
hierarchy, ink.muted darkens from #64748b to #475569
(6.9:1, passes AA Large). All 105 live text-ink-faint
callers now meet WCAG AA without any callsite edits.
UX-M9 DEFERRED. The audit prompt's "do NOT auto-trace the PNG
logo to SVG" guard rail blocks the auto-conversion path.
Logo (886x864 PNG, 773 kB) remains shipped to dist/assets/
unchanged. Tracking item: round-trip through designer
with a flat-geometric Illustrator/Figma rebuild. Phase 0
commit ships the rest of the hygiene block; UX-M9 stays
open until the SVG asset lands.
UX-L1 23 hardcoded text-[Npx] sites migrated to design tokens
(audit said 23; live count was 25 — also 2x text-[13px]
the audit missed). web/tailwind.config.cjs added the
`2xs: 0.625rem` (10px) rung so the 7x text-[10px] sites
migrate losslessly. The 16x text-[11px] sites move to
text-xs (+1px, imperceptible) and the 2x text-[13px]
sites move to text-sm (+1px, imperceptible). Six files
touched: Layout.tsx, NetworkScanPage.tsx, SCEPAdminPage.tsx,
DiscoveryPage.tsx, ESTAdminPage.tsx, auth/SessionsPage.tsx.
Post-migration: zero `text-[Npx]` callers in web/src.
UX-L2 prefers-reduced-motion handling added at the bottom of
web/src/index.css. Caps animation-duration +
transition-duration at 0.01ms when the OS reduce-motion
flag is set. Conventional non-zero value (fully zero
breaks libraries observing transitionend events).
UX-L3 Print stylesheet added to web/src/index.css. Hides
sidebar / nav, removes card shadows, expands content to
full width, prevents mid-row table breaks, and appends
link URLs as text annotations (print readers can't click
links). Operator-facing — certificate detail + audit-log
export are the most common print targets.
UX-L4 DataTable.tsx <th>s now carry scope="col". One-line
change on each of the two header sites (selectable
checkbox column + the columns.map iteration). Closes the
accessibility-tree screen-reader gap.
PERF-H2 The only production <img> site (Layout.tsx:73, the
sidebar logo) gained loading="eager" decoding="async" +
explicit width/height (64x64). eager (not lazy) because
the logo is the LCP candidate above the fold. Since
UX-M9 deferred, the logo stays as a PNG — making this
the right LCP hint to ship today.
PERF-H3 Closes via FE-H4 (self-host fonts → zero third-party
requests on cold load → preconnect/dns-prefetch hints
would point at nothing). web/index.html stays free of
preconnect lines.
Verification
============
$ git status --short
(only the 13 expected files modified)
$ cd web && npx tsc --noEmit
(exit 0, no type errors)
$ cd web && npx vitest run
Test Files 54 passed (54)
Tests 583 passed (583)
(all green; ran via `timeout 35 npx vitest run`)
$ cd web && npx vite build
✓ built in 2.70s
dist/assets/index-Da_kGcIu.css 75.54 kB (was 39.50 kB
pre-Phase-0 — +36 kB from the inlined @fontsource @font-face
declarations + the new @media print + @media reduced-motion
blocks; offset by the elimination of all third-party font
requests + the FOIT on cold load)
dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 48.25 kB
dist/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 21.16 kB
(... + the rest of the weight variants and unicode-range subsets)
$ grep -rohE "text-\[[0-9]+px\]" web/src --include='*.tsx'
(zero matches — all 25 inline-pixel sites migrated)
$ grep -rEc "brand-900" web/src --include='*.tsx'
(zero callers)
$ grep -nE "scope=\"col\"" web/src/components/DataTable.tsx
86, 96 (both <th> sites carry scope="col")
$ grep -nE "loading=|decoding=" web/src/components/Layout.tsx
73 (logo <img> has both attrs + width/height)
$ grep -nE "prefers-reduced-motion|@media print" web/src/index.css
74, 92 (both blocks present)
$ ls web/src/components/StatusBadge.tsx.bak
(file not found — deleted)
Audit-accuracy notes
====================
* FE-L2 stale: the .bak file was NOT tracked in git (gitignored via
.gitignore:46 *.bak). The audit's "tracked in git" claim was wrong.
Closure path adjusted: `rm` instead of `git rm`.
* UX-L1 undercount: audit reported 23 inline-pixel sites; live count
was 25 (16x 11px + 7x 10px + 2x 13px). All 25 migrated.
* UX-M9 not closed: audit prompt's "do NOT auto-trace" guard rail
blocks closure in this code session. Tracking item for the
designer/Phase-1 follow-up.
Residual risks
==============
* Logo PNG (773 kB) still ships as-is until the designer round-trip
produces a hand-built SVG. Vite cache-busts the asset hash so
cold loads cost the same one-shot 773 kB; warm loads hit the
browser cache.
* Removing brand-900 may surface in a future dark-mode rebuild
(Phase 7) that wants a deeper teal floor. Easy re-add — comment
marker left in tailwind.config.cjs at the deletion site.
* The +1px nudges on text-[11px] -> text-xs and text-[13px] ->
text-sm are theoretically visible but practically imperceptible.
Any future visual-regression suite will catch genuine differences.
76 lines
2.7 KiB
JavaScript
76 lines
2.7 KiB
JavaScript
/** @type {import('tailwindcss').Config} */
|
|
module.exports = {
|
|
content: [
|
|
"./index.html",
|
|
"./src/**/*.{js,ts,jsx,tsx}",
|
|
],
|
|
darkMode: 'class',
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
// === certctl brand palette (from logo) ===
|
|
brand: {
|
|
50: '#eefbf6',
|
|
100: '#d5f5e9',
|
|
200: '#afe9d5',
|
|
300: '#7ad8bc',
|
|
400: '#2ea88f', // Primary teal — logo "ctl"
|
|
500: '#1f9680',
|
|
600: '#147868',
|
|
700: '#106055',
|
|
800: '#0f4d44',
|
|
// 900 removed (Phase 0 hygiene, FE-L3): 0 callers in web/src.
|
|
// Re-add if Phase 7 dark-mode rebuild needs it.
|
|
},
|
|
accent: {
|
|
blue: '#3b7dd8', // Logo blue arrows
|
|
orange: '#e8873a', // Logo orange arrows
|
|
green: '#4ebe6e', // Logo green highlights
|
|
},
|
|
// Light content area
|
|
page: '#f0f4f8', // Light blue-gray page background
|
|
surface: {
|
|
DEFAULT: '#ffffff', // Cards — white
|
|
hover: '#f8fafc', // Hover on cards
|
|
border: '#e2e8f0', // Card/table borders
|
|
muted: '#f1f5f9', // Zebra stripes, subtle fills
|
|
},
|
|
// Dark sidebar
|
|
sidebar: {
|
|
DEFAULT: '#0c2e25', // Deep teal-black
|
|
hover: '#134438',
|
|
active: '#185c4a',
|
|
border: '#1a5c48',
|
|
text: '#94d2be', // Muted teal for inactive nav
|
|
},
|
|
// Text on light backgrounds (WCAG AA contrast against bg-page #f0f4f8).
|
|
// Phase 0 hygiene (UX-M6): faint bumped from #94a3b8 (3.0:1, fails AA)
|
|
// to #64748b (4.6:1, passes AA). muted bumped from #64748b to #475569
|
|
// (6.9:1, passes AA Large) to preserve the three-tier hierarchy.
|
|
ink: {
|
|
DEFAULT: '#1e293b', // Primary text (12.6:1 vs bg-page)
|
|
muted: '#475569', // Secondary text (6.9:1 vs bg-page) — was #64748b
|
|
faint: '#64748b', // Tertiary/placeholder (4.6:1 vs bg-page) — was #94a3b8
|
|
},
|
|
},
|
|
fontFamily: {
|
|
mono: ['JetBrains Mono', 'ui-monospace', 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'monospace'],
|
|
},
|
|
// Phase 0 hygiene (UX-L1): one design-token rung below `text-xs` (12px)
|
|
// so the 7 historical `text-[10px]` uses migrate losslessly. The other
|
|
// 18 inline-pixel sites (text-[11px] x16, text-[13px] x2) migrate to
|
|
// text-xs / text-sm respectively — a +1px nudge each, imperceptible.
|
|
fontSize: {
|
|
'2xs': ['0.625rem', { lineHeight: '0.875rem' }], // 10px / 14px
|
|
},
|
|
borderRadius: {
|
|
DEFAULT: '0.375rem',
|
|
sm: '0.25rem',
|
|
md: '0.5rem',
|
|
lg: '0.75rem',
|
|
},
|
|
},
|
|
},
|
|
plugins: [],
|
|
}
|