diff --git a/src/components/Instructions/InstructionItem.tsx b/src/components/Instructions/InstructionItem.tsx index 525ee2c..2b26b57 100644 --- a/src/components/Instructions/InstructionItem.tsx +++ b/src/components/Instructions/InstructionItem.tsx @@ -9,8 +9,9 @@ import { TableCell, TableRow } from "../ui/table"; import { ProgramRow } from "."; import { useAppSelector } from "@/store/hooks.ts"; import { selectWorkers, WorkerState } from "@/store/workers/workersSlice.ts"; -import { hexToRgb } from "@/lib/utils.ts"; +import { hexToRgb, invertHexColor } from "@/lib/utils.ts"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip.tsx"; +import useDarkMode from "@/hooks/useDarkMode.ts"; const getWorkerValueFromState = ( worker: WorkerState, @@ -73,6 +74,7 @@ export const InstructionItem = forwardRef( ref: ForwardedRef, ) => { const { numeralSystem } = useContext(NumeralSystemContext); + const isDarkMode = useDarkMode(); const workers = useAppSelector(selectWorkers); const workersWithCurrentPc = workers.filter((worker) => worker.currentState.pc === programRow.address); @@ -81,7 +83,7 @@ export const InstructionItem = forwardRef( onClick(programRow); }, [programRow, onClick]); - const { backgroundColor, hasTooltip } = getHighlightStatus(workers, programRow, status); + const { backgroundColor, hasTooltip } = getHighlightStatus(workers, programRow, status, isDarkMode); const renderContent = () => { return ( @@ -161,7 +163,7 @@ export const InstructionItem = forwardRef( }, ); -function getHighlightStatus(workers: WorkerState[], programRow: ProgramRow, status?: Status) { +function getHighlightStatus(workers: WorkerState[], programRow: ProgramRow, status?: Status, isDarkMode?: boolean) { const pcInAllWorkers = (state: "currentState" | "previousState") => workers.map((worker) => getWorkerValueFromState(worker, state, "pc")); @@ -177,7 +179,11 @@ function getHighlightStatus(workers: WorkerState[], programRow: ProgramRow, stat pcInAllWorkers("currentState").length; const blockBackground = programRow.block.number % 2 === 0 ? "#fff" : "#efefef"; - const backgroundColor = isHighlighted ? `rgba(${hexToRgb(bgColor)}, ${bgOpacity})` : blockBackground; + const backgroundColor = isHighlighted + ? `rgba(${hexToRgb(bgColor)}, ${bgOpacity})` + : isDarkMode + ? invertHexColor(blockBackground) + : blockBackground; return { backgroundColor, diff --git a/src/components/MemoryPreview/index.tsx b/src/components/MemoryPreview/index.tsx index 06036ed..034429a 100644 --- a/src/components/MemoryPreview/index.tsx +++ b/src/components/MemoryPreview/index.tsx @@ -51,8 +51,8 @@ const MemoryCell = ({ (); const [assembly, setAssembly] = useState(defaultAssembly); const [isFirstCompilation, setFirstCompilation] = useState(true); + const isDarkMode = useDarkMode(); // compile the assembly for the first time useEffect(() => { @@ -194,6 +196,7 @@ export const Assembly = ({ height="100%" placeholder="Try writing some PolkaVM assembly code." value={assembly} + theme={isDarkMode ? "dark" : "light"} onChange={(value) => compile(value)} /> diff --git a/src/components/ui/multi-select.tsx b/src/components/ui/multi-select.tsx index b7e7e3d..ba26e8d 100644 --- a/src/components/ui/multi-select.tsx +++ b/src/components/ui/multi-select.tsx @@ -222,13 +222,13 @@ export const MultiSelect = React.forwardRef selectedValues.slice(0, maxCount).map((value) => { const option = options.find((o) => o.value === value); return ( - + {option?.label} ); })} {!showOptionsAsTags && selectedValues.length > maxCount && ( - {selectedValues.length} PVMs in parallel + {selectedValues.length} PVMs in parallel )} {showOptionsAsTags && selectedValues.slice(0, maxCount).map((value) => { diff --git a/src/globals.css b/src/globals.css index 1e610ae..916cf42 100644 --- a/src/globals.css +++ b/src/globals.css @@ -35,21 +35,21 @@ .dark { --background: 190 84% 4.9%; - --foreground: 210 40% 98%; + --foreground: 210 40% 90%; --card: 190 84% 4.9%; - --card-foreground: 210 40% 98%; + --card-foreground: 210 40% 90%; --popover: 190 84% 4.9%; - --popover-foreground: 210 40% 98%; - --primary: 210 40% 98%; + --popover-foreground: 210 40% 90%; + --primary: 210 40% 90%; --primary-foreground: 190 47.4% 11.2%; --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; + --secondary-foreground: 210 40% 90%; --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; + --accent-foreground: 210 40% 90%; --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; + --destructive-foreground: 210 40% 90%; --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; --ring: 212.7 26.8% 83.9%; @@ -69,3 +69,7 @@ @apply bg-background text-foreground; } } + +::file-selector-button { + @apply bg-background text-foreground; +} diff --git a/src/hooks/useDarkMode.ts b/src/hooks/useDarkMode.ts new file mode 100644 index 0000000..68b3eeb --- /dev/null +++ b/src/hooks/useDarkMode.ts @@ -0,0 +1,14 @@ +import { useEffect, useState } from "react"; + +const useDarkMode = () => { + const [isDarkMode, setIsDarkMode] = useState(false); + + useEffect(() => { + const htmlElement = document.documentElement; + setIsDarkMode(htmlElement.classList.contains("dark")); + }, []); + + return isDarkMode; +}; + +export default useDarkMode; diff --git a/src/lib/utils.ts b/src/lib/utils.ts index afa7434..6dc47e7 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -12,3 +12,18 @@ export const hexToRgb = (hex: string) => { const b = bigint & 255; return `${r}, ${g}, ${b}`; }; + +export const invertHexColor = (hex: string) => { + hex = hex.replace(/^#/, ""); + + if (hex.length === 3) { + hex = hex + .split("") + .map((char) => char + char) + .join(""); + } + + const invertedColor = (0xffffff ^ parseInt(hex, 16)).toString(16).padStart(6, "0"); + + return `#${invertedColor}`; +}; diff --git a/src/main.tsx b/src/main.tsx index 291c14a..e5c340d 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -6,6 +6,8 @@ import { NumeralSystemProvider } from "@/context/NumeralSystemProvider"; import { Provider } from "react-redux"; import { store } from "./store"; +document.documentElement.classList.toggle("dark", window.matchMedia("(prefers-color-scheme: dark)").matches); + ReactDOM.createRoot(document.getElementById("root")!).render( // TODO: strict mode is disabled because of the App useEffect for init being called twice //