InvokeAI/docs/contributing/frontend/canvas-text-tool.md
DustyShoe e9246c1899
Feature(UI): Add text tool to canvas (#8723)
* Initial mashup of mentioned feature. Still need to resolve some quirks and kinks.

* Clean text tool integration

* Fixed text tool opions bar jumping and added more fonts

* Touch up for cursor styling

* Minor addition to doc file

* Appeasing frontend checks

* Prettier fix

* knip fixes

* Added safe zones to font selection and color picker to be clickable without commiting text.

* Removed color probing on cursor and added dynamic font display for fallback, minor tweaks

* Finally fixed the text shifting on commit

* Cursor now represent actual input field size. Tidy up options UI

* Some strikethrough and underline line tweaks

* Replaced the focus retry loop with a callback‑ref based approach in in CanvasTextOverlay.tsx
Renamed containerMetrics to textContainerData in CanvasTextOverlay.tsx
Fixed mouse cursor disapearing during typing.

* Added missing localistaion string

* Moved canvas-text-tool.md to docs/contributing/frontend

* ui: Improve functionality of the text toolbar

Few things done with this commit.

- The varying size of the font selector box has been fixed. The UI no longer shifts and moves with font change.
- We no longer format the font size input to add px each time. Instead now just have a permanent px indicator.
- The bug with the random text inputs on the slider value has also been fixed.
- The font size value is only committed on blur keeping it consistent with other editing apps.
- Fixed the spacing of the toolbar to make it look cleaner.
- Font size now permits increments of 1.

* Added autoselect text in font size on click allowing immediate imput

* Improvement: Added uncommited layer state with CTRL-move and options to select line spacing.

* Added rotation handle to rotate uncommiitted text layer.

* Fix: Redirect user facing labels to use localization file + Add tool discription to docs

* Fixed box padding. Disable tool swich when text input is active, added message on canvas for better UX.

* Updated  Text tool description

* Updated  Text tool description

* Typo

* Add draggable text-box border with improved cursor feedback and larger hit targets. Supress hotkeys on uncommitted text.

* Lint

* Fix(bug): text commit to link uploaded image assets instead of embedding full base64

---------

Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
Co-authored-by: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com>
2026-02-20 01:43:32 +00:00

2.5 KiB

Canvas Text Tool

Overview

The canvas text workflow is split between a Konva module that owns tool state and a React overlay that handles text entry.

  • invokeai/frontend/web/src/features/controlLayers/konva/CanvasTool/CanvasTextToolModule.ts
    • Owns the tool, cursor preview, and text session state (including the cursor "T" marker).
    • Manages dynamic cursor contrast, starts sessions on pointer down, and commits sessions by rasterizing the active text block into a new raster layer.
  • invokeai/frontend/web/src/features/controlLayers/components/Text/CanvasTextOverlay.tsx
    • Renders the on-canvas editor as a contentEditable overlay positioned in canvas space.
    • Syncs keyboard input, suppresses app hotkeys, and forwards commits/cancels to the Konva module.
  • invokeai/frontend/web/src/features/controlLayers/components/Text/TextToolOptions.tsx
    • Provides the font dropdown, size slider/input, formatting toggles, and alignment buttons that appear when the Text tool is active.

Rasterization pipeline

renderTextToCanvas() (invokeai/frontend/web/src/features/controlLayers/text/textRenderer.ts) converts the editor contents into a transparent canvas. The Text tool module configures the renderer with the active font stack, weight, styling flags, alignment, and the active canvas color. The resulting canvas is encoded to a PNG data URL and stored in a new raster layer (image object) with a transparent background.

Layer placement preserves the original click location:

  • The session stores the anchor coordinate (where the user clicked) and current alignment.
  • calculateLayerPosition() calculates the top-left position for the raster layer after applying the configured padding and alignment offsets.
  • New layers are inserted directly above the currently-selected raster layer (when present) and selected automatically.

Font stacks

Font definitions live in invokeai/frontend/web/src/features/controlLayers/text/textConstants.ts as ten deterministic stacks (sans, serif, mono, rounded, script, humanist, slab serif, display, narrow, UI serif). Each stack lists system-safe fallbacks so the editor can choose the first available font per platform.

To add or adjust fonts:

  1. Update TEXT_FONT_STACKS with the new id, label, and CSS font-family stack.
  2. If you add a new stack, extend the TEXT_FONT_IDS tuple and update the canvasTextSlice schema default (TEXT_DEFAULT_FONT_ID).
  3. Provide translation strings for any new labels in public/locales/*.
  4. The editor and renderer will automatically pick up the new stack via getFontStackById().