diff --git a/renderer/renderer.ts b/renderer/renderer.ts index 0b1134d..5100eba 100644 --- a/renderer/renderer.ts +++ b/renderer/renderer.ts @@ -53,7 +53,7 @@ export function createRenderer(canvas: HTMLCanvasElement, backend: RendererBacke context.viewport(0, 0, w, h); context.disable(context.SCISSOR_TEST); - context.clearColor(0.18, 0.18, 0.2, 1); + context.clearColor(0, 0, 0, 0); context.clear(context.COLOR_BUFFER_BIT); context.enable(context.SCISSOR_TEST); diff --git a/renderer/selection.ts b/renderer/selection.ts index 84bd2b2..173e304 100644 --- a/renderer/selection.ts +++ b/renderer/selection.ts @@ -5,7 +5,8 @@ import { clearScreenRect } from "./clear-rect"; import { documentRectToScreenRect } from "./screen-rect"; import type { RgbaColor, ScreenRect, WebGlRendererContext } from "./types"; -const selectionColor: RgbaColor = [0.1, 0.65, 1, 1]; +const selectionOuterColor: RgbaColor = [0, 0, 0, 1]; +const selectionInnerColor: RgbaColor = [1, 1, 1, 1]; export function renderSelectionOverlay(context: WebGlRendererContext, document: ImageDocument, editor: EditorState) { const target = selectedTransformTarget(document, editor.selection); @@ -13,7 +14,8 @@ export function renderSelectionOverlay(context: WebGlRendererContext, document: if (!bounds) return; const rect = documentRectToScreenRect(context.canvas, bounds, editor.viewport); - renderScreenRectStroke(context, rect, 3, selectionColor); + renderScreenRectStroke(context, rect, 6, selectionOuterColor); + renderScreenRectStroke(context, rect, 2, selectionInnerColor); } function renderScreenRectStroke(context: WebGlRendererContext, rect: ScreenRect, width: number, color: RgbaColor) { diff --git a/renderer/transform-controls.ts b/renderer/transform-controls.ts index ca3679c..015939d 100644 --- a/renderer/transform-controls.ts +++ b/renderer/transform-controls.ts @@ -5,8 +5,8 @@ import { clearScreenRect } from "./clear-rect"; import { documentRectToScreenRect } from "./screen-rect"; import type { RgbaColor, ScreenRect, WebGlRendererContext } from "./types"; -const handleColor: RgbaColor = [1, 1, 1, 1]; -const handleBorderColor: RgbaColor = [0.1, 0.65, 1, 1]; +const handleFillColor: RgbaColor = [0, 0, 0, 0.88]; +const handleBorderColor: RgbaColor = [1, 1, 1, 0.95]; export function renderTransformControls(context: WebGlRendererContext, document: ImageDocument, editor: EditorState) { const target = selectedTransformTarget(document, editor.selection); @@ -16,12 +16,12 @@ export function renderTransformControls(context: WebGlRendererContext, document: const rect = documentRectToScreenRect(context.canvas, bounds, editor.viewport); for (const handle of transformHandleRects(rect)) { clearScreenRect(context, handle.border, handleBorderColor); - clearScreenRect(context, handle.fill, handleColor); + clearScreenRect(context, handle.fill, handleFillColor); } } function transformHandleRects(rect: ScreenRect) { - const size = 8; + const size = 12; const border = 2; const half = size / 2; const points = [ diff --git a/view/App.tsx b/view/App.tsx index 4605783..7cc24cd 100644 --- a/view/App.tsx +++ b/view/App.tsx @@ -1,12 +1,11 @@ import { useEffect, useState } from "react"; -import { DownloadSimple, FolderOpen, ImageSquare, Stack } from "@phosphor-icons/react"; +import { DownloadSimple, FolderOpen, Stack } from "@phosphor-icons/react"; import type { ImageStudioApp } from "@app/app"; import { commandIds } from "@commands/ids"; import { BottomControlsIsland } from "./BottomControlsIsland"; import { CanvasViewport } from "./CanvasViewport"; import { LayersSheet } from "./LayersSheet"; import { ToolOverlay } from "./ToolOverlay"; -import { labelForTool } from "./toolLabels"; import { resolveTransformTargetBounds, selectedTransformTarget } from "@editor/transform-targets"; import { handleDeleteSelectionKey, handleHistoryKey, keybindEventFromKeyboardEvent } from "@input/index"; import { useAppState } from "./useAppState"; @@ -21,13 +20,11 @@ export type AppProps = { export function App({ app }: AppProps) { const state = useAppState(app.store); - const zoomPercent = Math.round(state.editor.viewport.zoom * 100); const viewportActivityIsland = useViewportActivityIsland(state.editor.viewport); const imageImport = useImageImport(app.store); const [layersOpen, setLayersOpen] = useState(false); const transformTarget = state.editor.transformSession?.target ?? selectedTransformTarget(state.document, state.editor.selection); const activeArtboard = state.document.artboards.find((artboard) => artboard.id === state.editor.selection.artboardId) ?? state.document.artboards[0]; - const activeToolLabel = state.editor.maskEdit ? "Mask edit" : labelForTool(state.editor.tools.activeTool); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { @@ -53,7 +50,7 @@ export function App({ app }: AppProps) { } if (event.key.toLowerCase() === "l") { - setLayersOpen(true); + setLayersOpen((open) => !open); event.preventDefault(); return; } @@ -72,40 +69,18 @@ export function App({ app }: AppProps) { const transformBounds = transformTarget ? resolveTransformTargetBounds(state.document, transformTarget) : undefined; return ( -
+
{imageImport.input} -
-
-
- -
-
-

Image Studio

-
{state.document.name}
-
-
- -
- {activeToolLabel} - {zoomPercent}% - - {state.editor.viewport.size.w}×{state.editor.viewport.size.h} - - {activeArtboard ? {activeArtboard.name} : null} -
- -
+
+
@@ -142,12 +117,8 @@ export function App({ app }: AppProps) { ); } -function topBarChipClass() { - return "rounded-full border border-white/10 bg-white/[0.06] px-3 py-1 text-xs font-medium text-white/70"; -} - function topBarButtonClass(active = false) { - const base = "inline-flex h-8 items-center gap-1.5 rounded-lg px-3 text-xs font-medium transition disabled:pointer-events-none disabled:opacity-35 focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/30"; + const base = "inline-flex size-12 items-center justify-center rounded-full text-sm font-medium transition disabled:pointer-events-none disabled:opacity-35 focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/30"; return active ? `${base} bg-white text-black hover:bg-white hover:text-black` : `${base} text-white/75 hover:bg-white/10 hover:text-white`; } diff --git a/view/BottomControlsIsland.tsx b/view/BottomControlsIsland.tsx index fec4e4b..0b05e12 100644 --- a/view/BottomControlsIsland.tsx +++ b/view/BottomControlsIsland.tsx @@ -30,7 +30,7 @@ export function BottomControlsIsland({ viewport, visible, action, activeTool, br return (
diff --git a/view/LayersSheet.tsx b/view/LayersSheet.tsx index 0ff8e05..3916ae5 100644 --- a/view/LayersSheet.tsx +++ b/view/LayersSheet.tsx @@ -1,5 +1,5 @@ import { useRef, useState, type DragEvent, type MutableRefObject } from "react"; -import { DownloadSimple, Eye, EyeSlash, FolderPlus, Lock, LockOpen, Plus, Stack, Trash } from "@phosphor-icons/react"; +import { ArrowDown, ArrowUp, DownloadSimple, Eye, EyeSlash, FolderPlus, Lock, LockOpen, Plus, Stack, Trash } from "@phosphor-icons/react"; import { commandIds } from "@commands/ids"; import type { ImageDocument } from "@core/document"; import type { Layer } from "@core/layer"; @@ -30,48 +30,47 @@ export function LayersSheet({ document, selection, maskEdit, open, dispatch }: L return (