From 13e8d3366bca3c3fa500ee60b15a02fc2ad5d599 Mon Sep 17 00:00:00 2001 From: TELVIN TEUM Date: Sat, 18 Jul 2026 10:05:44 +0300 Subject: [PATCH] Switch UI palette to dark mode defaults Reworks the frontend color system to a dark-first theme by updating Tailwind tokens (`canvas`, `surface`, `primary`, `charcoal`, `steel`, etc.) and propagating the new palette across key UI surfaces. This includes global base styles (`color-scheme`, selection, ring offset), dark Monaco/editor and xterm log viewer themes, chart/tooltip color updates, toast theming, and contrast fixes for brand/toolchain logos on black backgrounds. --- public/index.html | 2 +- src/app/providers.tsx | 2 +- .../brand/toolchains/ToolchainLogo.tsx | 10 +++++-- src/components/ui/Button.tsx | 4 +-- .../auth/components/ParticleField.tsx | 6 ++-- .../dashboard/components/ActivityChart.tsx | 24 +++++++++------ .../dashboard/components/SuccessRateChart.tsx | 22 +++++++++----- .../pipelines/components/LogViewer.tsx | 22 +++++++------- .../components/panels/PerformancePanel.tsx | 30 +++++++++++-------- .../workflows/components/WorkflowEditor.tsx | 30 +++++++++---------- src/index.css | 15 ++++++++++ tailwind.config.js | 18 +++++------ 12 files changed, 110 insertions(+), 75 deletions(-) diff --git a/public/index.html b/public/index.html index 42f46e7..c32d4e1 100644 --- a/public/index.html +++ b/public/index.html @@ -4,7 +4,7 @@ - + {children} - + ); diff --git a/src/components/brand/toolchains/ToolchainLogo.tsx b/src/components/brand/toolchains/ToolchainLogo.tsx index 3ad6ef5..0a082a6 100644 --- a/src/components/brand/toolchains/ToolchainLogo.tsx +++ b/src/components/brand/toolchains/ToolchainLogo.tsx @@ -15,7 +15,9 @@ interface BrandMark { const LOGOS: Record = { rust: { - color: '#000000', + // Rust's mark is officially black; on the black canvas we use the light + // foreground so it stays visible (same treatment GitHub gets below). + color: '#e8e6e3', title: 'Rust', path: 'M23.8346 11.7033l-1.0073-.6236a13.7268 13.7268 0 00-.0283-.2936l.8656-.8069a.3483.3483 0 00-.1154-.578l-1.1066-.414a8.4958 8.4958 0 00-.087-.2856l.6904-.9587a.3462.3462 0 00-.2257-.5446l-1.1663-.1894a9.3574 9.3574 0 00-.1407-.2622l.49-1.0761a.3437.3437 0 00-.0274-.3361.3486.3486 0 00-.3006-.154l-1.1845.0416a6.7444 6.7444 0 00-.1873-.2268l.2723-1.153a.3472.3472 0 00-.417-.4172l-1.1532.2724a14.0183 14.0183 0 00-.2278-.1873l.0415-1.1845a.3442.3442 0 00-.49-.328l-1.076.491c-.0872-.0476-.1742-.0952-.2623-.1407l-.1903-1.1673A.3483.3483 0 0016.256.955l-.9597.6905a8.4867 8.4867 0 00-.2855-.086l-.414-1.1066a.3483.3483 0 00-.5781-.1154l-.8069.8666a9.2936 9.2936 0 00-.2936-.0284L12.2946.1683a.3462.3462 0 00-.5892 0l-.6236 1.0073a13.7383 13.7383 0 00-.2936.0284L9.9803.3374a.3462.3462 0 00-.578.1154l-.4141 1.1065c-.0962.0274-.1903.0567-.2855.086L7.744.955a.3483.3483 0 00-.5447.2258L7.009 2.348a9.3574 9.3574 0 00-.2622.1407l-1.0762-.491a.3462.3462 0 00-.49.328l.0416 1.1845a7.9826 7.9826 0 00-.2278.1873L3.8413 3.425a.3472.3472 0 00-.4171.4171l.2713 1.1531c-.0628.075-.1255.1509-.1863.2268l-1.1845-.0415a.3462.3462 0 00-.328.49l.491 1.0761a9.167 9.167 0 00-.1407.2622l-1.1662.1894a.3483.3483 0 00-.2258.5446l.6904.9587a13.303 13.303 0 00-.087.2855l-1.1065.414a.3483.3483 0 00-.1155.5781l.8656.807a9.2936 9.2936 0 00-.0283.2935l-1.0073.6236a.3442.3442 0 000 .5892l1.0073.6236c.008.0982.0182.1964.0283.2936l-.8656.8079a.3462.3462 0 00.1155.578l1.1065.4141c.0273.0962.0567.1914.087.2855l-.6904.9587a.3452.3452 0 00.2268.5447l1.1662.1893c.0456.088.0922.1751.1408.2622l-.491 1.0762a.3462.3462 0 00.328.49l1.1834-.0415c.0618.0769.1235.1528.1873.2277l-.2713 1.1541a.3462.3462 0 00.4171.4161l1.153-.2713c.075.0638.151.1255.2279.1863l-.0415 1.1845a.3442.3442 0 00.49.327l1.0761-.49c.087.0486.1741.0951.2622.1407l.1903 1.1662a.3483.3483 0 00.5447.2268l.9587-.6904a9.299 9.299 0 00.2855.087l.414 1.1066a.3452.3452 0 00.5781.1154l.8079-.8656c.0972.0111.1954.0203.2936.0294l.6236 1.0073a.3472.3472 0 00.5892 0l.6236-1.0073c.0982-.0091.1964-.0183.2936-.0294l.8069.8656a.3483.3483 0 00.578-.1154l.4141-1.1066a8.4626 8.4626 0 00.2855-.087l.9587.6904a.3452.3452 0 00.5447-.2268l.1903-1.1662c.088-.0456.1751-.0931.2622-.1407l1.0762.49a.3472.3472 0 00.49-.327l-.0415-1.1845a6.7267 6.7267 0 00.2267-.1863l1.1531.2713a.3472.3472 0 00.4171-.416l-.2713-1.1542c.0628-.0749.1255-.1508.1863-.2278l1.1845.0415a.3442.3442 0 00.328-.49l-.49-1.076c.0475-.0872.0951-.1742.1407-.2623l1.1662-.1893a.3483.3483 0 00.2258-.5447l-.6904-.9587.087-.2855 1.1066-.414a.3462.3462 0 00.1154-.5781l-.8656-.8079c.0101-.0972.0202-.1954.0283-.2936l1.0073-.6236a.3442.3442 0 000-.5892zm-6.7413 8.3551a.7138.7138 0 01.2986-1.396.714.714 0 11-.2997 1.396zm-.3422-2.3142a.649.649 0 00-.7715.5l-.3573 1.6685c-1.1035.501-2.3285.7795-3.6193.7795a8.7368 8.7368 0 01-3.6951-.814l-.3574-1.6684a.648.648 0 00-.7714-.499l-1.473.3158a8.7216 8.7216 0 01-.7613-.898h7.1676c.081 0 .1356-.0141.1356-.088v-2.536c0-.074-.0536-.0881-.1356-.0881h-2.0966v-1.6077h2.2677c.2065 0 1.1065.0587 1.394 1.2088.0901.3533.2875 1.5044.4232 1.8729.1346.413.6833 1.2381 1.2685 1.2381h3.5716a.7492.7492 0 00.1296-.0131 8.7874 8.7874 0 01-.8119.9526zM6.8369 20.024a.714.714 0 11-.2997-1.396.714.714 0 01.2997 1.396zM4.1177 8.9972a.7137.7137 0 11-1.304.5791.7137.7137 0 011.304-.579zm-.8352 1.9813l1.5347-.6824a.65.65 0 00.33-.8585l-.3158-.7147h1.2432v5.6025H3.5669a8.7753 8.7753 0 01-.2834-3.348zm6.7343-.5437V8.7836h2.9601c.153 0 1.0792.1772 1.0792.8697 0 .575-.7107.7815-1.2948.7815zm10.7574 1.4862c0 .2187-.008.4363-.0243.651h-.9c-.09 0-.1265.0586-.1265.1477v.413c0 .973-.5487 1.1846-1.0296 1.2382-.4576.0517-.9648-.1913-1.0275-.4717-.2704-1.5186-.7198-1.8436-1.4305-2.4034.8817-.5599 1.799-1.386 1.799-2.4915 0-1.1936-.819-1.9458-1.3769-2.3153-.7825-.5163-1.6491-.6195-1.883-.6195H5.4682a8.7651 8.7651 0 014.907-2.7699l1.0974 1.151a.648.648 0 00.9182.0213l1.227-1.1743a8.7753 8.7753 0 016.0044 4.2762l-.8403 1.8982a.652.652 0 00.33.8585l1.6178.7188c.0283.2875.0425.577.0425.8717zm-9.3006-9.5993a.7128.7128 0 11.984 1.0316.7137.7137 0 01-.984-1.0316zm8.3389 6.71a.7107.7107 0 01.9395-.3625.7137.7137 0 11-.9405.3635z', }, @@ -30,7 +32,8 @@ const LOGOS: Record = { path: 'M1.811 10.231c-.047 0-.058-.023-.035-.059l.246-.315c.023-.035.081-.058.128-.058h4.172c.046 0 .058.035.035.07l-.199.303c-.023.036-.082.07-.117.07zM.047 11.306c-.047 0-.059-.023-.035-.058l.245-.316c.023-.035.082-.058.129-.058h5.328c.047 0 .07.035.058.07l-.093.28c-.012.047-.058.07-.105.07zm2.828 1.075c-.047 0-.059-.035-.035-.07l.163-.292c.023-.035.07-.07.117-.07h2.337c.047 0 .07.035.07.082l-.023.28c0 .047-.047.082-.082.082zm12.129-2.36c-.736.187-1.239.327-1.963.514-.176.046-.187.058-.34-.117-.174-.199-.303-.327-.548-.444-.737-.362-1.45-.257-2.115.175-.795.514-1.204 1.274-1.192 2.22.011.935.654 1.706 1.577 1.835.795.105 1.46-.175 1.987-.77.105-.13.198-.27.315-.434H10.47c-.245 0-.304-.152-.222-.35.152-.362.432-.97.596-1.274a.315.315 0 01.292-.187h4.253c-.023.316-.023.631-.07.947a4.983 4.983 0 01-.958 2.29c-.841 1.11-1.94 1.8-3.33 1.986-1.145.152-2.209-.07-3.143-.77-.865-.655-1.356-1.52-1.484-2.595-.152-1.274.222-2.419.993-3.424.83-1.086 1.928-1.776 3.272-2.02 1.098-.2 2.15-.07 3.096.571.62.41 1.063.97 1.356 1.648.07.105.023.164-.117.2m3.868 6.461c-1.064-.024-2.034-.328-2.852-1.029a3.665 3.665 0 01-1.262-2.255c-.21-1.32.152-2.489.947-3.529.853-1.122 1.881-1.706 3.272-1.95 1.192-.21 2.314-.095 3.33.595.923.63 1.496 1.484 1.648 2.605.198 1.578-.257 2.863-1.344 3.962-.771.783-1.718 1.273-2.805 1.495-.315.06-.63.07-.934.106zm2.78-4.72c-.011-.153-.011-.27-.034-.387-.21-1.157-1.274-1.81-2.384-1.554-1.087.245-1.788.935-2.045 2.033-.21.912.234 1.835 1.075 2.21.643.28 1.285.244 1.905-.07.923-.48 1.425-1.228 1.484-2.233z', }, dotnet: { - color: '#512BD4', + // Lightened from the official #512BD4, which is too dim on black. + color: '#7a5fdd', title: '.NET', path: 'M24 8.77h-2.468v7.565h-1.425V8.77h-2.462V7.53H24zm-6.852 7.565h-4.821V7.53h4.63v1.24h-3.205v2.494h2.953v1.234h-2.953v2.604h3.396zm-6.708 0H8.882L4.78 9.863a2.896 2.896 0 0 1-.258-.51h-.036c.032.189.048.592.048 1.21v5.772H3.157V7.53h1.659l3.965 6.32c.167.261.275.442.323.54h.024c-.04-.233-.06-.629-.06-1.185V7.529h1.372zm-8.703-.693a.868.829 0 0 1-.869.829.868.829 0 0 1-.868-.83.868.829 0 0 1 .868-.828.868.829 0 0 1 .869.829Z', }, @@ -45,7 +48,8 @@ const LOGOS: Record = { path: 'M23.181 2.974c.568 0 .923.463.792 1.035l-3.659 15.982c-.13.572-.697 1.035-1.265 1.035H.819c-.568 0-.923-.463-.792-1.035L3.686 4.009c.13-.572.697-1.035 1.265-1.035zm-8.375 9.346c.251-.394.227-.905-.09-1.243L9.122 5.125c-.38-.404-1.037-.407-1.466-.003-.429.402-.468 1.056-.088 1.46l4.662 4.96v.11l-7.42 5.374c-.45.327-.533.977-.187 1.453.346.476.991.597 1.44.27l8.229-5.91c.28-.196.438-.365.514-.52zm-2.796 4.399a.928.928 0 00-.934.923c0 .51.418.923.934.923h4.433a.928.928 0 00.934-.923.928.928 0 00-.934-.923z', }, gh: { - color: '#181717', + // GitHub's own dark-scheme mark color (near-black is invisible here). + color: '#f0f6fc', title: 'GitHub', path: 'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12', }, diff --git a/src/components/ui/Button.tsx b/src/components/ui/Button.tsx index 44e4bda..5821f8f 100644 --- a/src/components/ui/Button.tsx +++ b/src/components/ui/Button.tsx @@ -8,8 +8,8 @@ const buttonVariants = cva( { variants: { variant: { - primary: 'bg-primary text-white hover:bg-navy', - secondary: 'bg-surface text-charcoal hover:bg-charcoal hover:text-white', + primary: 'bg-primary text-white hover:bg-primary/85', + secondary: 'bg-surface text-charcoal hover:bg-charcoal hover:text-canvas', ghost: 'bg-transparent text-charcoal hover:bg-surface', }, size: { diff --git a/src/features/auth/components/ParticleField.tsx b/src/features/auth/components/ParticleField.tsx index 2ac2c5b..5743640 100644 --- a/src/features/auth/components/ParticleField.tsx +++ b/src/features/auth/components/ParticleField.tsx @@ -286,9 +286,9 @@ export function ParticleField({ className }: ParticleFieldProps) { const ix = px0 + dx; if (ix < 0 || ix >= PW) continue; const i = (row + ix) * 4; - buf[i] = 0; - buf[i + 1] = 0; - buf[i + 2] = 0; + buf[i] = 232; + buf[i + 1] = 230; + buf[i + 2] = 227; buf[i + 3] = alpha; } } diff --git a/src/features/dashboard/components/ActivityChart.tsx b/src/features/dashboard/components/ActivityChart.tsx index c9f77dc..bd93785 100644 --- a/src/features/dashboard/components/ActivityChart.tsx +++ b/src/features/dashboard/components/ActivityChart.tsx @@ -64,25 +64,31 @@ export function ActivityChart({ buckets, range, loading, error }: ActivityChartP
- + - + - - - - + + + +
diff --git a/src/features/dashboard/components/SuccessRateChart.tsx b/src/features/dashboard/components/SuccessRateChart.tsx index 8209b7f..01b4d33 100644 --- a/src/features/dashboard/components/SuccessRateChart.tsx +++ b/src/features/dashboard/components/SuccessRateChart.tsx @@ -25,9 +25,9 @@ export function SuccessRateChart({ summary, loading, error }: SuccessRateChartPr () => summary ? [ - { name: 'Succeeded', count: summary.pipelinesSucceeded, fill: '#5645d4' }, - { name: 'Failed', count: summary.pipelinesFailed, fill: '#c62828' }, - { name: 'Cancelled', count: summary.pipelinesCancelled, fill: '#787671' }, + { name: 'Succeeded', count: summary.pipelinesSucceeded, fill: '#6a59e8' }, + { name: 'Failed', count: summary.pipelinesFailed, fill: '#e5484d' }, + { name: 'Cancelled', count: summary.pipelinesCancelled, fill: '#8f8d88' }, ] : [], [summary], @@ -61,17 +61,23 @@ export function SuccessRateChart({ summary, loading, error }: SuccessRateChartPr
- - + + {data.map((entry) => ( diff --git a/src/features/pipelines/components/LogViewer.tsx b/src/features/pipelines/components/LogViewer.tsx index 74de1fc..92cc071 100644 --- a/src/features/pipelines/components/LogViewer.tsx +++ b/src/features/pipelines/components/LogViewer.tsx @@ -95,10 +95,10 @@ function decorate(chunk: LogChunk, showTimestamps: boolean): string { /** Match highlighting in the shell's primary tint. */ const SEARCH_DECORATIONS = { - matchBackground: '#5645d433', - activeMatchBackground: '#5645d466', - matchOverviewRuler: '#5645d4', - activeMatchColorOverviewRuler: '#5645d4', + matchBackground: '#5645d455', + activeMatchBackground: '#5645d488', + matchOverviewRuler: '#6a59e8', + activeMatchColorOverviewRuler: '#6a59e8', }; function formatBytesShort(bytes: number): string { @@ -239,13 +239,13 @@ export function LogViewer({ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace', scrollback: 10_000, theme: { - background: '#ffffff', - foreground: '#37352f', - cursor: '#ffffff', - selectionBackground: '#5645d433', - red: '#c62828', - blue: '#0075de', - magenta: '#5645d4', + background: '#000000', + foreground: '#e8e6e3', + cursor: '#e8e6e3', + selectionBackground: '#5645d455', + red: '#ef5350', + blue: '#4d9fff', + magenta: '#9d8cff', }, }); const fit = new FitAddon(); diff --git a/src/features/pipelines/components/panels/PerformancePanel.tsx b/src/features/pipelines/components/panels/PerformancePanel.tsx index 03db07a..3a2d69b 100644 --- a/src/features/pipelines/components/panels/PerformancePanel.tsx +++ b/src/features/pipelines/components/panels/PerformancePanel.tsx @@ -74,21 +74,23 @@ export function PerformancePanel({ jobs, events }: PerformancePanelProps) {
- - - + + + {/* Solid palette only: steel for waiting, primary for doing. */} - - + +
@@ -99,19 +101,21 @@ export function PerformancePanel({ jobs, events }: PerformancePanelProps) {
- - - + + + {/* 100% = one full core; multi-core jobs exceed it. */} - +
diff --git a/src/features/workflows/components/WorkflowEditor.tsx b/src/features/workflows/components/WorkflowEditor.tsx index 6b42c73..8bfb9d9 100644 --- a/src/features/workflows/components/WorkflowEditor.tsx +++ b/src/features/workflows/components/WorkflowEditor.tsx @@ -14,27 +14,27 @@ interface WorkflowEditorProps { const MARKER_OWNER = 'overup-validation'; -/** Editor colors from the shell palette — flat, light, no gradients. */ +/** Editor colors from the shell palette — flat, dark, no gradients. */ function defineTheme(monaco: Monaco) { monaco.editor.defineTheme('overup', { - base: 'vs', + base: 'vs-dark', inherit: true, rules: [ - { token: 'type', foreground: '5645d4' }, - { token: 'string.yaml', foreground: '0075de' }, - { token: 'number', foreground: '5645d4' }, - { token: 'comment', foreground: '787671' }, - { token: 'keyword', foreground: '5645d4' }, + { token: 'type', foreground: '9d8cff' }, + { token: 'string.yaml', foreground: '4d9fff' }, + { token: 'number', foreground: '9d8cff' }, + { token: 'comment', foreground: '8f8d88' }, + { token: 'keyword', foreground: '9d8cff' }, ], colors: { - 'editor.background': '#ffffff', - 'editor.foreground': '#37352f', - 'editor.lineHighlightBackground': '#f6f5f4', - 'editorLineNumber.foreground': '#787671', - 'editorLineNumber.activeForeground': '#37352f', - 'editorIndentGuide.background': '#f6f5f4', - 'editor.selectionBackground': '#5645d426', - 'focusBorder': '#5645d4', + 'editor.background': '#000000', + 'editor.foreground': '#e8e6e3', + 'editor.lineHighlightBackground': '#161614', + 'editorLineNumber.foreground': '#8f8d88', + 'editorLineNumber.activeForeground': '#e8e6e3', + 'editorIndentGuide.background': '#26251f', + 'editor.selectionBackground': '#6a59e845', + 'focusBorder': '#6a59e8', }, }); } diff --git a/src/index.css b/src/index.css index c1b1483..40ba8cc 100644 --- a/src/index.css +++ b/src/index.css @@ -3,6 +3,10 @@ @tailwind utilities; @layer base { + :root { + color-scheme: dark; + } + html, body, #root { @@ -12,4 +16,15 @@ body { @apply bg-canvas font-sans text-charcoal antialiased; } + + /* Focus rings offset against the black canvas, not preflight's white default. */ + *, + ::before, + ::after { + --tw-ring-offset-color: theme('colors.canvas'); + } + + ::selection { + @apply bg-primary/40 text-charcoal; + } } diff --git a/tailwind.config.js b/tailwind.config.js index c320382..904e9ec 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -9,15 +9,15 @@ module.exports = { transparent: 'transparent', current: 'currentColor', white: '#ffffff', - canvas: '#ffffff', - surface: '#f6f5f4', - primary: '#5645d4', - purple: '#5645d4', - navy: '#0a1530', - link: '#0075de', - charcoal: '#37352f', - steel: '#787671', - danger: '#c62828', + canvas: '#000000', + surface: '#161614', + primary: '#6a59e8', + purple: '#6a59e8', + navy: '#000000', + link: '#4d9fff', + charcoal: '#e8e6e3', + steel: '#8f8d88', + danger: '#e5484d', }, // Strict design rule: every corner is 6px. `full` is reserved for avatars. borderRadius: {