Skip to content

Conversation

@DustyShoe
Copy link
Collaborator

@DustyShoe DustyShoe commented Dec 30, 2025

Summary

Canvas Basic Text Tool!

Summary:

  • Adds a basic Text tool with overlay editing and rasterize-on-commit.
  • New text options row (font, size, bold/italic/underline/strike, alignment).
  • Handles hotkey suppression during typing, commit on Enter/tool switch.
  • Overlay positioning, tests for text helpers.
2025-12-30.13-29-23.mp4

Related Issues / Discussions

The fonts information is stored in invokeai\frontend\web\src\features\controlLayers\text\textConstants.ts
If anyone have an opinion what fonts and fallbacks should be used, please write in comments. There's 10 fonts to choose ATM and i'd like to make selection as diverse as possible.

QA Instructions

  • Activate Text tool, click canvas, type 2–3 lines, Shift+Enter adds newline, Enter commits. Esc cancels operation.
  • Verify that typing works as expected, hotkeys are suppressed while typing (only Ctrl/Cmd+C/V/Z/Y allowed).
  • Change font, size, bold/italic/underline/strike, alignment; preview matches raster after commit.
  • Click outside text box or switch tools; commit happens once, creates a raster layer above selected layer.

Merge Plan

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Tests added / updated (if applicable)
  • ❗Changes to a redux slice have a corresponding migration
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)

@github-actions github-actions bot added frontend PRs that change frontend files docs PRs that change docs labels Dec 30, 2025
@DustyShoe DustyShoe changed the title Feature/add text tool to canvas Feature(UI): Add text tool to canvas Dec 30, 2025
@DustyShoe DustyShoe marked this pull request as ready for review December 30, 2025 12:02
@DustyShoe DustyShoe requested a review from dunkeroni as a code owner January 7, 2026 02:39
Copy link
Collaborator

@lstein lstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made a request about where to put the documentation file. I've tested the feature and it works as advertised, but I'm not strong enough with typescript to comment on the code.

@lstein lstein added the v6.12.0 Intended for 6.12.0 release label Jan 30, 2026
@DustyShoe
Copy link
Collaborator Author

Also it would be good if someone proficient in TS could take a look. This piece was a tricky one.

@blessedcoolant
Copy link
Collaborator

Gave it a quick test. There's a few things I think this PR needs.

  1. [Functionality] Text Layers need to remain vector until they are explicitly converted to Raster. We should also be able to double click and edit the text after it is placed.
  2. [Bug] Something is off with the font size selector. If I type in 24, it actually goes to 84. This needs to be fixed. Also the slider options below should probably be in multiples of 2/4/8 -- Because that is the range the font are stepping.
  3. [Functionality] We need a hotkey for the text tool. Ideally it would be T but we are using that for something else. I would be open to removing that and using T for text or we can isolate context and make T the hotkey when the mouse is hovered on canvas.
  4. Pressing Escape after typing should actually confirm the text if there is text already typed. If empty, then we remove the layer. That is how it works in almost every other tool. The with clicking elsewhere to do it breaks the experience and also creates an unnecessary text type object. The single click should NOT do that if the intent is to confirm the existing text layer.
  5. The font selector needs to have a fixed width that way the top bar UI wont expand and collapse depending on what font has been picked. Moving UI is not good.

I'll add more as I test and find.

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.
@blessedcoolant
Copy link
Collaborator

Added a new commit.

opera_xLtl5DSXxt
  • 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.

@DustyShoe
Copy link
Collaborator Author

Overall, I agree with the review and appreciate the fixes that were made. That said, I’d like to disagree with points 1 and 4 and clarify the original intent behind this tool.

  1. Text tool behavior and vector text layers

I don’t want this tool to evolve into a full-featured text editor or introduce a new persistent “text layer” type. The original idea was to provide a very simple, unobtrusive way to add short annotations directly onto the canvas, mainly for mockups, references, or raw inputs for generation.

The intended workflow is:

  • select the tool
  • type a short piece of text
  • rasterize it
  • continue working with it as a regular raster layer

In this context, post-placement text editing doesn’t add much value. We’re not editing documents or long text blocks; most use cases involve a few words that are faster to retype than to maintain an editable text state. Introducing a new layer type would also increase UI and state complexity, especially considering the right panel is already quite dense with things like Inpaint Mask, Control Layers, Regional Guidance, etc.

  1. Escape / commit behavior

I’d like to keep the ability to cancel text input with a single key. This is useful when intentions change mid-typing or any other reason.

I agree that committing on canvas click is probably too aggressive and hurts UX. As a compromise, I’d suggest:

  • Enter commits the text
  • Escape cancels the input and removes the text

This keeps the behavior explicit, avoids accidental commits, and prevents unnecessary layers from being created without clear user intent.

P.S.

  1. I’m not sure that a hotkey for the text tool is that important. A hotkey mainly implies frequent switching back and forth between tools. I doubt there is a real use case where someone would constantly jump between the text tool and another tool in a way that makes a hotkey preferable to simply clicking the toolbar button.

@DustyShoe
Copy link
Collaborator Author

I'd like to ask to take another look at this PR.
Have made some changes to text layer behaviour. It is now movable with CTRL and can be rotated. Also fixed ugly bottom padding.
We commit only on Enter allowing freely click around UI. Switching to other tools is blocked while text input is active. Changing tabs (Generate, Upsacaling etc.) discards uncommitted text.

@lstein
Copy link
Collaborator

lstein commented Feb 1, 2026

Sure, I'll take a look later today!

@lstein
Copy link
Collaborator

lstein commented Feb 1, 2026

I tried out the text interface again and found it to be a nice addition to the canvas. However, there were a few things I found counterintuitive:

  1. Select the text tool and click somewhere in the canvas. Type into the text area. Now click outside the text area and type some more. Because the text area loses focus when you click outside the box, the keystrokes now act as hotkeys and I found myself inadvertently changing colors, opening and closing panels, etc.
  2. For the same reason, escape and enter only discard/commit when the text area has focus. I didn't find this natural.
  3. I kept trying to get rid of the textbox by clicking its border and hitting backspace.
  4. I wouldn't have figured out that control-click repositoins the text box on my own if I didn't have the instructions above. Could the dashed edges of the text box be grabbable, and could the mouse pointer convert into a move icon ✢ when over an edge?
  5. The rotate bar is about twice as long as you usually see, which makes it unusually prominent.
  6. Lastly, my fingers kept wanting to start a new line by pressing shift-enter (too much Discord!)

Here's what I would suggest that does not involve creating a whole new vector graphics application.

  1. Two modes for the text box -- click in the interior to enter key entry mode; click on the dotted border to enter move-it-around mode.
  2. In move-it-around mode, handles appear on the outline and the mouse pointer changes to indicate move-it mode.
  3. Control-click enters move mode as it does now, but with the visual indication.
  4. Typing backspace while in move-it-around mode deletes the text element.
  5. Clicking outside the box shouldn't change the mode. It remains in either text mode or move-it-around mode.
  6. Make the rotate bar shorter.
  7. (nice to have in the future) Shift-enter to start a newline. This will raise expectations of line spacing, justification, etc, that are out of scope for now.

@DustyShoe
Copy link
Collaborator Author

I’ll try to defend my decisions while also agreeing with some of the points raised.

  1. Click-away behavior and hotkeys

1.1 The click-away behavior is intentional. It allows users to copy and paste (or type) between the canvas text box and the prompt window without being locked into text input mode.

1.2 It also reserves the ability to use hotkeys. I personally found it useful to be able to change primary and secondary colors on the fly. That said, we can disable this for now if needed.

1.3 Keeping the tool always in typing mode causes issues with interacting with text option controls, especially numeric inputs like font size. Even if those controls are made interactable, clicking them exits text entry mode, which brings us back to the original problem.

  1. Text tool scope and interaction model

I did not intend for this tool to become an advanced text editor for writing long-form content inside Invoke. The expected flow is simple: type the text, commit with Enter, optionally rotate or reposition it, and press Escape if you change your mind and decide to do something else.

I do agree that hovering over the border to enable a Move mode makes sense, and I plan to implement that. However, I would still like to keep the Enter (commit) and Escape (cancel) behavior. Perhaps a small tooltip in a canvas corner could help users better understand this interaction model.

  1. Deleting the text box

Honestly, why Backspace? Delete seems more intuitive here. Using Backspace for node or noodle deletion is generally a bad design choice, and I would prefer not to repeat it in this tool.

  1. Move mode discovery

Answered in point 2.

  1. Rotate handle size

The rotate handle was intentionally made the same length as in the Transform tool for consistency. I actually spent extra time aligning it with that behavior; it used to be shorter before.

  1. New line behavior

Shift-Enter already creates a new line. If I misunderstood this point, please let me know.

I hope this helps clarify my intentions, and I’m open to further discussion. Apologies if this response feels a bit messy; it’s late and I’m pretty tired after pushing this feature to the finish line.

…r hit targets. Supress hotkeys on uncommitted text.
@DustyShoe
Copy link
Collaborator Author

DustyShoe commented Feb 2, 2026

I may be missing an obvious use case here, but I’m having a hard time understanding why a user would intentionally continue typing after clicking away from the text editor. It feels like the user’s intent has already shifted at that point.

At this point i have blocked all hotkeys while text is in uncommitted state.

@lstein
Copy link
Collaborator

lstein commented Feb 3, 2026

I’ll try to defend my decisions while also agreeing with some of the points raised.

  1. Click-away behavior and hotkeys

1.1 The click-away behavior is intentional. It allows users to copy and paste (or type) between the canvas text box and the prompt window without being locked into text input mode.

OK, leave click-away in.

1.2 It also reserves the ability to use hotkeys. I personally found it useful to be able to change primary and secondary colors on the fly. That said, we can disable this for now if needed.

This was driving me crazy, so appreciate disabling the hotkeys.

1.3 Keeping the tool always in typing mode causes issues with interacting with text option controls, especially numeric inputs like font size. Even if those controls are made interactable, clicking them exits text entry mode, which brings us back to the original problem.

Ok, leave current behavior.

  1. Text tool scope and interaction model

I did not intend for this tool to become an advanced text editor for writing long-form content inside Invoke. The expected flow is simple: type the text, commit with Enter, optionally rotate or reposition it, and press Escape if you change your mind and decide to do something else.

I do agree that hovering over the border to enable a Move mode makes sense, and I plan to implement that. However, I would still like to keep the Enter (commit) and Escape (cancel) behavior. Perhaps a small tooltip in a canvas corner could help users better understand this interaction model.

Ok. Just add the move mode for hovering and leave the Enter/Escape behavior

  1. Deleting the text box

Honestly, why Backspace? Delete seems more intuitive here. Using Backspace for node or noodle deletion is generally a bad design choice, and I would prefer not to repeat it in this tool.

This was my error. I meant Delete, so we agree here.

  1. Move mode discovery

Answered in point 2.

  1. Rotate handle size

The rotate handle was intentionally made the same length as in the Transform tool for consistency. I actually spent extra time aligning it with that behavior; it used to be shorter before.

Sure, leave it as is.

  1. New line behavior

Shift-Enter already creates a new line. If I misunderstood this point, please let me know.

I'll have to try it again. I thought I'd tried shift-enter and it didn't behave as expected.

I hope this helps clarify my intentions, and I’m open to further discussion. Apologies if this response feels a bit messy; it’s late and I’m pretty tired after pushing this feature to the finish line.

Nearly there! Don't get disheartened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs PRs that change docs frontend PRs that change frontend files v6.12.0 Intended for 6.12.0 release

Projects

Status: 6.12.x

Development

Successfully merging this pull request may close these issues.

5 participants