refactor: UI consistency — shared CSS, design system colors, no inline styles
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m22s
CI / docker (push) Successful in 1m9s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 36s

Phase 1: Extract 6 shared CSS modules (table-section, log-panel,
rate-colors, refresh-indicator, chart-card, section-card) eliminating
~135 duplicate class definitions across 11 files.

Phase 2: Replace all hardcoded hex colors in CSS modules with design
system variables. Strip ~55 hex fallbacks from var() patterns. Fix 4
undefined variable names (--accent, --bg-base, --surface, --bg-surface-raised).

Phase 3: Replace ~45 hardcoded hex values in ProcessDiagram SVG
components with var() CSS custom properties. Fix Dashboard.tsx color prop.

Phase 4: Create CSS modules for AdminLayout, DatabaseAdminPage,
OidcCallback (previously 100% inline). Extract shared PageLoader
component (replaces 3 copy-pasted spinner patterns). Move AppsTab
static inline styles to CSS classes. Extract LayoutShell StarredList styles.

58 files changed, net -219 lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-09 14:55:54 +02:00
parent bfed8174ca
commit ff62a34d89
58 changed files with 770 additions and 989 deletions

View File

@@ -61,23 +61,27 @@ export function DiagramNode({
const isSkipped = overlayActive && !executionState;
// Colors based on execution state (heatmap takes priority when no execution overlay)
let cardFill = isHovered ? '#F5F0EA' : 'white';
let borderStroke = isHovered || isSelected ? color : '#E4DFD8';
let cardFill = isHovered ? 'var(--bg-hover)' : 'var(--bg-surface)';
let borderStroke = isHovered || isSelected ? color : 'var(--border-subtle)';
let borderWidth = isHovered || isSelected ? 1.5 : 1;
let topBarColor = color;
let labelColor = '#1A1612';
let labelColor = 'var(--text-primary)';
if (isCompleted) {
cardFill = isHovered ? '#E4F5E6' : '#F0F9F1';
borderStroke = '#3D7C47';
cardFill = isHovered
? 'color-mix(in srgb, var(--success) 15%, var(--bg-surface))'
: 'color-mix(in srgb, var(--success) 10%, var(--bg-surface))';
borderStroke = 'var(--success)';
borderWidth = 1.5;
topBarColor = '#3D7C47';
topBarColor = 'var(--success)';
} else if (isFailed) {
cardFill = isHovered ? '#F9E4E1' : '#FDF2F0';
borderStroke = '#C0392B';
cardFill = isHovered
? 'color-mix(in srgb, var(--error) 15%, var(--bg-surface))'
: 'color-mix(in srgb, var(--error) 10%, var(--bg-surface))';
borderStroke = 'var(--error)';
borderWidth = 2;
topBarColor = '#C0392B';
labelColor = '#C0392B';
topBarColor = 'var(--error)';
labelColor = 'var(--error)';
} else if (heatmapEntry && !overlayActive) {
cardFill = heatmapColor(heatmapEntry.pctOfRoute);
borderStroke = heatmapBorderColor(heatmapEntry.pctOfRoute);
@@ -85,7 +89,7 @@ export function DiagramNode({
topBarColor = heatmapBorderColor(heatmapEntry.pctOfRoute);
}
const statusColor = isCompleted ? '#3D7C47' : isFailed ? '#C0392B' : undefined;
const statusColor = isCompleted ? 'var(--success)' : isFailed ? 'var(--error)' : undefined;
return (
<g
@@ -107,7 +111,7 @@ export function DiagramNode({
height={h + 4}
rx={CORNER_RADIUS + 2}
fill="none"
stroke="#C6820E"
stroke="var(--amber)"
strokeWidth={2.5}
/>
)}
@@ -150,11 +154,11 @@ export function DiagramNode({
{typeName}
</text>
{detail && detail !== typeName && (
<text x={TEXT_LEFT} y={TOP_BAR_HEIGHT + 24} fill={isFailed ? '#C0392B' : '#5C5347'} fontSize={10}>
<text x={TEXT_LEFT} y={TOP_BAR_HEIGHT + 24} fill={isFailed ? 'var(--error)' : 'var(--text-secondary)'} fontSize={10}>
{detail}
</text>
)}
<text x={TEXT_LEFT} y={TOP_BAR_HEIGHT + (detail && detail !== typeName ? 35 : 24)} fill="#1A7F8E" fontSize={9} fontStyle="italic">
<text x={TEXT_LEFT} y={TOP_BAR_HEIGHT + (detail && detail !== typeName ? 35 : 24)} fill="var(--running)" fontSize={9} fontStyle="italic">
{resolvedUri.split('?')[0]}
</text>
</>
@@ -164,7 +168,7 @@ export function DiagramNode({
{typeName}
</text>
{detail && detail !== typeName && (
<text x={TEXT_LEFT} y={h / 2 + 12} fill={isFailed ? '#C0392B' : '#5C5347'} fontSize={10}>
<text x={TEXT_LEFT} y={h / 2 + 12} fill={isFailed ? 'var(--error)' : 'var(--text-secondary)'} fontSize={10}>
{detail}
</text>
)}
@@ -189,24 +193,24 @@ export function DiagramNode({
if (isCompleted) {
badges.push(
<g key="status">
<circle cx={statusCx} cy={cy} r={BADGE_R} fill="#3D7C47" />
<path d={`M${statusCx - 3} ${cy} l2 2 4-4`} fill="none" stroke="white" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
<circle cx={statusCx} cy={cy} r={BADGE_R} fill="var(--success)" />
<path d={`M${statusCx - 3} ${cy} l2 2 4-4`} fill="none" stroke="var(--text-inverse)" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
</g>
);
slot++;
} else if (isFailed) {
badges.push(
<g key="status">
<circle cx={statusCx} cy={cy} r={BADGE_R} fill="none" stroke="#C0392B" strokeWidth={2} opacity={0.5}>
<circle cx={statusCx} cy={cy} r={BADGE_R} fill="none" stroke="var(--error)" strokeWidth={2} opacity={0.5}>
<animate attributeName="r" values="6;14" dur="1.5s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.5;0" dur="1.5s" repeatCount="indefinite" />
</circle>
<circle cx={statusCx} cy={cy} r={BADGE_R} fill="none" stroke="#C0392B" strokeWidth={2} opacity={0.5}>
<circle cx={statusCx} cy={cy} r={BADGE_R} fill="none" stroke="var(--error)" strokeWidth={2} opacity={0.5}>
<animate attributeName="r" values="6;14" dur="1.5s" begin="0.75s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.5;0" dur="1.5s" begin="0.75s" repeatCount="indefinite" />
</circle>
<circle cx={statusCx} cy={cy} r={BADGE_R} fill="#C0392B" />
<path d={`M${statusCx} ${cy - 3} v4 M${statusCx} ${cy + 2.5} v0.5`} fill="none" stroke="white" strokeWidth={1.5} strokeLinecap="round" />
<circle cx={statusCx} cy={cy} r={BADGE_R} fill="var(--error)" />
<path d={`M${statusCx} ${cy - 3} v4 M${statusCx} ${cy + 2.5} v0.5`} fill="none" stroke="var(--text-inverse)" strokeWidth={1.5} strokeLinecap="round" />
</g>
);
slot++;
@@ -217,8 +221,8 @@ export function DiagramNode({
const tapCx = statusCx - slot * (BADGE_D + BADGE_GAP);
badges.push(
<g key="tap">
<circle cx={tapCx} cy={cy} r={BADGE_R} fill="#7C3AED" />
<g transform={`translate(${tapCx - 5}, ${cy - 5})`} stroke="white" strokeWidth={1.4} fill="none" strokeLinecap="round" strokeLinejoin="round">
<circle cx={tapCx} cy={cy} r={BADGE_R} fill="var(--purple)" />
<g transform={`translate(${tapCx - 5}, ${cy - 5})`} stroke="var(--text-inverse)" strokeWidth={1.4} fill="none" strokeLinecap="round" strokeLinejoin="round">
<path d="M5 1 C5 1 2 4.5 2 6.5a3 3 0 006 0C8 4.5 5 1 5 1z" />
</g>
</g>
@@ -235,18 +239,18 @@ export function DiagramNode({
<g key="trace">
{tracePulse && (
<>
<circle cx={traceCx} cy={cy} r={BADGE_R} fill="none" stroke="#1A7F8E" strokeWidth={2} opacity={0.5}>
<circle cx={traceCx} cy={cy} r={BADGE_R} fill="none" stroke="var(--running)" strokeWidth={2} opacity={0.5}>
<animate attributeName="r" values={`${BADGE_R};${BADGE_R + 8}`} dur="1.5s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.5;0" dur="1.5s" repeatCount="indefinite" />
</circle>
<circle cx={traceCx} cy={cy} r={BADGE_R} fill="none" stroke="#1A7F8E" strokeWidth={2} opacity={0.5}>
<circle cx={traceCx} cy={cy} r={BADGE_R} fill="none" stroke="var(--running)" strokeWidth={2} opacity={0.5}>
<animate attributeName="r" values={`${BADGE_R};${BADGE_R + 8}`} dur="1.5s" begin="0.75s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.5;0" dur="1.5s" begin="0.75s" repeatCount="indefinite" />
</circle>
</>
)}
<circle cx={traceCx} cy={cy} r={BADGE_R} fill={traceHasData ? '#1A7F8E' : '#1A7F8E'} opacity={traceHasData ? 1 : 0.2} />
<g transform={`translate(${traceCx - 5}, ${cy - 5}) scale(${10/24})`} stroke={traceHasData ? 'white' : '#1A7F8E'} strokeWidth={2.4} fill="none" strokeLinecap="round" strokeLinejoin="round">
<circle cx={traceCx} cy={cy} r={BADGE_R} fill="var(--running)" opacity={traceHasData ? 1 : 0.2} />
<g transform={`translate(${traceCx - 5}, ${cy - 5}) scale(${10/24})`} stroke={traceHasData ? 'var(--text-inverse)' : 'var(--running)'} strokeWidth={2.4} fill="none" strokeLinecap="round" strokeLinejoin="round">
<path d="M4 16v-2.38C4 11.5 2.97 10.5 3 8c.03-2.72 1.49-6 4.5-6C9.37 2 10 3.8 10 5.5c0 3.11-2 5.66-2 8.68V16a2 2 0 1 1-4 0Z" />
<path d="M20 20v-2.38c0-2.12 1.03-3.12 1-5.62-.03-2.72-1.49-6-4.5-6C14.63 6 14 7.8 14 9.5c0 3.11 2 5.66 2 8.68V20a2 2 0 1 0 4 0Z" />
<path d="M16 17h4" />
@@ -292,9 +296,9 @@ export function DiagramNode({
<g transform={`translate(4, ${h - 14})`}>
<path
d="M2 2 v5 a3 3 0 003 3 h5"
fill="none" stroke="#C0392B" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round"
fill="none" stroke="var(--error)" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round"
/>
<path d="M8 8 l2 2 -2 2" fill="none" stroke="#C0392B" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
<path d="M8 8 l2 2 -2 2" fill="none" stroke="var(--error)" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
</g>
)}
</g>