MonacoThemeProvider.tsx88 lines · main
1import { useMonaco } from '@monaco-editor/react'
2import { useTheme } from 'next-themes'
3import { useMemo } from 'react'
4
5/*
6 * Briven Monaco theme — Phase 5 screen 4 of BACKEND_FORK_BRIEF.md.
7 * Palette sourced from packages/config/tailwind/theme.css:
8 * bg #0a0b0d
9 * text #f5f7fa
10 * primary #00e87a (cursor, selection accent)
11 * code-comment #6b7280
12 * code-keyword #ff7a9f
13 * code-string #9dffa8
14 * code-number #ffb86b
15 * code-fn #5b9fff
16 */
17const BRIVEN_DARK = {
18 bg: '0a0b0d',
19 text: 'f5f7fa',
20 primary: '00e87a',
21 comment: '6b7280',
22 keyword: 'ff7a9f',
23 string: '9dffa8',
24 number: 'ffb86b',
25 fn: '5b9fff',
26}
27
28const BRIVEN_LIGHT = {
29 bg: 'f5f7fa',
30 text: '0a0b0d',
31 primary: '00c968',
32 comment: '6b7280',
33 keyword: 'd1265f',
34 string: '0a8b3a',
35 number: 'b85a00',
36 fn: '2e5fbf',
37}
38
39export const getTheme = (theme: string) => {
40 const isDarkMode = theme.includes('dark')
41 const p = isDarkMode ? BRIVEN_DARK : BRIVEN_LIGHT
42 return {
43 base: isDarkMode ? ('vs-dark' as const) : ('vs' as const),
44 inherit: true,
45 rules: [
46 { token: '', background: p.bg, foreground: p.text },
47 { token: 'comment', foreground: p.comment, fontStyle: 'italic' },
48 { token: 'string', foreground: p.string },
49 { token: 'string.sql', foreground: p.string },
50 { token: 'number', foreground: p.number },
51 { token: 'keyword', foreground: p.keyword },
52 { token: 'keyword.sql', foreground: p.keyword },
53 { token: 'predefined.sql', foreground: p.fn },
54 { token: 'operator.sql', foreground: p.primary },
55 { token: 'identifier', foreground: p.text },
56 { token: 'delimiter', foreground: p.text },
57 ],
58 colors: {
59 'editor.background': `#${p.bg}`,
60 'editor.foreground': `#${p.text}`,
61 'editorCursor.foreground': `#${p.primary}`,
62 'editorLineNumber.foreground': `#${p.comment}`,
63 'editorLineNumber.activeForeground': `#${p.text}`,
64 'editor.selectionBackground': `#${p.primary}33`,
65 'editor.lineHighlightBackground': isDarkMode ? '#13151a' : '#e8eaef',
66 },
67 }
68}
69
70/**
71 * This component is used to set the theme for the Monaco editor. This would be a hook but it needs to be placed between
72 * ThemeProvider and the layout page so a component is the most convenient way to do this.
73 */
74export const MonacoThemeProvider = () => {
75 const monaco = useMonaco()
76 const { resolvedTheme } = useTheme()
77
78 // Define the briven theme for Monaco before anything is rendered. Using useEffect would sometime load the theme
79 // after the editor was loaded, so it looked off. useMemo will always be run before rendering
80 useMemo(() => {
81 if (monaco && resolvedTheme) {
82 const mode = getTheme(resolvedTheme)
83 monaco.editor.defineTheme('briven', mode)
84 }
85 }, [resolvedTheme, monaco])
86
87 return null
88}