fix: enable text tool pointer events and add tool options

Fixed two critical issues preventing text tool usage:

**Pointer Event Integration:**
- Added text tool to canvas pointer event handler
- Text tool now properly responds to canvas clicks
- Opens text dialog on click with correct position

**Tool Options Bar:**
- Added text tool options section to toolbar
- Font family selection (6 common fonts)
- Font size control (8-500px with number input)
- Color picker with hex input
- Helpful hint: "Click on canvas to add text"
- Options bar now appears when text tool is active

**Changes:**
- components/canvas/canvas-with-tools.tsx:
  - Added dedicated text tool handler before selection tools
  - Handles pointer down event to open text dialog

- components/editor/tool-options.tsx:
  - Imported useTextStore
  - Added isTextTool check
  - Created text tool options UI section
  - Shows font, size, and color controls

Text tool is now fully functional - click the Type icon, then
click anywhere on canvas to open the text editor dialog!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-21 09:47:51 +01:00
parent fea87d3a1e
commit 4e6dc6cb14
2 changed files with 84 additions and 1 deletions

View File

@@ -202,6 +202,24 @@ export function CanvasWithTools() {
return; return;
} }
// Text tool
if (activeTool === 'text') {
const activeLayer = getActiveLayer();
if (!activeLayer || !activeLayer.canvas || activeLayer.locked) return;
const newPointer: PointerState = {
isDown: true,
x: canvasPos.x,
y: canvasPos.y,
prevX: canvasPos.x,
prevY: canvasPos.y,
pressure: e.pressure || 1,
};
tools.text.onPointerDown(newPointer, {} as any, settings);
return;
}
// Selection tools // Selection tools
const selectionTools = ['select', 'rectangular-select', 'elliptical-select', 'lasso-select', 'magic-wand']; const selectionTools = ['select', 'rectangular-select', 'elliptical-select', 'lasso-select', 'magic-wand'];
if (e.button === 0 && !e.shiftKey && selectionTools.includes(activeTool)) { if (e.button === 0 && !e.shiftKey && selectionTools.includes(activeTool)) {

View File

@@ -3,11 +3,13 @@
import { useToolStore } from '@/store'; import { useToolStore } from '@/store';
import { useShapeStore } from '@/store/shape-store'; import { useShapeStore } from '@/store/shape-store';
import { useSelectionStore } from '@/store/selection-store'; import { useSelectionStore } from '@/store/selection-store';
import { useTextStore } from '@/store/text-store';
export function ToolOptions() { export function ToolOptions() {
const { activeTool, settings, setSize, setOpacity, setHardness, setColor, setFlow } = useToolStore(); const { activeTool, settings, setSize, setOpacity, setHardness, setColor, setFlow } = useToolStore();
const { settings: shapeSettings, setShapeType } = useShapeStore(); const { settings: shapeSettings, setShapeType } = useShapeStore();
const { selectionType, setSelectionType } = useSelectionStore(); const { selectionType, setSelectionType } = useSelectionStore();
const { settings: textSettings, setFontFamily, setFontSize, setColor: setTextColor } = useTextStore();
// Drawing tools: brush, pencil, eraser // Drawing tools: brush, pencil, eraser
const isDrawingTool = ['brush', 'eraser', 'pencil'].includes(activeTool); const isDrawingTool = ['brush', 'eraser', 'pencil'].includes(activeTool);
@@ -24,8 +26,11 @@ export function ToolOptions() {
// Selection tool // Selection tool
const isSelectionTool = activeTool === 'select'; const isSelectionTool = activeTool === 'select';
// Text tool
const isTextTool = activeTool === 'text';
// Don't show options bar if no options available // Don't show options bar if no options available
if (!isDrawingTool && !isFillTool && !isShapeTool && !isSelectionTool) { if (!isDrawingTool && !isFillTool && !isShapeTool && !isSelectionTool && !isTextTool) {
return null; return null;
} }
@@ -208,6 +213,66 @@ export function ToolOptions() {
</select> </select>
</div> </div>
)} )}
{/* Text Tool Options */}
{isTextTool && (
<>
<div className="flex items-center gap-2">
<label className="text-sm font-medium text-card-foreground whitespace-nowrap">
Font:
</label>
<select
value={textSettings.fontFamily}
onChange={(e) => setFontFamily(e.target.value)}
className="px-3 py-1.5 text-sm rounded-md border border-border bg-background text-foreground"
>
<option value="Arial">Arial</option>
<option value="Helvetica">Helvetica</option>
<option value="Times New Roman">Times New Roman</option>
<option value="Georgia">Georgia</option>
<option value="Courier New">Courier New</option>
<option value="Verdana">Verdana</option>
</select>
</div>
<div className="flex items-center gap-2">
<label className="text-sm font-medium text-card-foreground whitespace-nowrap">
Size:
</label>
<input
type="number"
min="8"
max="500"
value={textSettings.fontSize}
onChange={(e) => setFontSize(Number(e.target.value))}
className="w-20 px-2 py-1 text-sm rounded border border-border bg-background text-foreground"
/>
<span className="text-sm text-muted-foreground">px</span>
</div>
<div className="flex items-center gap-2">
<label className="text-sm font-medium text-card-foreground whitespace-nowrap">
Color:
</label>
<input
type="color"
value={textSettings.color}
onChange={(e) => setTextColor(e.target.value)}
className="h-8 w-16 rounded border border-border cursor-pointer"
/>
<input
type="text"
value={textSettings.color}
onChange={(e) => setTextColor(e.target.value)}
className="w-24 px-2 py-1 text-xs rounded border border-border bg-background text-foreground"
/>
</div>
<div className="text-sm text-muted-foreground italic">
Click on canvas to add text
</div>
</>
)}
</div> </div>
); );
} }