diff --git a/package-lock.json b/package-lock.json index 3faa59c9..24866d9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@codemirror/lang-javascript": "^6.2.2", "@codemirror/view": "^6.25.0", + "@uiw/codemirror-theme-github": "^4.21.24", "@uiw/codemirror-theme-monokai": "^4.21.24", "codemirror": "^6.0.1", "dat.gui": "^0.7.6", @@ -1068,6 +1069,17 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@uiw/codemirror-theme-github": { + "version": "4.21.24", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-github/-/codemirror-theme-github-4.21.24.tgz", + "integrity": "sha512-BggG0qiLpg5j9ijY4DJDnANefLADKh8FseH28J1ljvwtnvlR1GGnO+RZzOl11gLpDqb2DUM5xIaxmbLcKWljUg==", + "dependencies": { + "@uiw/codemirror-themes": "4.21.24" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, "node_modules/@uiw/codemirror-theme-monokai": { "version": "4.21.24", "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-monokai/-/codemirror-theme-monokai-4.21.24.tgz", diff --git a/package.json b/package.json index 05825ede..9dde67fa 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "dependencies": { "@codemirror/lang-javascript": "^6.2.2", "@codemirror/view": "^6.25.0", + "@uiw/codemirror-theme-github": "^4.21.24", "@uiw/codemirror-theme-monokai": "^4.21.24", "codemirror": "^6.0.1", "dat.gui": "^0.7.6", diff --git a/public/css/HomePage.css b/public/css/HomePage.css index cbb85899..a75944f2 100644 --- a/public/css/HomePage.css +++ b/public/css/HomePage.css @@ -14,10 +14,10 @@ --tooltip-background: #eee; --tooltip-border: rgba(0, 0, 0, 0.1); - --source-tab-color: white; - --source-tab-background: #444; - --source-tab-active-background: #282828; - --source-tab-active-shadow: rgb(167, 167, 167); + --source-tab-color: black; + --source-tab-background: #CCC; + --source-tab-active-background: #FFF; + --source-tab-active-shadow: #EEE; } @media (prefers-color-scheme: dark) { @@ -34,6 +34,11 @@ --tooltip-background: #111; --tooltip-border: rgba(255, 255, 255, 0.1); + + --source-tab-color: white; + --source-tab-background: #444; + --source-tab-active-background: #282828; + --source-tab-active-shadow: rgb(167, 167, 167); } } diff --git a/src/main.ts b/src/main.ts index f6d66d59..6423347f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,8 +1,9 @@ import { createElem as el } from './utils/elem'; import { SampleInfo, SourceInfo, pageCategories } from './samples'; import { monokai } from '@uiw/codemirror-theme-monokai'; +import { githubLight } from '@uiw/codemirror-theme-github'; import { EditorView } from '@codemirror/view'; -import { EditorState } from '@codemirror/state'; +import { EditorState, Compartment } from '@codemirror/state'; import { javascript } from '@codemirror/lang-javascript'; import { basicSetup } from 'codemirror'; import { Converter } from 'showdown'; @@ -33,18 +34,30 @@ const titleElem = getElem('#title', sampleElem); const descriptionElem = getElem('#description', sampleElem); const menuToggleElem = getElem('#menuToggle') as HTMLInputElement; +const darkMatcher = window.matchMedia('(prefers-color-scheme: dark)'); + +/** + * Gets the CodeMirrorTheme based on light or dark + */ +function getCodeMirrorTheme() { + const isDarkMode = darkMatcher.matches; + return isDarkMode ? monokai : githubLight; +} + // Get the parts of a string past the last `/` const basename = (name: string) => name.substring(name.lastIndexOf('/') + 1); // Make a new codemirror editor const readOnly = EditorState.readOnly.of(true); +const themeConfig = new Compartment(); + async function makeCodeMirrorEditor(parent: HTMLElement, filename: string) { const source = await (await fetch(filename)).text(); - new EditorView({ + return new EditorView({ extensions: [ basicSetup, - monokai, + themeConfig.of([getCodeMirrorTheme()]), EditorView.lineWrapping, javascript(), readOnly, @@ -96,9 +109,24 @@ function isSameDomain(url: string) { return new URL(url, window.location.href).origin === window.location.origin; } -// That current sample so we don't reload an iframe if the user picks the same sample. +// The current sample so we don't reload an iframe if the user picks the same sample. let currentSampleInfo: SampleInfo | undefined; +// The current set of codeMirrorEditors +const codeMirrorEditors: Promise[] = []; + +// Switch the code mirror themes if the color preference changes. +darkMatcher.addEventListener('change', () => { + const theme = getCodeMirrorTheme(); + for (const editorViewPromise of codeMirrorEditors) { + editorViewPromise.then((editorView) => { + editorView.dispatch({ + effects: themeConfig.reconfigure([theme]), + }); + }); + } +}); + /** * Change the iframe (and source editors) to the given sample or none */ @@ -154,6 +182,7 @@ function setSampleIFrame( codeTabsElem.innerHTML = ''; sourcesElem.innerHTML = ''; sourcesElem.style.display = sources.length > 0 ? '' : 'none'; + codeMirrorEditors.length = 0; sources.forEach((source, i) => { const { path } = source; const active = (i === 0).toString(); @@ -182,7 +211,7 @@ function setSampleIFrame( }); sourcesElem.appendChild(elem); const url = isSameDomain(path) ? `${filename}/${path}` : source.path; - makeCodeMirrorEditor(elem, url); + codeMirrorEditors.push(makeCodeMirrorEditor(elem, url)); }); }