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

@@ -3,7 +3,7 @@ import { commandIds } from "@commands/ids";
import type { AppStore } from "@editor/store";
import type { InteractionMode, OperationId, ToolId } from "@editor/tools";
import { availableOperationIds, availableToolIds } from "@editor/tools";
import type { WorkspacePanel } from "@editor/state";
import { isOperationWorkspacePanel, type WorkspacePanel } from "@editor/state";
import { labelForTool } from "./toolLabels";
export type ToolOverlayProps = {
@@ -17,10 +17,10 @@ export function ToolOverlay({ activeTool, interactionMode, panel, dispatch }: To
return (
<nav
aria-label="Tools"
className="pointer-events-auto flex w-20 flex-col items-center gap-3 rounded-full p-2 text-white backdrop-blur-xl"
className="app-surface pointer-events-auto flex w-11 flex-col items-center gap-1 rounded-xl p-1 text-white"
>
{availableToolIds.map((tool) => {
const active = isToolHighlighted(tool, activeTool, interactionMode);
const active = !isOperationWorkspacePanel(panel) && isToolHighlighted(tool, activeTool, interactionMode);
const Icon = iconForTool(tool);
return (
@@ -33,11 +33,11 @@ export function ToolOverlay({ activeTool, interactionMode, panel, dispatch }: To
className={buttonClass(active)}
onClick={() => dispatch(commandIds.toolSetActive, { tool })}
>
<Icon size={24} weight={active ? "fill" : "regular"} />
<Icon size={18} weight={active ? "fill" : "regular"} />
</button>
);
})}
<div className="h-px w-8 bg-white/15" aria-hidden="true" />
<div className="my-0.5 h-px w-6 bg-white/10" aria-hidden="true" />
{availableOperationIds.map((operation) => {
const active = panel === operation;
const Icon = iconForOperation(operation);
@@ -51,7 +51,7 @@ export function ToolOverlay({ activeTool, interactionMode, panel, dispatch }: To
className={buttonClass(active)}
onClick={() => dispatch(commandIds.workspaceSetPanel, { panel: active ? "none" : operation })}
>
<Icon size={24} weight={active ? "fill" : "regular"} />
<Icon size={18} weight={active ? "fill" : "regular"} />
</button>
);
})}
@@ -88,6 +88,6 @@ function isToolHighlighted(tool: ToolId, activeTool: ToolId, interactionMode: In
}
function buttonClass(active: boolean) {
const base = "inline-flex size-12 items-center justify-center rounded-full text-xs font-medium transition 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`;
const base = "inline-flex size-9 items-center justify-center rounded-lg text-xs font-medium transition focus:outline-none focus-visible:ring-2 focus-visible:ring-sky-300/50";
return active ? `${base} bg-sky-300 text-slate-950` : `${base} text-white/55 hover:bg-white/[0.07] hover:text-white`;
}