Skip to content

Commit 0d2f07b

Browse files
committed
refactor: Improve canvas color system using filters to handle dark and light mode dynamically
1 parent 779ad4b commit 0d2f07b

File tree

9 files changed

+175
-1351
lines changed

9 files changed

+175
-1351
lines changed

apps/collabydraw/app/globals.css

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ h6 {
188188
--color-promo: var(--color-primary);
189189

190190
--selection-box-border-color: #6965db;
191+
--theme-filter: none;
191192
}
192193

193194
.dark {
@@ -272,6 +273,7 @@ h6 {
272273
--color-promo: var(--color-primary);
273274

274275
--selection-box-border-color: #a8a5ff;
276+
--theme-filter: invert(93%) hue-rotate(180deg);
275277
}
276278
}
277279

@@ -432,11 +434,11 @@ button {
432434
height: 1.35rem;
433435
border: 1px solid #d6d6d6;
434436
border-radius: 4px;
435-
filter: none;
436437
background-position: left center;
437438
position: relative;
438439
font-family: inherit;
439440
box-sizing: border-box;
441+
filter: var(--theme-filter);
440442
}
441443

442444
.color-picker__button:hover:after {
@@ -448,7 +450,6 @@ button {
448450
bottom: -2px;
449451
box-shadow: 0 0 0 1px #d6d6d6;
450452
border-radius: 5px;
451-
filter: none;
452453
}
453454

454455
.color-picker__button.active .color-picker__button-outline {
@@ -463,6 +464,16 @@ button {
463464
filter: none;
464465
}
465466

467+
.color-picker__button.is-transparent {
468+
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==)
469+
}
470+
471+
.color-picker__button.active-color {
472+
border-radius: calc(var(--radius) + 1px);
473+
width: 1.625rem;
474+
height: 1.625rem;
475+
}
476+
466477
.popover-tooltip-arrow-pointer {
467478
position: absolute;
468479
left: 0px;
@@ -716,4 +727,15 @@ button {
716727
.dark .collabydraw .welcome-screen-menu-item:active .welcome-screen-menu-item__icon,
717728
.dark .collabydraw .welcome-screen-menu-item:active .welcome-screen-menu-item__text {
718729
color: var(--color-gray-10);
730+
}
731+
732+
.dark .collabydraw-canvas,
733+
.dark .collabydraw-canvas-dark {
734+
filter: var(--theme-filter);
735+
position: absolute;
736+
z-index: 2;
737+
}
738+
739+
.canvas-bg-color-item {
740+
filter: var(--theme-filter);
719741
}

apps/collabydraw/components/canvas/CanvasSheet.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useWebSocket } from "@/hooks/useWebSocket";
44
import { Game } from "@/draw/Game";
5-
import { BgFill, canvasBgDark, canvasBgLight, Shape, StrokeEdge, StrokeFill, StrokeWidth, ToolType } from "@/types/canvas";
5+
import { BgFill, canvasBgLight, Shape, StrokeEdge, StrokeFill, StrokeStyle, StrokeWidth, ToolType } from "@/types/canvas";
66
import { useCallback, useEffect, useRef, useState } from "react";
77
import { Scale } from "../Scale";
88
import { MobileNavbar } from "../mobile-navbar";
@@ -14,6 +14,7 @@ import { useMediaQuery } from "@/hooks/useMediaQuery";
1414
import Toolbar from "../Toolbar";
1515
import ScreenLoading from "../ScreenLoading";
1616
import CollaborationStart from "../CollaborationStartBtn";
17+
import { cn } from "@/lib/utils";
1718

1819
export function CanvasSheet({ roomName, roomId, userId, userName }: { roomName: string; roomId: string; userId: string; userName: string; }) {
1920
const { theme } = useTheme()
@@ -25,16 +26,18 @@ export function CanvasSheet({ roomName, roomId, userId, userName }: { roomName:
2526
const [strokeWidth, setStrokeWidth] = useState<StrokeWidth>(1);
2627
const [bgFill, setBgFill] = useState<BgFill>("#00000000");
2728
const [strokeEdge, setStrokeEdge] = useState<StrokeEdge>("round");
29+
const [strokeStyle, setStrokeStyle] = useState<StrokeStyle>("solid");
2830
const [grabbing, setGrabbing] = useState(false);
2931
const [existingShapes, setExistingShapes] = useState<Shape[]>([]);
3032
const paramsRef = useRef({ roomId, roomName, userId, userName });
3133
const activeToolRef = useRef(activeTool);
3234
const strokeFillRef = useRef(strokeFill);
3335
const strokeWidthRef = useRef(strokeWidth);
3436
const strokeEdgeRef = useRef(strokeEdge);
37+
const strokeStyleRef = useRef(strokeStyle);
3538
const bgFillRef = useRef(bgFill);
3639
const [sidebarOpen, setSidebarOpen] = useState(false);
37-
const [canvasColor, setCanvasColor] = useState<string>(theme === 'light' ? canvasBgLight[0] : canvasBgDark[0]);
40+
const [canvasColor, setCanvasColor] = useState<string>(canvasBgLight[0]);
3841
const canvasColorRef = useRef(canvasColor);
3942

4043
const { isConnected, messages, sendMessage } = useWebSocket(
@@ -47,8 +50,8 @@ export function CanvasSheet({ roomName, roomId, userId, userName }: { roomName:
4750
const { matches, isLoading } = useMediaQuery('md');
4851

4952
useEffect(() => {
50-
setCanvasColor(theme === 'light' ? canvasBgLight[0] : canvasBgDark[0]);
51-
}, [theme]);
53+
setCanvasColor(canvasBgLight[0]);
54+
}, [theme])
5255

5356
useEffect(() => {
5457
const handleResize = () => {
@@ -107,6 +110,11 @@ export function CanvasSheet({ roomName, roomId, userId, userName }: { roomName:
107110
game?.setStrokeEdge(strokeEdge);
108111
}, [strokeEdge, game]);
109112

113+
useEffect(() => {
114+
strokeStyleRef.current = strokeStyle;
115+
game?.setStrokeStyle(strokeStyle);
116+
}, [strokeStyle, game]);
117+
110118
useEffect(() => {
111119
activeToolRef.current = activeTool;
112120
game?.setTool(activeTool);
@@ -249,7 +257,7 @@ export function CanvasSheet({ roomName, roomId, userId, userName }: { roomName:
249257

250258
return (
251259
<div className={`collabydraw h-screen overflow-hidden ${(activeTool === "grab" && !sidebarOpen) ? (grabbing ? "cursor-grabbing" : "cursor-grab") : "cursor-crosshair"} `}>
252-
<div className="App_Menu App_Menu_Top fixed top-4 right-4 left-4 flex justify-center items-center md:grid md:grid-cols-[1fr_auto_1fr] md:gap-8 md:items-start">
260+
<div className="App_Menu App_Menu_Top fixed z-[4] top-4 right-4 left-4 flex justify-center items-center md:grid md:grid-cols-[1fr_auto_1fr] md:gap-8 md:items-start">
253261
{matches && (
254262
<div className="Main_Menu_Stack Sidebar_Trigger_Button md:grid md:gap-[calc(.25rem*6)] grid-cols-[auto] grid-flow-row grid-rows auto-rows-min justify-self-start">
255263
<div className="relative">
@@ -275,6 +283,8 @@ export function CanvasSheet({ roomName, roomId, userId, userName }: { roomName:
275283
setBgFill={setBgFill}
276284
strokeEdge={strokeEdge}
277285
setStrokeEdge={setStrokeEdge}
286+
strokeStyle={strokeStyle}
287+
setStrokeStyle={setStrokeStyle}
278288
/>
279289
</div>
280290
)}
@@ -311,7 +321,7 @@ export function CanvasSheet({ roomName, roomId, userId, userName }: { roomName:
311321
roomName={roomName}
312322
/>
313323
)}
314-
<canvas ref={canvasRef} />
324+
<canvas className={cn("collabydraw collabydraw-canvas", theme === 'dark' ? 'collabydraw-canvas-dark' : '')} ref={canvasRef} />
315325
</div >
316326
)
317327
}

apps/collabydraw/components/canvas/StandaloneCanvas.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client"
22

33
import { Game } from "@/draw/Game";
4-
import { BgFill, canvasBgDark, canvasBgLight, LOCALSTORAGE_CANVAS_KEY, Shape, StrokeEdge, StrokeFill, StrokeStyle, StrokeWidth, ToolType } from "@/types/canvas";
4+
import { BgFill, canvasBgLight, LOCALSTORAGE_CANVAS_KEY, Shape, StrokeEdge, StrokeFill, StrokeStyle, StrokeWidth, ToolType } from "@/types/canvas";
55
import { useCallback, useEffect, useRef, useState } from "react";
66
import { Scale } from "../Scale";
77
import Toolbar from "../Toolbar";
@@ -14,6 +14,7 @@ import { HomeWelcome, MainMenuWelcome, ToolMenuWelcome } from "../welcome-screen
1414
import { useMediaQuery } from "@/hooks/useMediaQuery";
1515
import ScreenLoading from "../ScreenLoading";
1616
import CollaborationStart from "../CollaborationStartBtn";
17+
import { cn } from "@/lib/utils";
1718

1819
export function StandaloneCanvas() {
1920
const { theme } = useTheme()
@@ -35,7 +36,7 @@ export function StandaloneCanvas() {
3536
const strokeStyleRef = useRef(strokeStyle);
3637
const bgFillRef = useRef(bgFill);
3738
const [sidebarOpen, setSidebarOpen] = useState(false);
38-
const [canvasColor, setCanvasColor] = useState<string>(theme === 'light' ? canvasBgLight[0] : canvasBgDark[0]);
39+
const [canvasColor, setCanvasColor] = useState<string>(canvasBgLight[0]);
3940
const canvasColorRef = useRef(canvasColor);
4041
const [isCanvasEmpty, setIsCanvasEmpty] = useState(true);
4142

@@ -83,7 +84,7 @@ export function StandaloneCanvas() {
8384
}, [game]);
8485

8586
useEffect(() => {
86-
setCanvasColor(theme === 'light' ? canvasBgLight[0] : canvasBgDark[0]);
87+
setCanvasColor(canvasBgLight[0]);
8788
}, [theme])
8889

8990
useEffect(() => {
@@ -293,7 +294,7 @@ export function StandaloneCanvas() {
293294
return (
294295
<div data-isloading={isLoading} data-matches={matches} className={`collabydraw h-screen overflow-hidden ${(activeTool === "grab" && !sidebarOpen) ? (grabbing ? "cursor-grabbing" : "cursor-grab") : "cursor-crosshair"} `}>
295296
{!isLoading && (
296-
<div className="App_Menu App_Menu_Top fixed top-4 right-4 left-4 flex justify-center items-center md:grid md:grid-cols-[1fr_auto_1fr] md:gap-8 md:items-start">
297+
<div className="App_Menu App_Menu_Top fixed z-[4] top-4 right-4 left-4 flex justify-center items-center md:grid md:grid-cols-[1fr_auto_1fr] md:gap-8 md:items-start">
297298
{matches && !isLoading && (
298299
<div className="Main_Menu_Stack Sidebar_Trigger_Button md:grid md:gap-[calc(.25rem*6)] grid-cols-[auto] grid-flow-row grid-rows auto-rows-min justify-self-start">
299300
<div className="relative">
@@ -382,7 +383,7 @@ export function StandaloneCanvas() {
382383
<ScreenLoading />
383384
)}
384385

385-
<canvas ref={canvasRef} />
386+
<canvas className={cn("collabydraw collabydraw-canvas", theme === 'dark' ? 'collabydraw-canvas-dark' : '')} ref={canvasRef} />
386387

387388
</div >
388389
)

apps/collabydraw/components/color-board.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export function ColorBoard({
5656
<div className="">
5757
<ItemLabel label="Background" />
5858
<div className="relative">
59-
<div className="color-picker-container grid grid-cols-[1fr_1.5rem_2.5rem] md:grid-cols-[1fr_20px_1.625rem] max-w-[17rem] md:max-w-80 py-1 px-0 items-center">
59+
<div className="color-picker-container grid grid-cols-[1fr_1.5rem_2.5rem] md:grid-cols-[1fr_20px_1.625rem] max-w-[17rem] md:max-w-80 py-1 px-0 items-center">
6060
<div className="flex items-center justify-between">
6161
{bgFills.map((color) => (
6262
<ColorPickerButton
@@ -82,9 +82,9 @@ function ColorPickerButton({ color, isSelected, onClick }: { color: string; isSe
8282
return (
8383
<button
8484
className={cn(
85-
"w-[1.35rem] h-[1.35rem] rounded-md border ring-0 transition-all hover:scale-110 focus:outline-none color-picker__button",
85+
"color-picker__button w-[1.35rem] h-[1.35rem] rounded-md border ring-0 transition-all hover:scale-110 focus:outline-none",
8686
isSelected && "active",
87-
color === "#00000000" ? "bg-[url('/bg-transparent-checkerboard.png')] dark:bg-[url('/checkerboard-dark.png')] bg-cover bg-center" : ""
87+
color === "#00000000" ? "is-transparent" : ""
8888
)}
8989
style={color !== "#00000000" ? { backgroundColor: color } : {}}
9090
onClick={onClick}
@@ -135,7 +135,9 @@ function ColorPopover<T extends string>({
135135
<Popover>
136136
<PopoverTrigger asChild>
137137
<button
138-
className="w-[1.625rem] h-[1.625rem] rounded-md border transition-all hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring ring-2 ring-ring ring-offset-2 ring-offset-background"
138+
className={cn("color-picker__button active-color w-[1.625rem] h-[1.625rem] rounded-md border transition-all hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring ring-2 ring-ring ring-offset-2 ring-offset-background",
139+
selectedColor === "#00000000" ? "is-transparent" : ""
140+
)}
139141
style={{ backgroundColor: selectedColor }}
140142
aria-label={`Selected color ${selectedColor}`}
141143
>

apps/collabydraw/components/color-picker.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Check, Edit } from "lucide-react"
77
import { Button } from "@/components/ui/button"
88
import { Input } from "@/components/ui/input"
99
import { cn } from "@/lib/utils"
10-
import { canvasBgDark, canvasBgLight } from "@/types/canvas"
10+
import { canvasBgLight } from "@/types/canvas"
1111
import { useTheme } from "next-themes"
1212

1313
interface ColorPickerProps {
@@ -19,10 +19,10 @@ export function ColorPicker({ value, onChange }: ColorPickerProps) {
1919
const [isEditing, setIsEditing] = useState(false)
2020
const [inputValue, setInputValue] = useState(value)
2121
const { theme } = useTheme()
22-
const [canvasBg, setCanvasBg] = useState(theme === "dark" ? canvasBgDark : canvasBgLight);
22+
const [canvasBg, setCanvasBg] = useState(canvasBgLight);
2323

2424
useEffect(() => {
25-
setCanvasBg(theme === "dark" ? canvasBgDark : canvasBgLight);
25+
setCanvasBg(canvasBgLight);
2626
}, [theme])
2727

2828
useEffect(() => {
@@ -70,7 +70,7 @@ export function ColorPicker({ value, onChange }: ColorPickerProps) {
7070
<button
7171
key={color}
7272
className={cn(
73-
"h-8 w-8 rounded-md border transition-all hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring",
73+
"canvas-bg-color-item h-8 w-8 rounded-md border transition-all hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring",
7474
color === value && "ring-2 ring-ring ring-offset-2 ring-offset-background",
7575
)}
7676
style={{ backgroundColor: color }}

0 commit comments

Comments
 (0)