This commit is contained in:
2025-11-13 18:08:38 +01:00
parent 1dc540582d
commit 53adb131e0
9 changed files with 75 additions and 193 deletions

View File

@ -25,7 +25,7 @@
import { loadLastProjectId } from "./lib/project-system/persistence";
import { createAppContext, setAppContext } from "./lib/contexts/app-context";
import type { ProjectMode } from "./lib/project-system/types";
import { themes } from "./lib/themes";
import { themes, applyTheme } from "./lib/themes";
import {
Save,
Share2,
@ -239,52 +239,9 @@
}
$effect(() => {
if (typeof document !== 'undefined') {
const themeName = $editorSettings.theme;
const theme = themes[themeName];
const theme = themes[$editorSettings.theme];
if (theme) {
const root = document.documentElement.style;
root.setProperty('--bg-color', theme.colors.background);
root.setProperty('--surface-color', theme.colors.surface);
root.setProperty('--border-color', theme.colors.border);
root.setProperty('--text-color', theme.colors.text);
root.setProperty('--text-secondary', theme.colors.textSecondary);
root.setProperty('--accent-color', theme.colors.accent);
root.setProperty('--accent-hover', theme.colors.accentHover);
root.setProperty('--input-bg', theme.colors.input);
root.setProperty('--input-border', theme.colors.inputBorder);
root.setProperty('--button-bg', theme.colors.button);
root.setProperty('--button-hover', theme.colors.buttonHover);
root.setProperty('--danger-color', theme.colors.danger);
root.setProperty('--danger-hover', theme.colors.dangerHover);
root.setProperty('--editor-background', theme.editor.background);
root.setProperty('--editor-foreground', theme.editor.foreground);
root.setProperty('--editor-caret', theme.editor.caret);
root.setProperty('--editor-selection', theme.editor.selection);
root.setProperty('--editor-active-line', theme.editor.activeLine);
root.setProperty('--editor-gutter', theme.editor.gutter);
root.setProperty('--editor-gutter-text', theme.editor.gutterText);
root.setProperty('--editor-active-line-gutter', theme.editor.activeLineGutter);
root.setProperty('--editor-line-number', theme.editor.lineNumber);
root.setProperty('--syntax-keyword', theme.syntax.keyword);
root.setProperty('--syntax-operator', theme.syntax.operator);
root.setProperty('--syntax-string', theme.syntax.string);
root.setProperty('--syntax-number', theme.syntax.number);
root.setProperty('--syntax-boolean', theme.syntax.boolean);
root.setProperty('--syntax-comment', theme.syntax.comment);
root.setProperty('--syntax-function', theme.syntax.function);
root.setProperty('--syntax-class', theme.syntax.class);
root.setProperty('--syntax-variable', theme.syntax.variable);
root.setProperty('--syntax-property', theme.syntax.property);
root.setProperty('--syntax-constant', theme.syntax.constant);
root.setProperty('--syntax-type', theme.syntax.type);
root.setProperty('--syntax-tag', theme.syntax.tag);
root.setProperty('--syntax-attribute', theme.syntax.attribute);
}
applyTheme(theme);
}
});
@ -600,7 +557,7 @@
padding: var(--space-sm);
background-color: var(--border-color);
color: var(--text-color);
border: 1px solid #555;
border: 1px solid var(--border-color);
cursor: pointer;
display: flex;
align-items: center;
@ -609,7 +566,7 @@
}
.icon-button:hover:not(:disabled) {
background-color: #444;
background-color: var(--button-hover);
border-color: var(--accent-color);
}
@ -623,12 +580,12 @@
}
.icon-button.stop-button:not(:disabled) {
color: #ff6b6b;
color: var(--danger-color);
}
.icon-button.stop-button:hover:not(:disabled) {
color: #ff5252;
border-color: #ff5252;
color: var(--danger-hover);
border-color: var(--danger-hover);
}
h3 {
@ -705,10 +662,10 @@
}
.enable-audio-button:hover {
background-color: #535bdb;
background-color: var(--accent-hover);
}
.enable-audio-button:active {
background-color: var(--accent-hover);
background-color: var(--accent-color);
}
</style>

View File

@ -7,9 +7,8 @@
line-height: 1.5;
font-weight: 400;
color-scheme: dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
color: var(--text-color);
background-color: var(--bg-color);
font-synthesis: none;
text-rendering: optimizeLegibility;
@ -35,12 +34,12 @@ body {
a {
font-weight: 500;
color: #646cff;
color: var(--accent-color);
text-decoration: inherit;
}
a:hover {
color: #535bf2;
color: var(--accent-hover);
}
button {
@ -49,17 +48,17 @@ button {
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
background-color: var(--button-bg);
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
border-color: var(--accent-color);
}
button:focus,
button:focus-visible {
outline: 2px solid #646cff;
outline: 2px solid var(--accent-color);
outline-offset: 2px;
}

View File

@ -141,7 +141,7 @@
input[type="range"] {
width: 100%;
height: 8px;
background: #4b5563;
background: var(--input-bg);
appearance: none;
cursor: pointer;
}
@ -163,7 +163,7 @@
}
input[type="range"]:hover {
background: #6b7280;
background: var(--button-hover);
}
input[type="range"]::-webkit-slider-thumb:hover {
@ -178,7 +178,7 @@
width: 100%;
background-color: var(--bg-color);
color: var(--text-color);
border: 1px solid #555;
border: 1px solid var(--border-color);
padding: 0.4rem;
font-size: var(--font-sm);
cursor: pointer;
@ -213,15 +213,15 @@
appearance: none;
width: 16px;
height: 16px;
background-color: #4b5563;
border: 1px solid #6b7280;
background-color: var(--input-bg);
border: 1px solid var(--input-border);
cursor: pointer;
transition: all var(--transition-base);
}
input[type="checkbox"]:hover {
background-color: #6b7280;
border-color: #9ca3af;
background-color: var(--button-hover);
border-color: var(--border-color);
}
input[type="checkbox"]:checked {

View File

@ -1,5 +1,5 @@
import { writable } from 'svelte/store';
import type { ThemeName } from '$lib/themes';
import type { ThemeName } from '../themes';
const STORAGE_KEY = 'editorSettings';

View File

@ -0,0 +1,46 @@
import type { Theme } from './types';
export function applyTheme(theme: Theme): void {
if (typeof document === 'undefined') return;
const root = document.documentElement.style;
root.setProperty('--bg-color', theme.colors.background);
root.setProperty('--surface-color', theme.colors.surface);
root.setProperty('--border-color', theme.colors.border);
root.setProperty('--text-color', theme.colors.text);
root.setProperty('--text-secondary', theme.colors.textSecondary);
root.setProperty('--accent-color', theme.colors.accent);
root.setProperty('--accent-hover', theme.colors.accentHover);
root.setProperty('--input-bg', theme.colors.input);
root.setProperty('--input-border', theme.colors.inputBorder);
root.setProperty('--button-bg', theme.colors.button);
root.setProperty('--button-hover', theme.colors.buttonHover);
root.setProperty('--danger-color', theme.colors.danger);
root.setProperty('--danger-hover', theme.colors.dangerHover);
root.setProperty('--editor-background', theme.editor.background);
root.setProperty('--editor-foreground', theme.editor.foreground);
root.setProperty('--editor-caret', theme.editor.caret);
root.setProperty('--editor-selection', theme.editor.selection);
root.setProperty('--editor-active-line', theme.editor.activeLine);
root.setProperty('--editor-gutter', theme.editor.gutter);
root.setProperty('--editor-gutter-text', theme.editor.gutterText);
root.setProperty('--editor-active-line-gutter', theme.editor.activeLineGutter);
root.setProperty('--editor-line-number', theme.editor.lineNumber);
root.setProperty('--syntax-keyword', theme.syntax.keyword);
root.setProperty('--syntax-operator', theme.syntax.operator);
root.setProperty('--syntax-string', theme.syntax.string);
root.setProperty('--syntax-number', theme.syntax.number);
root.setProperty('--syntax-boolean', theme.syntax.boolean);
root.setProperty('--syntax-comment', theme.syntax.comment);
root.setProperty('--syntax-function', theme.syntax.function);
root.setProperty('--syntax-class', theme.syntax.class);
root.setProperty('--syntax-variable', theme.syntax.variable);
root.setProperty('--syntax-property', theme.syntax.property);
root.setProperty('--syntax-constant', theme.syntax.constant);
root.setProperty('--syntax-type', theme.syntax.type);
root.setProperty('--syntax-tag', theme.syntax.tag);
root.setProperty('--syntax-attribute', theme.syntax.attribute);
}

View File

@ -1,49 +0,0 @@
import type { Theme } from './types';
export function generateThemeCss(theme: Theme): string {
return `
/* ${theme.name} Theme */
/* UI Colors */
--bg-color: ${theme.colors.background};
--surface-color: ${theme.colors.surface};
--border-color: ${theme.colors.border};
--text-color: ${theme.colors.text};
--text-secondary: ${theme.colors.textSecondary};
--accent-color: ${theme.colors.accent};
--accent-hover: ${theme.colors.accentHover};
--input-bg: ${theme.colors.input};
--input-border: ${theme.colors.inputBorder};
--button-bg: ${theme.colors.button};
--button-hover: ${theme.colors.buttonHover};
--danger-color: ${theme.colors.danger};
--danger-hover: ${theme.colors.dangerHover};
/* Editor Colors */
--editor-background: ${theme.editor.background};
--editor-foreground: ${theme.editor.foreground};
--editor-caret: ${theme.editor.caret};
--editor-selection: ${theme.editor.selection};
--editor-active-line: ${theme.editor.activeLine};
--editor-gutter: ${theme.editor.gutter};
--editor-gutter-text: ${theme.editor.gutterText};
--editor-active-line-gutter: ${theme.editor.activeLineGutter};
--editor-line-number: ${theme.editor.lineNumber};
/* Syntax Highlighting */
--syntax-keyword: ${theme.syntax.keyword};
--syntax-operator: ${theme.syntax.operator};
--syntax-string: ${theme.syntax.string};
--syntax-number: ${theme.syntax.number};
--syntax-boolean: ${theme.syntax.boolean};
--syntax-comment: ${theme.syntax.comment};
--syntax-function: ${theme.syntax.function};
--syntax-class: ${theme.syntax.class};
--syntax-variable: ${theme.syntax.variable};
--syntax-property: ${theme.syntax.property};
--syntax-constant: ${theme.syntax.constant};
--syntax-type: ${theme.syntax.type};
--syntax-tag: ${theme.syntax.tag};
--syntax-attribute: ${theme.syntax.attribute};
`.trim();
}

View File

@ -1,7 +1,5 @@
export type { Theme } from './types';
export { createHighlightStyle } from './utils';
export { generateThemeCss } from './exportCss';
export { applyTheme } from './apply-theme';
import type { Theme } from './types';
import { light } from './definitions/light';
import { blue } from './definitions/blue';

View File

@ -1,29 +0,0 @@
import { HighlightStyle } from '@codemirror/language';
import { tags as t } from '@lezer/highlight';
import type { Theme } from './types';
export function createHighlightStyle(theme: Theme): HighlightStyle {
return HighlightStyle.define([
{ tag: t.keyword, color: theme.syntax.keyword },
{ tag: [t.name, t.deleted, t.character, t.macroName], color: theme.syntax.variable },
{ tag: [t.function(t.variableName), t.labelName], color: theme.syntax.function },
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: theme.syntax.constant },
{ tag: [t.definition(t.name), t.separator], color: theme.syntax.variable },
{ tag: [t.typeName, t.className, t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: theme.syntax.class },
{ tag: [t.operator, t.operatorKeyword, t.url, t.escape, t.regexp, t.link, t.special(t.string)], color: theme.syntax.operator },
{ tag: [t.meta, t.comment], color: theme.syntax.comment },
{ tag: t.strong, fontWeight: 'bold' },
{ tag: t.emphasis, fontStyle: 'italic' },
{ tag: t.strikethrough, textDecoration: 'line-through' },
{ tag: t.link, color: theme.syntax.string, textDecoration: 'underline' },
{ tag: t.heading, fontWeight: 'bold', color: theme.syntax.keyword },
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: theme.syntax.boolean },
{ tag: [t.processingInstruction, t.string, t.inserted], color: theme.syntax.string },
{ tag: t.invalid, color: theme.editor.foreground },
{ tag: t.number, color: theme.syntax.number },
{ tag: [t.propertyName], color: theme.syntax.property },
{ tag: [t.typeName], color: theme.syntax.type },
{ tag: [t.tagName], color: theme.syntax.tag },
{ tag: [t.attributeName], color: theme.syntax.attribute },
]);
}

View File

@ -2,7 +2,7 @@ import { mount } from 'svelte'
import './base.css'
import './app.css'
import App from './App.svelte'
import { themes } from './lib/themes'
import { themes, applyTheme } from './lib/themes'
// Apply saved theme before mounting app to prevent flash
const STORAGE_KEY = 'editorSettings';
@ -11,47 +11,7 @@ if (stored) {
try {
const settings = JSON.parse(stored);
if (settings.theme && themes[settings.theme]) {
const theme = themes[settings.theme];
const root = document.documentElement.style;
root.setProperty('--bg-color', theme.colors.background);
root.setProperty('--surface-color', theme.colors.surface);
root.setProperty('--border-color', theme.colors.border);
root.setProperty('--text-color', theme.colors.text);
root.setProperty('--text-secondary', theme.colors.textSecondary);
root.setProperty('--accent-color', theme.colors.accent);
root.setProperty('--accent-hover', theme.colors.accentHover);
root.setProperty('--input-bg', theme.colors.input);
root.setProperty('--input-border', theme.colors.inputBorder);
root.setProperty('--button-bg', theme.colors.button);
root.setProperty('--button-hover', theme.colors.buttonHover);
root.setProperty('--danger-color', theme.colors.danger);
root.setProperty('--danger-hover', theme.colors.dangerHover);
root.setProperty('--editor-background', theme.editor.background);
root.setProperty('--editor-foreground', theme.editor.foreground);
root.setProperty('--editor-caret', theme.editor.caret);
root.setProperty('--editor-selection', theme.editor.selection);
root.setProperty('--editor-active-line', theme.editor.activeLine);
root.setProperty('--editor-gutter', theme.editor.gutter);
root.setProperty('--editor-gutter-text', theme.editor.gutterText);
root.setProperty('--editor-active-line-gutter', theme.editor.activeLineGutter);
root.setProperty('--editor-line-number', theme.editor.lineNumber);
root.setProperty('--syntax-keyword', theme.syntax.keyword);
root.setProperty('--syntax-operator', theme.syntax.operator);
root.setProperty('--syntax-string', theme.syntax.string);
root.setProperty('--syntax-number', theme.syntax.number);
root.setProperty('--syntax-boolean', theme.syntax.boolean);
root.setProperty('--syntax-comment', theme.syntax.comment);
root.setProperty('--syntax-function', theme.syntax.function);
root.setProperty('--syntax-class', theme.syntax.class);
root.setProperty('--syntax-variable', theme.syntax.variable);
root.setProperty('--syntax-property', theme.syntax.property);
root.setProperty('--syntax-constant', theme.syntax.constant);
root.setProperty('--syntax-type', theme.syntax.type);
root.setProperty('--syntax-tag', theme.syntax.tag);
root.setProperty('--syntax-attribute', theme.syntax.attribute);
applyTheme(themes[settings.theme]);
}
} catch (e) {
console.error('Failed to parse editor settings:', e);