diff --git a/dashboard/src/utils/monacoTheme.ts b/dashboard/src/utils/monacoTheme.ts new file mode 100644 index 000000000..2b69a5fd3 --- /dev/null +++ b/dashboard/src/utils/monacoTheme.ts @@ -0,0 +1,73 @@ +import type { editor } from "monaco-editor"; + +/** + * Defines the custom "reactor" Monaco theme: + * - Transparent background so the reactor canvas shows through + * - Cherenkov blue accents for UI elements + * - Industrial precision aesthetic + */ +export function defineReactorMonacoTheme() { + // Access monaco via the global + const monaco = (window as any).monaco; + if (!monaco) return; + + monaco.editor.defineTheme("reactor-dark", { + base: "vs-dark", + inherit: true, + rules: [ + { token: "", foreground: "E4E1E6", background: "00000000" }, + { token: "comment", foreground: "5C6370", fontStyle: "italic" }, + { token: "keyword", foreground: "7DD9CC" }, + { token: "string", foreground: "69F0AE" }, + { token: "number", foreground: "FFD54F" }, + { token: "type", foreground: "A1C9FF" }, + { token: "delimiter", foreground: "8E9099" }, + { token: "variable", foreground: "E4E1E6" }, + ], + colors: { + "editor.background": "#00000000", + "editor.foreground": "#E4E1E6", + "editor.lineHighlightBackground": "#1A3A5C22", + "editor.lineHighlightBorder": "#00F2FF18", + "editor.selectionBackground": "#005FB044", + "editor.inactiveSelectionBackground": "#005FB022", + "editorLineNumber.foreground": "#44474F", + "editorLineNumber.activeForeground": "#00F2FF", + "editorCursor.foreground": "#00F2FF", + "editorWhitespace.foreground": "#1A1A22", + "editorIndentGuide.background": "#1A1A22", + "editorIndentGuide.activeBackground": "#00F2FF22", + "editor.wordHighlightBackground": "#005FB018", + "editorGutter.background": "#00000000", + "scrollbar.shadow": "#00000000", + "scrollbarSlider.background": "#1A3A5C44", + "scrollbarSlider.hoverBackground": "#1A3A5C88", + "scrollbarSlider.activeBackground": "#00F2FF44", + }, + } satisfies editor.IStandaloneThemeData); +} + +/** + * Highlight error lines in Monaco editor with Cherenkov red glow + */ +export function setMonacoEditorErrors( + monaco: any, + editorInstance: editor.IStandaloneCodeEditor | null, + errors: Array<{ line: number; message: string }>, +) { + if (!editorInstance || !monaco) return; + + const model = editorInstance.getModel(); + if (!model) return; + + const markers: editor.IMarkerData[] = errors.map((err) => ({ + severity: monaco.MarkerSeverity.Error, + message: err.message, + startLineNumber: err.line, + startColumn: 1, + endLineNumber: err.line, + endColumn: model.getLineMaxColumn(err.line), + })); + + monaco.editor.setModelMarkers(model, "reactor-errors", markers); +} diff --git a/dashboard/src/views/ConfigPage.vue b/dashboard/src/views/ConfigPage.vue index 3a5bf7561..59a921dfb 100644 --- a/dashboard/src/views/ConfigPage.vue +++ b/dashboard/src/views/ConfigPage.vue @@ -147,43 +147,48 @@ transition="dialog-bottom-transition" scrollable > - - - - mdi-close - - {{ tm("codeEditor.title") }} - - - - {{ tm("editor.revertCode") }} +
+ + + + mdi-close - - {{ tm("editor.applyConfig") }} - - 💡 {{ tm("editor.applyTip") }} - - - - - - + {{ tm("codeEditor.title") }} + + + + {{ tm("editor.revertCode") }} + + + {{ tm("editor.applyConfig") }} + + 💡 {{ tm("editor.applyTip") }} + + + + + + +
@@ -337,6 +342,7 @@ import { } from "@/utils/confirmDialog"; import UnsavedChangesConfirmDialog from "@/components/config/UnsavedChangesConfirmDialog.vue"; import { normalizeTextInput } from "@/utils/inputValue"; +import { defineReactorMonacoTheme } from "@/utils/monacoTheme"; export default { name: "ConfigPage", @@ -498,6 +504,9 @@ export default { } }, }, + beforeMount() { + defineReactorMonacoTheme(); + }, mounted() { const hashConfigType = this.extractConfigTypeFromHash( this.$route?.fullPath || "", @@ -1105,4 +1114,47 @@ export default { padding: 0; border-radius: 0 0 16px 16px; } + +/* Reactor glassmorphism editor container */ +.editor-reactor-container { + width: 100vw; + height: 100vh; + background: rgba(10, 10, 12, 0.92); + backdrop-filter: blur(40px) saturate(1.3); + display: flex; + align-items: center; + justify-content: center; + padding: 32px; + box-sizing: border-box; +} + +.editor-glass-card { + width: 100%; + max-width: 1400px; + height: calc(100vh - 64px); + background: rgba(15, 15, 22, 0.55) !important; + backdrop-filter: blur(24px) saturate(1.2); + border: 1px solid rgba(0, 242, 255, 0.15); + border-radius: 28px !important; + box-shadow: + inset 0 0 40px rgba(0, 0, 0, 0.6), + 0 0 80px rgba(0, 26, 51, 0.4), + 0 0 0 0.5px rgba(0, 242, 255, 0.05); + overflow: hidden; + display: flex; + flex-direction: column; +} + +.editor-toolbar { + background: rgba(10, 10, 16, 0.8) !important; + border-bottom: 1px solid rgba(0, 242, 255, 0.08) !important; + backdrop-filter: blur(12px); + flex-shrink: 0; +} + +.editor-monaco-wrapper { + flex: 1; + overflow: hidden; + border-radius: 0 0 28px 28px; +}