Files
image-studio/view/ToolOverlay.tsx
syntaxbullet 7188569672 feat: add ComfyUI integration for image generation
- Implemented ComfyUI API for generating images with various modes (text-to-image, image-to-image, inpaint, outpaint).
- Created GenerateSheet and associated controls for user input on generation settings.
- Added subtle scrollbar styles for improved UI experience.
- Enhanced canvas input handling to ignore key events when focused on editable elements.
- Optimized canvas resizing logic to prevent unnecessary dispatches.
- Introduced error handling for generation failures and loading models.
- Added functionality to upload images and masks for inpainting.
2026-07-04 15:10:30 +02:00

70 lines
2.3 KiB
TypeScript

import { Cursor, Eraser, Hand, PaintBrush, DropHalf, MagicWand, Sparkle } 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 w-20 flex-col items-center gap-3 rounded-full p-2 text-white backdrop-blur-xl"
>
{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={24} weight={active ? "fill" : "regular"} />
</button>
);
})}
</nav>
);
}
function iconForTool(tool: ToolId) {
switch (tool) {
case "generate":
return Sparkle;
case "brush":
return PaintBrush;
case "eraser":
return Eraser;
case "chromaKey":
return DropHalf;
case "magicWand":
return MagicWand;
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) {
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`;
}