feat(frontend): sprint 4 — dark mode + matrix overhaul + tactic selection + done read-only + UI polish

US-17: fix duplicate "Create engagement" button, icon conventions (Save/RotateCcw/Grid2x2), UsersAdminPage form baseline alignment
US-18: done status fully read-only + Reopen button (done → review_required) for all roles
US-19: invalidate engagement queries on simulation PATCH/transition for auto-status propagation
US-20: MitreMatrixModal rewritten — CSS grid 12-column layout, no horizontal scroll, attack.mitre.org compact look
US-21: tactic header clickable in matrix, tactic chips (MitreTacticTag) in field, single atomic PATCH with technique_ids + tactic_ids
US-22: MitreTechniquesField chips-only area + inline search input + matrix icon button; chips show ID-only (name in title=)
US-23: useTheme hook — 3-state light/dark/system, CSS variables, Tailwind darkMode class, localStorage persistence

92/92 tests passing, typecheck and lint clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Knacky
2026-05-27 20:06:01 +02:00
parent d5ab1fd26f
commit f5ea9d16af
21 changed files with 721 additions and 337 deletions

View File

@@ -5,6 +5,41 @@
@tailwind utilities;
@layer base {
/* Light mode — default */
:root {
--color-canvas: #ffffff;
--color-paper: #ffffff;
--color-cloud: #f7f7f7;
--color-fog: #e8e8e8;
--color-steel: #c2c2c2;
--color-hairline: #e8e8e8;
--color-ink: #1a1a1a;
--color-ink-soft: #292929;
--color-ink-deep: #000000;
--color-ink-on: #ffffff;
--color-charcoal: #3d3d3d;
--color-graphite: #636363;
/* DESIGN.md: body line-height 1.4 when substituting Inter */
font-size: 16.5px;
}
/* Dark mode overrides */
.dark {
--color-canvas: #111827;
--color-paper: #1f2937;
--color-cloud: #1f2937;
--color-fog: #374151;
--color-steel: #4b5563;
--color-hairline: #374151;
--color-ink: #f9fafb;
--color-ink-soft: #e5e7eb;
--color-ink-deep: #ffffff;
--color-ink-on: #111827;
--color-charcoal: #d1d5db;
--color-graphite: #9ca3af;
}
html,
body,
#root {
@@ -13,15 +48,9 @@
body {
@apply bg-canvas text-ink font-sans antialiased;
/* DESIGN.md: body line-height 1.4 when substituting Inter */
font-feature-settings: 'cv11', 'ss01';
}
/* Compensate for Inter being slightly narrower than Forma DJR Micro (~3%) */
:root {
font-size: 16.5px;
}
h1,
h2,
h3,
@@ -39,7 +68,7 @@
* Buttons stay sharp (rounded-md = 4px); cards stay soft (rounded-xl = 16px).
*/
.btn-primary {
@apply inline-flex items-center justify-center bg-primary text-ink-on uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors;
@apply inline-flex items-center justify-center gap-xs bg-primary text-white uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors;
}
.btn-primary:hover {
@apply bg-primary-deep;
@@ -49,7 +78,7 @@
}
.btn-ink {
@apply inline-flex items-center justify-center bg-ink text-ink-on uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors;
@apply inline-flex items-center justify-center gap-xs bg-ink text-white uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors;
}
.btn-ink:hover {
@apply bg-ink-soft;
@@ -59,21 +88,24 @@
}
.btn-outline {
@apply inline-flex items-center justify-center bg-canvas text-primary border border-primary uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors;
@apply inline-flex items-center justify-center gap-xs bg-canvas text-primary border border-primary uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors;
}
.btn-outline:hover {
@apply bg-primary-soft;
}
.btn-outline:disabled {
@apply border-steel text-steel cursor-not-allowed;
}
.btn-outline-ink {
@apply inline-flex items-center justify-center bg-canvas text-ink border border-ink uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors;
@apply inline-flex items-center justify-center gap-xs bg-canvas text-ink border border-ink uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors;
}
.btn-outline-ink:hover {
@apply bg-cloud;
}
.btn-text-link {
@apply inline-flex items-center text-primary font-medium text-[16px] leading-[1.38] underline-offset-2 hover:underline;
@apply inline-flex items-center gap-xxs text-primary font-medium text-[16px] leading-[1.38] underline-offset-2 hover:underline;
}
.text-input {
@@ -85,7 +117,7 @@
}
.badge-pill-ink {
@apply inline-flex items-center bg-ink text-ink-on rounded-lg px-3 py-[6px] text-[14px] leading-[1.3] font-medium;
@apply inline-flex items-center bg-ink text-white rounded-lg px-3 py-[6px] text-[14px] leading-[1.3] font-medium;
}
.badge-pill-outline {