From c64fed239c2f05fc7bf1b56af0356c4df9b35357 Mon Sep 17 00:00:00 2001 From: Neil Murphy Date: Wed, 1 Jan 2025 15:05:42 +0000 Subject: [PATCH 1/8] using PrismLight instead of Prism for syntax highlighting --- src/components/CodePreview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/CodePreview.tsx b/src/components/CodePreview.tsx index ca7c1e7d..b374d75e 100644 --- a/src/components/CodePreview.tsx +++ b/src/components/CodePreview.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; +import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter"; import { oneDark, oneLight, From 5ee6bc898981d638bbeecf1086a99b900c9e1840 Mon Sep 17 00:00:00 2001 From: Neil Murphy Date: Wed, 1 Jan 2025 17:10:40 +0000 Subject: [PATCH 2/8] consolidate theme logic, allow the user to select a highlighter style from the new dropdown --- src/components/CodePreview.tsx | 37 ++----- src/components/HighlighterStyleSelector.tsx | 108 ++++++++++++++++++++ src/components/ThemeToggle.tsx | 26 +---- src/consts/highlighter-styles.ts | 98 ++++++++++++++++++ src/contexts/AppContext.tsx | 44 +++++++- src/hooks/useKeyboardNavigation.ts | 13 ++- src/layouts/Header.tsx | 4 + src/styles/main.css | 7 +- src/types/index.ts | 11 ++ 9 files changed, 289 insertions(+), 59 deletions(-) create mode 100644 src/components/HighlighterStyleSelector.tsx create mode 100644 src/consts/highlighter-styles.ts diff --git a/src/components/CodePreview.tsx b/src/components/CodePreview.tsx index b374d75e..9cd7be99 100644 --- a/src/components/CodePreview.tsx +++ b/src/components/CodePreview.tsx @@ -1,9 +1,6 @@ -import { useEffect, useState } from "react"; import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter"; -import { - oneDark, - oneLight, -} from "react-syntax-highlighter/dist/esm/styles/prism"; + +import { useAppContext } from "@contexts/AppContext"; import CopyToClipboard from "./CopyToClipboard"; @@ -13,34 +10,22 @@ type Props = { }; const CodePreview = ({ language = "markdown", code }: Props) => { - const [theme, setTheme] = useState<"dark" | "light">("dark"); - - useEffect(() => { - const handleThemeChange = () => { - const newTheme = document.documentElement.getAttribute("data-theme") as - | "dark" - | "light"; - setTheme(newTheme || "dark"); - }; - - handleThemeChange(); - const observer = new MutationObserver(handleThemeChange); - observer.observe(document.documentElement, { - attributes: true, - attributeFilter: ["data-theme"], - }); - - return () => observer.disconnect(); - }, []); + const { highlighterStyle } = useAppContext(); return (
{code.join("\n")} diff --git a/src/components/HighlighterStyleSelector.tsx b/src/components/HighlighterStyleSelector.tsx new file mode 100644 index 00000000..7ceb9266 --- /dev/null +++ b/src/components/HighlighterStyleSelector.tsx @@ -0,0 +1,108 @@ +import { useRef, useEffect, useState } from "react"; + +import { highlighterStyles } from "@consts/highlighter-styles"; +import { useAppContext } from "@contexts/AppContext"; +import { useKeyboardNavigation } from "@hooks/useKeyboardNavigation"; +import { HighlighterStyleType } from "@types"; + +const HighlighterStyleSelector = () => { + const { highlighterStyle, setHighlighterStyle } = useAppContext(); + + const dropdownRef = useRef(null); + const [isOpen, setIsOpen] = useState(false); + + const handleSelect = (selected: HighlighterStyleType) => { + setHighlighterStyle(selected); + setIsOpen(false); + }; + + const { focusedIndex, handleKeyDown, resetFocus, focusFirst } = + useKeyboardNavigation({ + items: highlighterStyles, + isOpen, + onSelect: handleSelect, + onClose: () => setIsOpen(false), + }); + + const handleBlur = () => { + setTimeout(() => { + if ( + dropdownRef.current && + !dropdownRef.current.contains(document.activeElement) + ) { + setIsOpen(false); + } + }, 0); + }; + + const toggleDropdown = () => { + setIsOpen((prev) => { + if (!prev) setTimeout(focusFirst, 0); + return !prev; + }); + }; + + useEffect(() => { + if (!isOpen) { + resetFocus(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isOpen]); + + useEffect(() => { + if (isOpen && focusedIndex >= 0) { + const element = document.querySelector( + `.selector__item:nth-child(${focusedIndex + 1})` + ) as HTMLElement; + element?.focus(); + } + }, [isOpen, focusedIndex]); + + return ( +
+ + {isOpen && ( +
    + {highlighterStyles.map((hs, index) => ( +
  • handleSelect(hs)} + className={`selector__item ${ + highlighterStyle.name === hs.name ? "selected" : "" + } ${focusedIndex === index ? "focused" : ""}`} + aria-selected={highlighterStyle.name === hs.name} + > + +
  • + ))} +
+ )} +
+ ); +}; + +export default HighlighterStyleSelector; diff --git a/src/components/ThemeToggle.tsx b/src/components/ThemeToggle.tsx index a8cdd66f..92be1fa1 100644 --- a/src/components/ThemeToggle.tsx +++ b/src/components/ThemeToggle.tsx @@ -1,29 +1,7 @@ -import { useState, useEffect } from "react"; +import { useAppContext } from "@contexts/AppContext"; const ThemeToggle = () => { - const [theme, setTheme] = useState("dark"); - - useEffect(() => { - // if the theme isn't set, use the user's system preference - const savedTheme = localStorage.getItem("theme"); - if (savedTheme) { - setTheme(savedTheme); - document.documentElement.setAttribute("data-theme", savedTheme); - } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) { - setTheme("dark"); - document.documentElement.setAttribute("data-theme", "dark"); - } else { - setTheme("light"); - document.documentElement.setAttribute("data-theme", "light"); - } - }, []); - - const toggleTheme = () => { - const newTheme = theme === "dark" ? "light" : "dark"; - setTheme(newTheme); - localStorage.setItem("theme", newTheme); - document.documentElement.setAttribute("data-theme", newTheme); - }; + const { theme, toggleTheme } = useAppContext(); return ( - {isOpen && ( -
    - {highlighterStyles.map((hs, index) => ( -
  • handleSelect(hs)} - className={`selector__item ${ - highlighterStyle.name === hs.name ? "selected" : "" - } ${focusedIndex === index ? "focused" : ""}`} - aria-selected={highlighterStyle.name === hs.name} - > - -
  • - ))} -
- )} -
+ ); }; diff --git a/src/components/LanguageSelector.tsx b/src/components/LanguageSelector.tsx index ae30b12f..1be4468b 100644 --- a/src/components/LanguageSelector.tsx +++ b/src/components/LanguageSelector.tsx @@ -1,115 +1,46 @@ -import { useRef, useEffect, useState } from "react"; +import { useMemo } from "react"; import { useAppContext } from "@contexts/AppContext"; -import { useKeyboardNavigation } from "@hooks/useKeyboardNavigation"; import { useLanguages } from "@hooks/useLanguages"; -import { LanguageType } from "@types"; +import { SelectorOption } from "@types"; -// Inspired by https://blog.logrocket.com/creating-custom-select-dropdown-css/ +import Selector from "./Selector"; const LanguageSelector = () => { const { language, setLanguage } = useAppContext(); const { fetchedLanguages, loading, error } = useLanguages(); - const dropdownRef = useRef(null); - const [isOpen, setIsOpen] = useState(false); + const options = useMemo( + () => + fetchedLanguages.map((item) => ({ + name: item.lang, + icon: item.icon, + })), + [fetchedLanguages] + ); - const handleSelect = (selected: LanguageType) => { + const handleSelect = (option: SelectorOption) => { + const selected = fetchedLanguages.find((lang) => lang.lang === option.name); + if (!selected) { + return; + } setLanguage(selected); - setIsOpen(false); - }; - - const { focusedIndex, handleKeyDown, resetFocus, focusFirst } = - useKeyboardNavigation({ - items: fetchedLanguages, - isOpen, - onSelect: handleSelect, - onClose: () => setIsOpen(false), - }); - - const handleBlur = () => { - setTimeout(() => { - if ( - dropdownRef.current && - !dropdownRef.current.contains(document.activeElement) - ) { - setIsOpen(false); - } - }, 0); }; - const toggleDropdown = () => { - setIsOpen((prev) => { - if (!prev) setTimeout(focusFirst, 0); - return !prev; - }); - }; - - useEffect(() => { - if (!isOpen) { - resetFocus(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isOpen]); - - useEffect(() => { - if (isOpen && focusedIndex >= 0) { - const element = document.querySelector( - `.selector__item:nth-child(${focusedIndex + 1})` - ) as HTMLElement; - element?.focus(); - } - }, [isOpen, focusedIndex]); + if (loading) { + return

Loading languages...

; + } - if (loading) return

Loading languages...

; - if (error) return

Error fetching languages: {error}

; + if (error) { + return

Error fetching languages: {error}

; + } return ( -
- - {isOpen && ( -
    - {fetchedLanguages.map((lang, index) => ( -
  • handleSelect(lang)} - className={`selector__item ${ - language.lang === lang.lang ? "selected" : "" - } ${focusedIndex === index ? "focused" : ""}`} - aria-selected={language.lang === lang.lang} - > - -
  • - ))} -
- )} -
+ ); }; diff --git a/src/components/Selector.tsx b/src/components/Selector.tsx new file mode 100644 index 00000000..3fb8b8b9 --- /dev/null +++ b/src/components/Selector.tsx @@ -0,0 +1,116 @@ +/** + * Inspired by https://blog.logrocket.com/creating-custom-select-dropdown-css/ + */ + +import { FC, useEffect, useRef, useState } from "react"; + +import { useKeyboardNavigation } from "@hooks/useKeyboardNavigation"; +import { SelectorOption } from "@types"; + +interface SelectorProps { + options: Array; + selectedOption: SelectorOption; + handleSelect: (option: SelectorOption) => void; +} + +const Selector: FC = (props) => { + const { options, selectedOption, handleSelect } = props; + + const dropdownRef = useRef(null); + const [isOpen, setIsOpen] = useState(false); + + const { focusedIndex, handleKeyDown, resetFocus, focusFirst } = + useKeyboardNavigation({ + options, + isOpen, + onSelect: handleSelect, + onClose: () => setIsOpen(false), + }); + + const handleBlur = () => { + setTimeout(() => { + if ( + dropdownRef.current && + !dropdownRef.current.contains(document.activeElement) + ) { + setIsOpen(false); + } + }, 0); + }; + + const toggleDropdown = () => { + setIsOpen((prev) => { + if (!prev) setTimeout(focusFirst, 0); + return !prev; + }); + }; + + useEffect(() => { + if (!isOpen) { + resetFocus(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isOpen]); + + useEffect(() => { + if (isOpen && focusedIndex >= 0) { + const element = document.querySelector( + `.selector__item:nth-child(${focusedIndex + 1})` + ) as HTMLElement; + element?.focus(); + } + }, [isOpen, focusedIndex]); + + return ( +
+ + {isOpen && ( +
    + {options.map((item, index) => ( +
  • { + handleSelect(item); + setIsOpen(false); + }} + className={`selector__item ${ + selectedOption.name === item.name ? "selected" : "" + } ${focusedIndex === index ? "focused" : ""}`} + aria-selected={selectedOption.name === item.name} + > + +
  • + ))} +
+ )} +
+ ); +}; + +export default Selector; diff --git a/src/hooks/useKeyboardNavigation.ts b/src/hooks/useKeyboardNavigation.ts index c1e50927..25a77659 100644 --- a/src/hooks/useKeyboardNavigation.ts +++ b/src/hooks/useKeyboardNavigation.ts @@ -1,19 +1,20 @@ import { useState } from "react"; -interface UseKeyboardNavigationProps { - // items: LanguageType[]; - items: Array; +import { SelectorOption } from "@types"; + +interface UseKeyboardNavigationProps { + options: Array; isOpen: boolean; - onSelect: (item: T) => void; + onSelect: (item: SelectorOption) => void; onClose: () => void; } -export const useKeyboardNavigation = ({ - items, +export const useKeyboardNavigation = ({ + options, isOpen, onSelect, onClose, -}: UseKeyboardNavigationProps) => { +}: UseKeyboardNavigationProps) => { const [focusedIndex, setFocusedIndex] = useState(-1); const handleKeyDown = (event: React.KeyboardEvent) => { @@ -22,16 +23,16 @@ export const useKeyboardNavigation = ({ switch (event.key) { case "ArrowDown": event.preventDefault(); - setFocusedIndex((prev) => (prev < items.length - 1 ? prev + 1 : 0)); + setFocusedIndex((prev) => (prev < options.length - 1 ? prev + 1 : 0)); break; case "ArrowUp": event.preventDefault(); - setFocusedIndex((prev) => (prev > 0 ? prev - 1 : items.length - 1)); + setFocusedIndex((prev) => (prev > 0 ? prev - 1 : options.length - 1)); break; case "Enter": event.preventDefault(); if (focusedIndex >= 0) { - onSelect(items[focusedIndex]); + onSelect(options[focusedIndex]); } break; case "Escape": diff --git a/src/hooks/useLanguages.ts b/src/hooks/useLanguages.ts index dc669f61..0389ac44 100644 --- a/src/hooks/useLanguages.ts +++ b/src/hooks/useLanguages.ts @@ -3,8 +3,9 @@ import { LanguageType } from "@types"; import { useFetch } from "./useFetch"; export const useLanguages = () => { - const { data, loading, error } = - useFetch("/consolidated/_index.json"); + const { data, loading, error } = useFetch( + "/consolidated/_index.json" + ); return { fetchedLanguages: data || [], loading, error }; }; diff --git a/src/types/index.ts b/src/types/index.ts index a4a1038a..a2c7647a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -35,3 +35,8 @@ export type AppState = { React.SetStateAction >; }; + +export interface SelectorOption { + name: string; + icon?: string; +} From 4ce57e58bfaf39ce58887f3ec71d38773e6e83da Mon Sep 17 00:00:00 2001 From: Neil Murphy Date: Wed, 1 Jan 2025 18:35:40 +0000 Subject: [PATCH 4/8] highlighter style persisted in localStorage --- src/components/HighlighterStyleSelector.tsx | 4 +-- src/contexts/AppContext.tsx | 32 +++++++++++++++++---- src/types/index.ts | 4 +-- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/components/HighlighterStyleSelector.tsx b/src/components/HighlighterStyleSelector.tsx index a2c0ded9..f663b634 100644 --- a/src/components/HighlighterStyleSelector.tsx +++ b/src/components/HighlighterStyleSelector.tsx @@ -5,7 +5,7 @@ import { SelectorOption } from "@types"; import Selector from "./Selector"; const HighlighterStyleSelector = () => { - const { highlighterStyle, setHighlighterStyle } = useAppContext(); + const { highlighterStyle, toggleHighlighterStyle } = useAppContext(); const options = highlighterStyles.map((style) => ({ name: style.name, @@ -18,7 +18,7 @@ const HighlighterStyleSelector = () => { if (!selected) { return; } - setHighlighterStyle(selected); + toggleHighlighterStyle(selected); }; return ( diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx index 7fd2560a..7ad5fd19 100644 --- a/src/contexts/AppContext.tsx +++ b/src/contexts/AppContext.tsx @@ -8,7 +8,13 @@ import { } from "react"; import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism"; -import { AppState, LanguageType, SnippetType } from "@types"; +import { highlighterStyles } from "@consts/highlighter-styles"; +import { + AppState, + HighlighterStyleType, + LanguageType, + SnippetType, +} from "@types"; // tokens const defaultLanguage: LanguageType = { @@ -16,7 +22,10 @@ const defaultLanguage: LanguageType = { icon: "/icons/javascript.svg", }; -const defaultHighlighterStyle = { name: "oneDark", style: oneDark }; +const defaultHighlighterStyle: HighlighterStyleType = { + name: "oneDark", + style: oneDark, +}; // TODO: add custom loading and error handling const defaultState: AppState = { @@ -29,7 +38,7 @@ const defaultState: AppState = { theme: "dark", toggleTheme: () => {}, highlighterStyle: defaultHighlighterStyle, - setHighlighterStyle: () => {}, + toggleHighlighterStyle: () => {}, }; const AppContext = createContext(defaultState); @@ -48,7 +57,13 @@ export const AppProvider: FC<{ children: React.ReactNode }> = ({ ); const [highlighterStyle, setHighlighterStyle] = useState< AppState["highlighterStyle"] - >(defaultHighlighterStyle); + >( + localStorage.getItem("highlighterStyleName") + ? highlighterStyles.find( + (style) => style.name === localStorage.getItem("highlighterStyleName") + ) || defaultHighlighterStyle + : defaultHighlighterStyle + ); const toggleTheme = useCallback(() => { const newTheme = theme === "dark" ? "light" : "dark"; @@ -57,6 +72,13 @@ export const AppProvider: FC<{ children: React.ReactNode }> = ({ document.documentElement.setAttribute("data-theme", newTheme); }, [theme]); + const toggleHighlighterStyle = ( + newHighlighterStyle: HighlighterStyleType + ) => { + setHighlighterStyle(newHighlighterStyle); + localStorage.setItem("highlighterStyleName", newHighlighterStyle.name); + }; + /** * set the theme on initial load */ @@ -77,7 +99,7 @@ export const AppProvider: FC<{ children: React.ReactNode }> = ({ theme, toggleTheme, highlighterStyle, - setHighlighterStyle, + toggleHighlighterStyle, }} > {children} diff --git a/src/types/index.ts b/src/types/index.ts index a2c7647a..8fb1ea4d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -31,9 +31,7 @@ export type AppState = { theme: "dark" | "light"; toggleTheme: () => void; highlighterStyle: HighlighterStyleType; - setHighlighterStyle: React.Dispatch< - React.SetStateAction - >; + toggleHighlighterStyle: (_: HighlighterStyleType) => void; }; export interface SelectorOption { From f205b8837b5fe4124c78cb5d054c45e25d74e2d3 Mon Sep 17 00:00:00 2001 From: Neil Murphy Date: Wed, 1 Jan 2025 18:45:29 +0000 Subject: [PATCH 5/8] language persisted in localStorage --- src/components/LanguageSelector.tsx | 4 ++-- src/contexts/AppContext.tsx | 35 +++++++++++++++++++++++++++-- src/types/index.ts | 2 +- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/components/LanguageSelector.tsx b/src/components/LanguageSelector.tsx index 1be4468b..e273f5e1 100644 --- a/src/components/LanguageSelector.tsx +++ b/src/components/LanguageSelector.tsx @@ -7,7 +7,7 @@ import { SelectorOption } from "@types"; import Selector from "./Selector"; const LanguageSelector = () => { - const { language, setLanguage } = useAppContext(); + const { language, toggleLanguage } = useAppContext(); const { fetchedLanguages, loading, error } = useLanguages(); const options = useMemo( @@ -24,7 +24,7 @@ const LanguageSelector = () => { if (!selected) { return; } - setLanguage(selected); + toggleLanguage(selected); }; if (loading) { diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx index 7ad5fd19..c0fcc184 100644 --- a/src/contexts/AppContext.tsx +++ b/src/contexts/AppContext.tsx @@ -9,6 +9,7 @@ import { import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism"; import { highlighterStyles } from "@consts/highlighter-styles"; +import { useLanguages } from "@hooks/useLanguages"; import { AppState, HighlighterStyleType, @@ -30,7 +31,7 @@ const defaultHighlighterStyle: HighlighterStyleType = { // TODO: add custom loading and error handling const defaultState: AppState = { language: defaultLanguage, - setLanguage: () => {}, + toggleLanguage: () => {}, category: "", setCategory: () => {}, snippet: null, @@ -46,6 +47,8 @@ const AppContext = createContext(defaultState); export const AppProvider: FC<{ children: React.ReactNode }> = ({ children, }) => { + const { fetchedLanguages } = useLanguages(); + const [language, setLanguage] = useState(defaultLanguage); const [category, setCategory] = useState(""); const [snippet, setSnippet] = useState(null); @@ -65,6 +68,11 @@ export const AppProvider: FC<{ children: React.ReactNode }> = ({ : defaultHighlighterStyle ); + const toggleLanguage = (newLanguage: LanguageType) => { + setLanguage(newLanguage); + localStorage.setItem("languageName", newLanguage.lang); + }; + const toggleTheme = useCallback(() => { const newTheme = theme === "dark" ? "light" : "dark"; setTheme(newTheme); @@ -79,6 +87,29 @@ export const AppProvider: FC<{ children: React.ReactNode }> = ({ localStorage.setItem("highlighterStyleName", newHighlighterStyle.name); }; + /** + * check if the language is saved in local storage + */ + useEffect(() => { + if (fetchedLanguages.length === 0) { + return; + } + + const languageName = localStorage.getItem("languageName"); + if (!languageName) { + return; + } + + const selected = fetchedLanguages.find( + (lang) => lang.lang === languageName + ); + if (!selected) { + return; + } + + setLanguage(selected); + }, [fetchedLanguages]); + /** * set the theme on initial load */ @@ -91,7 +122,7 @@ export const AppProvider: FC<{ children: React.ReactNode }> = ({ >; + toggleLanguage: (_: LanguageType) => void; category: string; setCategory: React.Dispatch>; snippet: SnippetType | null; From 4105d60dad454879b1c95cb3ce290d97fcae9871 Mon Sep 17 00:00:00 2001 From: Neil Murphy Date: Thu, 2 Jan 2025 12:54:21 +0000 Subject: [PATCH 6/8] fix selector overflow issue with ellipsis --- src/styles/main.css | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/styles/main.css b/src/styles/main.css index ebd1b909..8d0ffc77 100644 --- a/src/styles/main.css +++ b/src/styles/main.css @@ -331,15 +331,22 @@ abbr { border-radius: var(--br-md); cursor: pointer; - display: grid; - grid-template-columns: 1fr auto; + display: flex; align-items: center; + justify-content: space-between; } .selector__value { display: flex; gap: 0.5em; align-items: center; + width: calc(100% - 30px); +} + +.selector__value > span { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } .selector__value img { @@ -451,7 +458,7 @@ abbr { } .header__highlighter-style-selector { - width: 250px; + width: 280px; } .primary-nav { From 69c33fc24f2ace626894c84a344e0a594d1b5954 Mon Sep 17 00:00:00 2001 From: Neil Murphy Date: Thu, 2 Jan 2025 13:12:29 +0000 Subject: [PATCH 7/8] cspell ignore highlighter-styles.ts --- cspell.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cspell.json b/cspell.json index 86c63589..e7ee57ab 100644 --- a/cspell.json +++ b/cspell.json @@ -11,6 +11,7 @@ "ignorePaths": [ "node_modules", "dist", - "public" + "public", + "src/consts/highlighter-styles.ts" ] } From 5bbd91b007c571ad0c4e20b0166aff65e948fb89 Mon Sep 17 00:00:00 2001 From: Neil Murphy Date: Thu, 2 Jan 2025 13:22:08 +0000 Subject: [PATCH 8/8] JS lang text should be uppercase, reverting to Prism instead of PrismLight --- src/components/CodePreview.tsx | 2 +- src/contexts/AppContext.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/CodePreview.tsx b/src/components/CodePreview.tsx index 05b1ea5e..7b73b684 100644 --- a/src/components/CodePreview.tsx +++ b/src/components/CodePreview.tsx @@ -1,4 +1,4 @@ -import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter"; +import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { useAppContext } from "@contexts/AppContext"; diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx index c0fcc184..c347d50f 100644 --- a/src/contexts/AppContext.tsx +++ b/src/contexts/AppContext.tsx @@ -19,7 +19,7 @@ import { // tokens const defaultLanguage: LanguageType = { - lang: "JavaScript", + lang: "JAVASCRIPT", icon: "/icons/javascript.svg", };