Editor: site-matched theme, Victor Mono font, no false TS errors

- Add spoon-dark/spoon-light Monaco themes built from the site's design tokens
  (teal --primary accent), switched by next-themes resolvedTheme
- Use Victor Mono (with ligatures + italic comments) for the editor font
- Disable Monaco's in-browser TS *semantic* diagnostics, which were false
  positives (no node_modules / path aliases in the browser) e.g. 'Cannot find
  module ~/server/auth'; keep real syntax-error reporting
This commit is contained in:
Gabriel Brown
2026-06-24 07:45:24 -04:00
parent ae90681d9b
commit 1072cf10cd
3 changed files with 197 additions and 4 deletions
@@ -2,15 +2,26 @@
import { useEffect, useRef, useState } from 'react';
import dynamic from 'next/dynamic';
import { useTheme } from 'next-themes';
import { Button, Switch } from '@spoon/ui';
import type { MonacoLike } from './monaco-theme';
import { languageForPath } from './languages';
import {
configureSpoonMonaco,
remeasureFontsWhenReady,
SPOON_DARK,
SPOON_LIGHT,
} from './monaco-theme';
const MonacoEditor = dynamic(async () => await import('@monaco-editor/react'), {
ssr: false,
});
const EDITOR_FONT_FAMILY =
"var(--font-victor-mono), 'Geist Mono', ui-monospace, SFMono-Regular, monospace";
type MonacoEditorInstance = {
getModel?: () => unknown;
};
@@ -42,6 +53,8 @@ export const CodeEditor = ({
const editorRef = useRef<MonacoEditorInstance | null>(null);
const vimRef = useRef<VimMode | null>(null);
const statusRef = useRef<HTMLDivElement | null>(null);
const { resolvedTheme } = useTheme();
const editorTheme = resolvedTheme === 'light' ? SPOON_LIGHT : SPOON_DARK;
useEffect(() => {
const editor = editorRef.current;
@@ -115,14 +128,23 @@ export const CodeEditor = ({
path={path}
language={languageForPath(path)}
value={content}
theme='vs-dark'
theme={editorTheme}
beforeMount={(monaco) => {
configureSpoonMonaco(monaco as unknown as MonacoLike);
}}
options={{
readOnly,
minimap: { enabled: false },
fontFamily: EDITOR_FONT_FAMILY,
fontLigatures: true,
fontSize: 13,
lineHeight: 1.6,
scrollBeyondLastLine: false,
wordWrap: 'on',
automaticLayout: true,
smoothScrolling: true,
cursorSmoothCaretAnimation: 'on',
padding: { top: 12, bottom: 12 },
scrollbar: { alwaysConsumeMouseWheel: false },
quickSuggestions: true,
suggestOnTriggerCharacters: true,
@@ -131,8 +153,9 @@ export const CodeEditor = ({
bracketPairColorization: { enabled: true },
renderWhitespace: 'selection',
}}
onMount={(editor) => {
onMount={(editor, monaco) => {
editorRef.current = editor as MonacoEditorInstance;
remeasureFontsWhenReady(monaco as unknown as MonacoLike);
}}
onChange={(next) => {
const nextValue = next ?? '';