63 lines
2.0 KiB
TypeScript
63 lines
2.0 KiB
TypeScript
import { Crop, Cursor, Hand, PaintBrush } from "@phosphor-icons/react";
|
|
import { commandIds } from "@commands/ids";
|
|
import type { AppStore } from "@editor/store";
|
|
import type { InteractionMode, ToolId } from "@editor/tools";
|
|
import { availableToolIds } from "@editor/tools";
|
|
import { labelForTool } from "./toolLabels";
|
|
|
|
export type ToolOverlayProps = {
|
|
activeTool: ToolId;
|
|
interactionMode: InteractionMode;
|
|
dispatch: AppStore["dispatch"];
|
|
};
|
|
|
|
export function ToolOverlay({ activeTool, interactionMode, dispatch }: ToolOverlayProps) {
|
|
return (
|
|
<nav
|
|
aria-label="Tools"
|
|
className="pointer-events-auto flex flex-col gap-1 rounded-lg border border-white/10 bg-black/70 p-1 text-white shadow-xl backdrop-blur"
|
|
>
|
|
{availableToolIds.map((tool) => {
|
|
const active = isToolHighlighted(tool, activeTool, interactionMode);
|
|
const Icon = iconForTool(tool);
|
|
|
|
return (
|
|
<button
|
|
key={tool}
|
|
type="button"
|
|
aria-label={labelForTool(tool)}
|
|
aria-pressed={active}
|
|
title={labelForTool(tool)}
|
|
className={buttonClass(active)}
|
|
onClick={() => dispatch(commandIds.toolSetActive, { tool })}
|
|
>
|
|
<Icon size={22} weight={active ? "fill" : "regular"} />
|
|
</button>
|
|
);
|
|
})}
|
|
</nav>
|
|
);
|
|
}
|
|
|
|
function iconForTool(tool: ToolId) {
|
|
switch (tool) {
|
|
case "crop":
|
|
return Crop;
|
|
case "brush":
|
|
return PaintBrush;
|
|
case "pan":
|
|
return Hand;
|
|
case "select":
|
|
return Cursor;
|
|
}
|
|
}
|
|
|
|
function isToolHighlighted(tool: ToolId, activeTool: ToolId, interactionMode: InteractionMode) {
|
|
if (interactionMode.type === "temporary-pan") return tool === "pan";
|
|
return activeTool === tool;
|
|
}
|
|
|
|
function buttonClass(active: boolean) {
|
|
return `grid size-9 place-items-center rounded-md transition focus:outline-none focus-visible:outline-none ${active ? "bg-white text-black" : "text-white/80 hover:bg-white/10 hover:text-white"}`;
|
|
}
|