fix: change colors based on which color scheme
This commit is contained in:
parent
2c852694ea
commit
a5bea3b585
9 changed files with 48 additions and 43 deletions
|
|
@ -8,6 +8,7 @@ import { ImageContext } from "@/context/Image";
|
|||
import { LoadingContext } from "@/context/Loading";
|
||||
import { SettingsContext } from "@/context/Settings";
|
||||
import { TexturesContext } from "@/context/Textures";
|
||||
import { ThemeContext } from "@/context/Theme";
|
||||
import { ToolContext } from "@/context/Tool";
|
||||
|
||||
import Blocks from "./Blocks";
|
||||
|
|
@ -29,6 +30,7 @@ function Canvas() {
|
|||
const { setLoading } = useContext(LoadingContext);
|
||||
const { settings } = useContext(SettingsContext);
|
||||
const { missingTexture, textures, solidTextures } = useContext(TexturesContext);
|
||||
const { isDark } = useContext(ThemeContext);
|
||||
const { tool, radius, selectedBlock, cssCursor, setTool, setSelectedBlock, setCssCursor } = useContext(ToolContext);
|
||||
|
||||
const stageContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
|
@ -278,7 +280,7 @@ function Canvas() {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div ref={stageContainerRef} className="relative w-full h-full" style={{ cursor: cssCursor }}>
|
||||
<div ref={stageContainerRef} className="relative w-full h-full bg-zinc-200 dark:bg-black" style={{ cursor: cssCursor }}>
|
||||
<Stage
|
||||
width={stageSize.width}
|
||||
height={stageSize.height}
|
||||
|
|
@ -287,6 +289,7 @@ function Canvas() {
|
|||
onMouseUp={onMouseUp}
|
||||
onWheel={onWheel}
|
||||
onClick={onClick}
|
||||
options={{ backgroundAlpha: 0 }}
|
||||
>
|
||||
<Blocks
|
||||
blocks={visibleBlocks}
|
||||
|
|
@ -302,13 +305,13 @@ function Canvas() {
|
|||
/>
|
||||
|
||||
<Container x={coords.x} y={coords.y} scale={scale}>
|
||||
{settings.canvasBorder && <CanvasBorder canvasSize={canvasSize} />}
|
||||
<Cursor mouseCoords={mouseCoords} radius={radius} />
|
||||
{settings.canvasBorder && <CanvasBorder canvasSize={canvasSize} isDark={isDark} />}
|
||||
<Cursor mouseCoords={mouseCoords} radius={radius} isDark={isDark} />
|
||||
</Container>
|
||||
|
||||
{settings.grid && (
|
||||
<Container>
|
||||
<Grid stageSize={stageSize} coords={coords} scale={scale} />
|
||||
<Grid stageSize={stageSize} coords={coords} scale={scale} isDark={isDark} />
|
||||
</Container>
|
||||
)}
|
||||
</Stage>
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@ import { Graphics } from "@pixi/react";
|
|||
|
||||
interface Props {
|
||||
canvasSize: CanvasSize;
|
||||
isDark: boolean;
|
||||
}
|
||||
|
||||
function CanvasBorder({ canvasSize }: Props) {
|
||||
function CanvasBorder({ canvasSize, isDark }: Props) {
|
||||
return (
|
||||
<Graphics
|
||||
draw={(g) => {
|
||||
g.clear();
|
||||
g.lineStyle(2, 0xffffff, 0.25, 1);
|
||||
g.lineStyle(2, isDark ? 0xffffff : 0x000000, 0.25, 1);
|
||||
g.drawRect(canvasSize.minX * 16, canvasSize.minY * 16, (canvasSize.maxX - canvasSize.minX) * 16, (canvasSize.maxY - canvasSize.minY) * 16);
|
||||
}}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ import { Graphics } from "@pixi/react";
|
|||
interface Props {
|
||||
mouseCoords: Position;
|
||||
radius: number;
|
||||
isDark: boolean;
|
||||
}
|
||||
|
||||
function Cursor({ mouseCoords, radius }: Props) {
|
||||
function Cursor({ mouseCoords, radius, isDark }: Props) {
|
||||
const isOddRadius = radius % 2 !== 0;
|
||||
const halfSize = Math.floor(radius / 2);
|
||||
|
||||
|
|
@ -18,7 +19,7 @@ function Cursor({ mouseCoords, radius }: Props) {
|
|||
y={(mouseCoords.y + offset) * 16}
|
||||
draw={(g) => {
|
||||
g.clear();
|
||||
g.lineStyle(1, 0xffffff, 1);
|
||||
g.lineStyle(1, isDark ? 0xffffff : 0x000000, 1);
|
||||
g.drawRect(0, 0, size, size);
|
||||
}}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -4,14 +4,15 @@ interface Props {
|
|||
stageSize: Dimension;
|
||||
coords: Position;
|
||||
scale: number;
|
||||
isDark: boolean;
|
||||
}
|
||||
|
||||
function Grid({ stageSize, coords, scale }: Props) {
|
||||
function Grid({ stageSize, coords, scale, isDark }: Props) {
|
||||
return (
|
||||
<Graphics
|
||||
draw={(g) => {
|
||||
g.clear();
|
||||
g.lineStyle(1, 0xffffff, 0.1);
|
||||
g.lineStyle(1, isDark ? 0xffffff : 0x000000, 0.1);
|
||||
|
||||
const tileSize = 16 * scale;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { useContext } from "react";
|
||||
import { ThemeContext } from "@/context/Theme";
|
||||
import { MenubarRadioGroup, MenubarRadioItem, MenubarSub, MenubarSubContent, MenubarSubTrigger } from "@/components/ui/menubar";
|
||||
import { useTheme } from "@/context/Theme";
|
||||
|
||||
function ThemeChanger() {
|
||||
const { setTheme, theme } = useTheme();
|
||||
const { setTheme, theme } = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
<MenubarSub>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { useContext } from "react";
|
||||
import { Link } from "react-router";
|
||||
|
||||
import { Menubar as UIMenubar } from "@/components/ui/menubar";
|
||||
import { DialogProvider } from "@/context/Dialog";
|
||||
import { ThemeContext } from "@/context/Theme";
|
||||
|
||||
import { Menubar as UIMenubar } from "@/components/ui/menubar";
|
||||
|
||||
import FileMenu from "./FileMenu";
|
||||
import ViewMenu from "./ViewMenu";
|
||||
|
|
@ -11,11 +14,13 @@ import BlockmaticText from "@/assets/blockmatic-text.svg?react";
|
|||
import GithubIcon from "@/assets/github.svg?react";
|
||||
|
||||
function Menubar() {
|
||||
const { isDark } = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
<DialogProvider>
|
||||
<UIMenubar className="rounded-none border-t-0 border-x-0 col-span-3">
|
||||
<Link to={{ pathname: "/" }} className="px-4 w-32">
|
||||
<BlockmaticText className="h-full w-full" fill="white" />
|
||||
<BlockmaticText className="h-full w-full" fill={isDark ? "white" : "black"} />
|
||||
</Link>
|
||||
|
||||
<FileMenu />
|
||||
|
|
@ -23,7 +28,7 @@ function Menubar() {
|
|||
<MoreMenu />
|
||||
|
||||
<a href="https://github.com/trafficlunar/blockmatic" className="w-5 absolute right-2">
|
||||
<GithubIcon fill="white" />
|
||||
<GithubIcon fill={isDark ? "white" : "black"} />
|
||||
</a>
|
||||
</UIMenubar>
|
||||
</DialogProvider>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Container, Graphics, Sprite, Stage } from "@pixi/react";
|
|||
import { BlocksIcon } from "lucide-react";
|
||||
|
||||
import { TexturesContext } from "@/context/Textures";
|
||||
import { ThemeContext } from "@/context/Theme";
|
||||
import { ToolContext } from "@/context/Tool";
|
||||
|
||||
import _blockData from "@/data/blocks/programmer-art/data.json";
|
||||
|
|
@ -15,6 +16,7 @@ interface Props {
|
|||
|
||||
function SelectorBlocks({ stageWidth, searchInput }: Props) {
|
||||
const { missingTexture, textures } = useContext(TexturesContext);
|
||||
const { isDark } = useContext(ThemeContext);
|
||||
const { selectedBlock, setSelectedBlock } = useContext(ToolContext);
|
||||
|
||||
const [hoverPosition, setHoverPosition] = useState<Position | null>(null);
|
||||
|
|
@ -82,8 +84,8 @@ function SelectorBlocks({ stageWidth, searchInput }: Props) {
|
|||
y={hoverPosition.y}
|
||||
draw={(g) => {
|
||||
g.clear();
|
||||
g.beginFill("#0000004D");
|
||||
g.lineStyle(2, 0xffffff, 1, 1);
|
||||
g.beginFill(0x000000, 0.5);
|
||||
g.lineStyle(2, isDark ? 0xffffff : 0x000000, 1, 1);
|
||||
g.drawRect(0, 0, 32, 32);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -95,7 +97,7 @@ function SelectorBlocks({ stageWidth, searchInput }: Props) {
|
|||
y={selectedBlockPosition.y}
|
||||
draw={(g) => {
|
||||
g.clear();
|
||||
g.lineStyle(2, 0xffffff, 1, 1);
|
||||
g.lineStyle(2, isDark ? 0xffffff : 0x000000, 1, 1);
|
||||
g.drawRect(0, 0, 32, 32);
|
||||
}}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { createContext, ReactNode, useMemo, useState } from "react";
|
|||
|
||||
interface Context {
|
||||
stageSize: Dimension;
|
||||
canvasSize: Dimension;
|
||||
canvasSize: CanvasSize;
|
||||
blocks: Block[];
|
||||
coords: Position;
|
||||
scale: number;
|
||||
|
|
|
|||
|
|
@ -1,25 +1,22 @@
|
|||
import { createContext, useContext, useEffect, useState } from "react";
|
||||
import { createContext, useEffect, useState } from "react";
|
||||
|
||||
type ThemeProviderProps = {
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
defaultTheme?: Theme;
|
||||
storageKey?: string;
|
||||
};
|
||||
}
|
||||
|
||||
type ThemeProviderState = {
|
||||
interface Context {
|
||||
theme: Theme;
|
||||
isDark: boolean;
|
||||
setTheme: (theme: Theme) => void;
|
||||
};
|
||||
}
|
||||
|
||||
const initialState: ThemeProviderState = {
|
||||
theme: "system",
|
||||
setTheme: () => null,
|
||||
};
|
||||
export const ThemeContext = createContext<Context>({} as Context);
|
||||
|
||||
const ThemeProviderContext = createContext<ThemeProviderState>(initialState);
|
||||
|
||||
export function ThemeProvider({ children, defaultTheme = "system", storageKey = "vite-ui-theme", ...props }: ThemeProviderProps) {
|
||||
export function ThemeProvider({ children, defaultTheme = "system", storageKey = "vite-ui-theme", ...props }: Props) {
|
||||
const [theme, setTheme] = useState<Theme>(() => (localStorage.getItem(storageKey) as Theme) || defaultTheme);
|
||||
const [isDark, setIsDark] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const root = window.document.documentElement;
|
||||
|
|
@ -27,17 +24,19 @@ export function ThemeProvider({ children, defaultTheme = "system", storageKey =
|
|||
root.classList.remove("light", "dark");
|
||||
|
||||
if (theme === "system") {
|
||||
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
|
||||
root.classList.add(systemTheme);
|
||||
root.classList.add(systemTheme ? "dark" : "light");
|
||||
return;
|
||||
}
|
||||
|
||||
root.classList.add(theme);
|
||||
setIsDark(theme == "dark");
|
||||
}, [theme]);
|
||||
|
||||
const value = {
|
||||
theme,
|
||||
isDark,
|
||||
setTheme: (theme: Theme) => {
|
||||
localStorage.setItem(storageKey, theme);
|
||||
setTheme(theme);
|
||||
|
|
@ -45,16 +44,8 @@ export function ThemeProvider({ children, defaultTheme = "system", storageKey =
|
|||
};
|
||||
|
||||
return (
|
||||
<ThemeProviderContext.Provider {...props} value={value}>
|
||||
<ThemeContext.Provider {...props} value={value}>
|
||||
{children}
|
||||
</ThemeProviderContext.Provider>
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const useTheme = () => {
|
||||
const context = useContext(ThemeProviderContext);
|
||||
|
||||
if (context === undefined) throw new Error("useTheme must be used within a ThemeProvider");
|
||||
|
||||
return context;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue