Text boxes respond to the keys and gestures people already know from word processors: typing, moving the cursor,
selecting with the mouse or Shift, copy and paste, undo and the right-click menu. All of these work with no code once
you call enableRichText or createCanvasRichText. This page lists every key and gesture, says which keys the library
leaves to your app, and shows the commands that do the same from your own buttons and menus.
Start and stop editing
A box is first selected, then edited:
- Click a box to select it. On Konva your app selects it, by putting it on your
Konva.Transformer. On a plain canvas the built-in object controls select it (or your app callsrt.select(box)whenobjectControlsis off). - Click the selected box again to place the cursor and type.
Editing ends when someone presses Esc (the box stays selected), presses anywhere outside the box being edited, or starts resizing the box with a handle. Clicks on your page outside the canvas, such as on your toolbar, do not end editing.
From your code:
// Konva
rt.manager.edit(box); // start editing the box now, as a click on the selected box would
rt.manager.stopEditing(); // stop editing; the box stays selected
rt.manager.editing(); // the box being edited, or null
isEditingText(); // is any box on the page being edited?
stopEditingText(); // stop editing wherever it is on the page
// Plain canvas
rt.stopEditing();
rt.editing();
isEditingText and stopEditingText are exported from @mycreativeshop/rich-text/konva. A box marked editable: false
never starts editing; see the read-only boxes section of Getting started.
Keys
Keys reach the text only while a box is being edited. "Ctrl" means Ctrl or Cmd: both work on every system.
Typing
| Key | What it does |
|---|---|
| Any character | Types it, in the style of the letter before the cursor, or of the first selected letter |
| Enter | Starts a new paragraph in the same style. In an empty list item, Enter ends the list |
| Shift+Enter | A line break inside the paragraph |
| Tab | Types a tab: the text after it moves to the paragraph's next tab stop (see Tab stops) |
| Backspace, Delete | Deletes the letter before or after the cursor, or the selection |
Moving and selecting
| Key | What it does |
|---|---|
| Left, Right | Moves the cursor one letter; with Shift, extends the selection |
| Up, Down | Moves the cursor one line; with Shift, extends the selection |
| Home, End | Moves the cursor to the start or end of the line; with Shift, extends the selection |
| Ctrl+Home, Ctrl+End | Moves the cursor to the start or end of the text; with Shift, extends the selection |
| Ctrl+A | Selects all of the box's text |
| Esc | Stops editing; the box stays selected |
Clipboard and undo
| Key | What it does |
|---|---|
| Ctrl+C, Ctrl+X | Copies or cuts the selection, with its styles |
| Ctrl+V | Pastes at the cursor, replacing the selection |
| Ctrl+Z | Undo |
| Ctrl+Shift+Z, Ctrl+Y | Redo |
| Ctrl+B, Ctrl+I, Ctrl+U | Left to your app (see below) |
Mouse and touch
| Gesture | What it does |
|---|---|
| Click | Selects a box; a click on the selected box places the cursor |
| Drag across text | Selects text in the box being edited, also past the box's edge |
| Drag a box | Moves it: on Konva when the box is draggable, on a plain canvas with the object controls. A box being edited does not move |
| Double-click | On the selected box or the box being edited, selects the word under the pointer |
| Shift+click | Extends the selection to the click |
| Right-click | Opens the menu: spelling suggestions, Cut, Copy and Paste |
| Side handles | Change the width; the text wraps again (see Resize handles) |
| Corner handles | Scale the text |
On touch screens a tap is a click, and a double-tap selects a word. The library allows a little more movement and time for a touch than for a mouse before a tap counts as a drag or two taps stop counting as a double-tap.
Bold, italic and underline keys
The library does not bind Ctrl+B, Ctrl+I or Ctrl+U, because what they do belongs to your app's toolbar. While a box is being edited, a Ctrl+letter key the library does not use never types its letter, and the key goes on to your page. Bind the keys yourself:
window.addEventListener("keydown", (e) => {
if (!(e.ctrlKey || e.metaKey) || e.altKey) return;
const commands = rt.manager; // plain canvas: rt
if (!commands.selected()) return; // no box selected: the key is the browser's
const key = e.key.toLowerCase();
if (key === "b") commands.toggleBold();
else if (key === "i") commands.toggleItalic();
else if (key === "u") commands.toggleUnderline();
else return;
e.preventDefault(); // some browsers open bookmarks or the page source on these keys
});
The commands change the selected words while a box is being edited, and the whole box when it is only selected. Ctrl with Alt is left as typing, so the characters that European keyboards type with AltGr (such as @, € and {) still type.
Copy, cut and paste
Copy and cut put the selected text on the system clipboard as plain text, and keep its styles inside the library. A paste of text copied from a text box puts back each letter's style, including line breaks between paragraphs. Text pasted from anywhere else (another app, a web page, Word) arrives as plain text in the style of the cursor's position; each line break in it starts a new paragraph.
The same commands are available for your own menu or buttons:
// Konva
rt.manager.copy(); // false when nothing is selected
rt.manager.cut();
await rt.manager.paste();
rt.manager.hasSelection(); // whether Copy and Cut can do anything
// Plain canvas
rt.copy();
rt.cut();
await rt.paste(); // false when no box is being edited
rt.hasSelection();
Call paste() from a click: browsers let a page read the clipboard only during a user action, and some ask the user
first. On Konva, onClipboardAccessDenied tells you when the browser refused, so you can suggest Ctrl+V, which always
works:
const rt = enableRichText(stage, {
onClipboardAccessDenied: () => showMessage("Press Ctrl+V to paste."),
});
Undo and redo
Ctrl+Z undoes and Ctrl+Shift+Z or Ctrl+Y redoes while a box is being edited. Letters typed in one burst are one step: a space, a tab, moving the cursor or a pause of one second starts the next step, so undo takes back about a word at a time. A paste and a resize are each one step. Formatting commands on the same box less than a second apart join one step, so dragging a size slider is undone in one press. The library keeps the last 50 steps.
Undo and redo never start or stop editing: in the box being edited the cursor goes back to where the change was, and a box that is not being edited is selected and shows no cursor.
From your own buttons:
rt.manager.undo(); // plain canvas: rt.undo()
rt.manager.redo(); // plain canvas: rt.redo()
On Konva, disableInternalUndoRedoShortcuts: true makes the library ignore Ctrl+Z and Ctrl+Y so your app can bind
them and call undo() and redo() itself. To keep text changes in your app's own undo history beside its other
changes, use "host" history mode, described in Your app's undo.
The right-click menu
A right-click on the box being edited opens the library's menu: up to five spelling suggestions, Add to dictionary and Ignore on a misspelled word (see Spellcheck), then Cut and Copy when text is selected, and Paste. A right-click anywhere else is left to your app.
On Konva the menu works with no code. On a plain canvas, forward the browser's contextmenu event:
canvas.addEventListener("contextmenu", (e) => {
if (rt.contextMenu(rt.fromEvent(e, canvas, sceneToCanvas), { x: e.clientX, y: e.clientY }).handled) e.preventDefault();
});
To show your own menu instead, pass enableContextMenu: false to enableRichText or createCanvasRichText.
Keys the library leaves to your page
- Every key while no box is being edited. Your own shortcuts, such as Delete to remove a selected box, should check
isEditingText()(plain canvas:rt.editing()) first; see Your shortcuts and editing events. - Every key while the page's focus is in an
input,textarea,selectorcontenteditableelement. - Shift+Tab, and Tab with Ctrl, Cmd or Alt. After Esc ends editing, Tab moves through the page as usual, so the keyboard is never trapped in a text box.
- Ctrl+letter keys the library does not use, such as Ctrl+B, Ctrl+S and Ctrl+P.
The library listens for keys on the window. To take a key before the library does, for example to give Tab another job while editing, listen on the document in the capture phase:
document.addEventListener("keydown", (e) => {
if (e.key === "Tab" && isEditingText()) {
e.preventDefault();
e.stopPropagation(); // the library never sees this Tab
moveToNextField();
}
}, true);
Options
| Option | Surface | Default | What it does |
|---|---|---|---|
enableContextMenu |
both | true |
Shows the library's right-click menu on the box being edited |
enableSpellcheck |
both | true |
Underlines misspelled words while editing (see Spellcheck) |
objectControls |
plain canvas | true |
Click selects, drag moves, handles resize; false leaves these to your app |
selectionColor |
plain canvas | translucent blue | The color of the text selection |
caretWidth |
plain canvas | 1.5 |
The cursor's width in CSS pixels |
disableInternalUndoRedoShortcuts |
Konva | false |
Leaves Ctrl+Z and Ctrl+Y to your app |
onClipboardAccessDenied |
Konva | none | Called when the browser refused to let a paste read the clipboard |
onBeforeMouseDown |
Konva | none | Called before a press on a box reaches the library; return true to keep the library from handling it |
Limits
Limit: Ctrl+Left and Ctrl+Right move one letter, not one word, and Ctrl+Backspace deletes one letter. Page Up and Page Down do nothing in a text box.
Limit: There is no triple-click: a third click places the cursor.
Limit: On Konva, the cursor and selection are drawn on the box's layer each time the layer draws. A layer set to
clearBeforeDraw(false)keeps every cursor it has drawn, so a blinking or moving cursor leaves marks. Keep text boxes you edit on a layer that clears.
Limit: Only a physical keyboard types into a text box. Phone keyboards, input methods for Chinese, Japanese and Korean, accent keys, dictation and autocorrect work in Story Mode today; see Coming soon.
In the API reference
- RichTextManager:
edit,stopEditing,copy,cut,paste,undo,redoon Konva - EnableRichTextOptions: the Konva options, passed to
enableRichText - CanvasRichText and CanvasRichTextOptions: the plain canvas
- isEditingText and stopEditingText