From b7b072f6d27da828859ff76c81f528ba1f03b436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Fri, 21 Nov 2025 09:17:12 +0100 Subject: [PATCH] feat: improve UI and transparency support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UI Improvements: - Style scrollbars with primary color accent - Scrollbar thumb transitions on hover (40% → 60% → 80% opacity) - Add fill tool options to toolbar (color picker + opacity) - Support for Firefox with scrollbar-color property Transparency Support: - Set default canvas background to transparent - First layer now transparent instead of white fill - Enables creating images with transparency - Checkerboard pattern shows through transparent areas - Proper PNG export support with alpha channel 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/globals.css | 9 +++--- components/editor/editor-layout.tsx | 4 +-- components/editor/tool-options.tsx | 47 +++++++++++++++++++++++++++-- store/canvas-store.ts | 2 +- 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/app/globals.css b/app/globals.css index 5a6ebf5..3cd1ab1 100644 --- a/app/globals.css +++ b/app/globals.css @@ -156,9 +156,10 @@ font-feature-settings: "rlig" 1, "calt" 1; } - /* Apply custom scrollbar globally */ + /* Apply custom scrollbar globally with primary color accent */ * { scrollbar-width: thin; + scrollbar-color: color-mix(in oklch, var(--primary) 40%, transparent) var(--muted); } *::-webkit-scrollbar { @@ -172,18 +173,18 @@ } *::-webkit-scrollbar-thumb { - background: color-mix(in oklch, var(--muted-foreground) 30%, transparent); + background: color-mix(in oklch, var(--primary) 40%, transparent); border-radius: 5px; border: 2px solid var(--muted); transition: background 0.2s ease; } *::-webkit-scrollbar-thumb:hover { - background: color-mix(in oklch, var(--muted-foreground) 50%, transparent); + background: color-mix(in oklch, var(--primary) 60%, transparent); } *::-webkit-scrollbar-thumb:active { - background: color-mix(in oklch, var(--muted-foreground) 70%, transparent); + background: color-mix(in oklch, var(--primary) 80%, transparent); } /* Scrollbar corners */ diff --git a/components/editor/editor-layout.tsx b/components/editor/editor-layout.tsx index 4e899d2..8cf5803 100644 --- a/components/editor/editor-layout.tsx +++ b/components/editor/editor-layout.tsx @@ -37,10 +37,10 @@ export function EditorLayout() { if (layers.length === 0) { const { createLayer } = useLayerStore.getState(); createLayer({ - name: 'Background', + name: 'Layer 1', width: 800, height: 600, - fillColor: '#ffffff', + // No fillColor - layer is transparent by default }); } }, []); diff --git a/components/editor/tool-options.tsx b/components/editor/tool-options.tsx index 3c3a868..f557f5c 100644 --- a/components/editor/tool-options.tsx +++ b/components/editor/tool-options.tsx @@ -12,9 +12,12 @@ export function ToolOptions() { // Drawing tools: brush, pencil, eraser const isDrawingTool = ['brush', 'eraser', 'pencil'].includes(activeTool); const showHardness = ['brush'].includes(activeTool); - const showColor = ['brush', 'pencil', 'fill'].includes(activeTool); + const showColor = ['brush', 'pencil'].includes(activeTool); const showFlow = ['brush'].includes(activeTool); + // Fill tool + const isFillTool = activeTool === 'fill'; + // Shape tool const isShapeTool = activeTool === 'shape'; @@ -22,7 +25,7 @@ export function ToolOptions() { const isSelectionTool = activeTool === 'select'; // Don't show options bar if no options available - if (!isDrawingTool && !isShapeTool && !isSelectionTool) { + if (!isDrawingTool && !isFillTool && !isShapeTool && !isSelectionTool) { return null; } @@ -125,6 +128,46 @@ export function ToolOptions() { )} + {/* Fill Tool Options */} + {isFillTool && ( + <> +
+ + setColor(e.target.value)} + className="h-8 w-16 rounded border border-border cursor-pointer" + /> + setColor(e.target.value)} + className="w-24 px-2 py-1 text-xs rounded border border-border bg-background text-foreground" + /> +
+ +
+ + setOpacity(Number(e.target.value) / 100)} + className="w-32" + /> + + {Math.round(settings.opacity * 100)}% + +
+ + )} + {/* Shape Tool Options */} {isShapeTool && (
diff --git a/store/canvas-store.ts b/store/canvas-store.ts index c22273c..76e355f 100644 --- a/store/canvas-store.ts +++ b/store/canvas-store.ts @@ -58,7 +58,7 @@ export const useCanvasStore = create()( zoom: 1, offsetX: 0, offsetY: 0, - backgroundColor: '#ffffff', + backgroundColor: 'transparent', showGrid: false, gridSize: 20, showRulers: true,