MonacoThemeProvider.tsx 2.8 KB

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