feat: improve UI and transparency support

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 <noreply@anthropic.com>
This commit is contained in:
2025-11-21 09:17:12 +01:00
parent cd59f0606b
commit b7b072f6d2
4 changed files with 53 additions and 9 deletions

View File

@@ -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 */

View File

@@ -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
});
}
}, []);

View File

@@ -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 && (
<>
<div className="flex items-center gap-2">
<label className="text-sm font-medium text-card-foreground whitespace-nowrap">
Color:
</label>
<input
type="color"
value={settings.color}
onChange={(e) => setColor(e.target.value)}
className="h-8 w-16 rounded border border-border cursor-pointer"
/>
<input
type="text"
value={settings.color}
onChange={(e) => setColor(e.target.value)}
className="w-24 px-2 py-1 text-xs rounded border border-border bg-background text-foreground"
/>
</div>
<div className="flex items-center gap-2">
<label className="text-sm font-medium text-card-foreground whitespace-nowrap">
Opacity:
</label>
<input
type="range"
min="0"
max="100"
value={settings.opacity * 100}
onChange={(e) => setOpacity(Number(e.target.value) / 100)}
className="w-32"
/>
<span className="text-sm text-muted-foreground w-10">
{Math.round(settings.opacity * 100)}%
</span>
</div>
</>
)}
{/* Shape Tool Options */}
{isShapeTool && (
<div className="flex items-center gap-2">

View File

@@ -58,7 +58,7 @@ export const useCanvasStore = create<CanvasStore>()(
zoom: 1,
offsetX: 0,
offsetY: 0,
backgroundColor: '#ffffff',
backgroundColor: 'transparent',
showGrid: false,
gridSize: 20,
showRulers: true,