refactor: Update bottom controls for improved styling and functionality

- Adjusted button styles across various components for consistency and better UX.
- Enhanced layout of action controls to utilize whitespace more effectively.
- Updated slider styles for a more modern appearance and improved usability.
- Refined input fields and labels for better accessibility and readability.
- Introduced new app surface styles for a cohesive design across the application.
- Added tests for canvas cursor behavior to ensure correct cursor display during operations.
This commit is contained in:
syntaxbullet
2026-07-11 14:55:32 +02:00
parent 37aa719047
commit 5915c62a9a
31 changed files with 345 additions and 287 deletions

View File

@@ -0,0 +1,12 @@
import { describe, expect, test } from "bun:test";
import { canvasCursorClass } from "./cursor";
describe("canvas cursor", () => {
test("keeps the brush cursor while non-operation UI is open", () => {
expect(canvasCursorClass({ type: "tool", tool: "brush" }, false, false, true, false)).toBe("cursor-crosshair");
});
test("uses the default cursor while an operation suspends canvas tools", () => {
expect(canvasCursorClass({ type: "tool", tool: "brush" }, false, false, true, true)).toBe("cursor-default");
});
});

View File

@@ -1,6 +1,7 @@
import type { InteractionMode } from "@editor/tools";
import { isPanInteractionMode } from "@editor/tools";
export function canvasCursorClass(interactionMode: InteractionMode, isPanning: boolean, hasBrushPreview = false, canBrush = true) {
export function canvasCursorClass(interactionMode: InteractionMode, isPanning: boolean, hasBrushPreview = false, canBrush = true, operationOpen = false) {
if (operationOpen) return "cursor-default";
if (isPanning) return "cursor-grabbing";
if (isPanInteractionMode(interactionMode)) return "cursor-grab";
if (interactionMode.type === "tool" && (interactionMode.tool === "brush" || interactionMode.tool === "eraser")) {

View File

@@ -1,6 +1,7 @@
import { useEffect, useRef, type RefObject } from "react";
import { commandIds } from "@commands/ids";
import type { AppStore } from "@editor/store";
import { isOperationWorkspacePanel } from "@editor/state";
import { isPanInteractionMode } from "@editor/tools";
import type { GlobalKeybindConsumer, GlobalPointerConsumer, GlobalWheelConsumer } from "@input/index";
import {
@@ -59,6 +60,10 @@ export function useCanvasInput(
}
const state = store.getState();
if (isOperationWorkspacePanel(state.editor.workspace.panel)) {
clearBrushPreview();
return;
}
if (!canPreviewBrush(state.document, state.editor)) {
clearBrushPreview();
return;
@@ -117,7 +122,7 @@ export function useCanvasInput(
const state = store.getState();
const documentPoint = viewportPointToDocumentPoint(inputEvent.position, state.editor.viewport);
const brush = (inputEvent.buttons & 1) === 1 && !isPanInteractionMode(state.editor.tools.interactionMode)
const brush = !isOperationWorkspacePanel(state.editor.workspace.panel) && (inputEvent.buttons & 1) === 1 && !isPanInteractionMode(state.editor.tools.interactionMode)
? beginBrushSession(state.document, state.editor, documentPoint)
: undefined;
if (brush) {
@@ -129,7 +134,7 @@ export function useCanvasInput(
return;
}
if (state.editor.tools.activeTool === "magicWand") {
if (!isOperationWorkspacePanel(state.editor.workspace.panel) && state.editor.tools.activeTool === "magicWand") {
void applyMagicWandAt(store, documentPoint, inputEvent.shiftKey ? "add" : inputEvent.altKey ? "subtract" : undefined);
event.preventDefault();
return;