fix(ui): keep charts and terminal readable in custom themes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2026-10-24 12:37:41 +02:00
co-authored by Claude Opus 5.5
parent 2111e95c7a
commit 0ad88d8c63
4 changed files with 34 additions and 33 deletions
+10 -5
View File
@@ -70,16 +70,15 @@ function customThemeAccent() {
return `#${channels.map((channel) => channel.toString(16).padStart(2, '0')).join('')}`;
}
// A custom theme can be light or dark: it sets only the cursor accent, and the page brightness picks the text colors.
function createSystemTerminalTheme() {
if (document.documentElement.dataset.theme === 'custom') {
return createApplicationTerminalTheme(customThemeAccent());
}
const isCustomTheme = document.documentElement.dataset.theme === 'custom';
if (document.documentElement.classList.contains('dark')) {
return createApplicationTerminalTheme('#8C8E9C');
return createApplicationTerminalTheme(isCustomTheme ? customThemeAccent() : '#8C8E9C');
}
return createApplicationTerminalTheme('#52525b', {
return createApplicationTerminalTheme(isCustomTheme ? customThemeAccent() : '#52525b', {
black: '#18181b',
red: '#dc2626',
green: '#15803d',
@@ -89,6 +88,12 @@ function createSystemTerminalTheme() {
cyan: '#0e7490',
white: '#52525b',
brightBlack: '#71717a',
brightRed: '#b91c1c',
brightGreen: '#166534',
brightYellow: '#854d0e',
brightBlue: '#1d4ed8',
brightMagenta: '#7e22ce',
brightCyan: '#155e75',
brightWhite: '#18181b',
foreground: '#18181b',
});
+18
View File
@@ -91,3 +91,21 @@ test('console input cannot forward control sequences or send into a shell sessio
component.submitConsoleCommand();
assert.equal(messages.length, 0);
});
function systemTerminalTheme({ theme, dark }) {
const source = readFileSync(new URL('./terminal.js', import.meta.url), 'utf8');
const themeSource = source.slice(source.indexOf('const baseApplicationTerminalTheme'), source.indexOf('const applicationTerminalThemes'));
return vm.runInNewContext(`${themeSource}\ncreateSystemTerminalTheme();`, {
document: { documentElement: { dataset: { theme }, classList: { contains: (name) => name === 'dark' && dark } } },
localStorage: { getItem: (key) => (key === 'themeColor' ? '#c2410c' : null) },
});
}
test('system terminal theme uses dark text on light custom themes and light text on dark custom themes', () => {
const lightCustom = systemTerminalTheme({ theme: 'custom', dark: false });
assert.equal(lightCustom.foreground, '#18181b');
assert.equal(lightCustom.brightGreen, '#166534');
assert.equal(lightCustom.cursor, systemTerminalTheme({ theme: 'custom', dark: true }).cursor);
assert.equal(systemTerminalTheme({ theme: 'custom', dark: true }).foreground, '#eee9f2');
assert.equal(systemTerminalTheme({ theme: 'light', dark: false }).cursor, '#52525b');
});
+3 -25
View File
@@ -49,33 +49,11 @@
sessionStorage.setItem('navLevel', this.navLevel);
this.$watch('navLevel', level => sessionStorage.setItem('navLevel', level));
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
const userSettings = localStorage.getItem('theme');
if (userSettings !== 'system') { return; }
document.documentElement.classList.toggle('dark', e.matches);
document.documentElement.dataset.theme = e.matches ? 'dark' : 'light';
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
if (localStorage.getItem('theme') === 'system') { window.applyStoredTheme(); }
});
this.queryTheme();
window.applyStoredTheme();
},
queryTheme() {
const darkModePreference = window.matchMedia('(prefers-color-scheme: dark)').matches;
const userSettings = localStorage.getItem('theme') || 'dark';
localStorage.setItem('theme', userSettings);
let isDark = false;
if (userSettings === 'dark' || userSettings === 'custom') {
document.documentElement.classList.add('dark');
isDark = true;
} else if (userSettings === 'light') {
document.documentElement.classList.remove('dark');
} else if (darkModePreference) {
document.documentElement.classList.add('dark');
isDark = true;
} else {
document.documentElement.classList.remove('dark');
}
document.documentElement.dataset.theme = userSettings === 'custom' ? 'custom' : (isDark ? 'dark' : 'light');
document.querySelector('meta[name=theme-color]')?.setAttribute('content', isDark ? '#101010' : '#ffffff');
}
}">
{{-- Search is only useful when workspace resources are available --}}
@if (isSubscribed() || ! isCloud())
+3 -3
View File
@@ -379,7 +379,9 @@
let theme = localStorage.theme
let cpuColor = '#1e90ff'
let ramColor = '#00ced1'
let textColor = '#ffffff'
// Chart text follows the CSS text color, so it stays readable after a theme change without a re-render
// (for example a page that Livewire restores from its cache on Back).
const textColor = 'currentColor'
let editorBackground = '#181818'
let editorTheme = 'blackboard'
@@ -391,13 +393,11 @@
if (theme == 'dark' || (theme == 'custom' && document.documentElement.classList.contains('dark'))) {
cpuColor = '#1e90ff'
ramColor = '#00ced1'
textColor = '#ffffff'
editorBackground = '#181818'
editorTheme = 'blackboard'
} else {
cpuColor = '#1e90ff'
ramColor = '#00ced1'
textColor = '#000000'
editorBackground = '#ffffff'
editorTheme = null
}