[]previous and next page

Right to left

Mirror the interface, start text from the right and keep the canvas where it is. How CanvasFlow handles Arabic, Hebrew and mixed text.

Right to left is not a skin. It changes where panels sit, which way menus open, where a line of text starts and where it grows while you type. CanvasFlow treats it as part of the design from the first line: one option sets the layout, and each text still follows its own letters.

A live CanvasFlow editor runs here when JavaScript is on.

Switch between LTR, RTL and Auto. The interface mirrors. The canvas, and the shapes on it, stay where they are.

Set the layout direction#

main.tsts
import { createCanvasFlow } from 'canvasflow/dom'
import { mountUI } from 'canvasflow/ui'

const app = createCanvasFlow(document.getElementById('board')!, {
  dir: 'rtl', // 'ltr', 'rtl' or 'auto'
})
mountUI(app)

app.setDirection('ltr') // change it at runtime
app.direction // the setting: 'auto' | 'ltr' | 'rtl'
app.editor.state.direction // what it resolved to: 'ltr' | 'rtl'

auto, the default, follows the page: the dir attribute of the canvas's container or any ancestor, including <html dir>. If your page flips its dir at runtime (a language switch), the canvas follows. ltr and rtl force a direction whatever the page says.

Every binding passes it through as the dir prop or option, and dir follows later changes. The default UI also has it in the menu, under Preferences → Layout direction, and in the command palette as Right-to-left layout.

What mirrors#

The interface lays itself out from the reading direction, with logical properties instead of left and right:

  • The toolbar, the style panel, the layers panel, the page menu and the zoom controls swap sides, and the buttons inside each swap order.
  • Menus open from the start edge of their button, and submenus open toward the end.
  • Arrow keys do what they look like: in a menu or a group of options, the key that points toward the end opens a submenu or moves to the next option.
  • Icons that point along the reading direction flip: undo, redo, submenu arrows and the text alignment icons.

What does not mirror#

The canvas. A drawing is not text. Coordinates, the camera, pan and zoom, shapes, arrows and the selection handles are the same in both directions, so a board looks identical to everyone who opens it, whatever their language. Keyboard shortcuts are not mirrored either.

Text has a direction of its own#

Layout direction is about the interface. Each piece of text also has its own direction, set by the dir style, which every text-bearing shape (text, labels on shapes, notes, arrow labels) has:

dir The text flows
auto (the default) By its first letter that has a direction: Arabic and Hebrew letters flow right to left, Latin, Greek, Cyrillic and others left to right. Text with no such letter, like numbers or an empty label, takes the layout direction.
ltr Left to right, always.
rtl Right to left, always.

The style panel shows it as Text direction when you select something that has text.

ts
editor.setStyle('dir', 'rtl') // the selection, and the next shape
editor.createShape({ type: 'geo', props: { text: 'مرحبا', dir: 'auto' } })
ts
editor.resolveDirection('auto', 'مرحبا') // 'rtl'
editor.resolveDirection('auto', '2026') // the layout direction
editor.resolveDirection('ltr', 'مرحبا') // 'ltr'

Start and end#

Alignment is logical. start is the edge the text begins from, so it is the left edge for English and the right edge for Arabic. end is the other one. The same align: 'start' does the right thing in both.

dir: 'ltr'
dir: 'rtl'
dir: 'auto'
The same alignment, start, in three directions. Start is the right edge when the text flows right to left.

Typing keeps its anchor#

When you click and type, the text box grows. It grows from the edge its alignment names: a left-aligned text keeps its left edge still, a right-aligned one keeps its right edge, and a centered text keeps its middle, so it grows both ways instead of drifting. Because start follows the direction, an Arabic text typed at a click grows to the left from that point, and an English one to the right. The first letter decides: type one Arabic letter in an empty box and the anchor moves to the right edge.

The rest follows#

  • A frame's name sits at its start corner: top left in English, top right in Arabic.
  • Labels, notes and arrows draw with the resolved direction, in the editor, in exports and on React Native (where the platform shapes the text and CanvasFlow places it on the right side).
  • Exported SVG carries direction="rtl" on right-to-left text, so another program draws it the same way.

In your own shapes#

A custom shape that draws text should resolve the direction from its props and pass it on, so it behaves like the built-in ones:

LabelShape.tsts
import { labelNode } from 'canvasflow'

render(shape, ctx) {
  const { text, dir } = shape.props
  return labelNode(layout, box, shape.props, {
    dir: this.editor.resolveDirection(dir, text),
  })
}

If your geometry needs to know which side the text sits on, physicalAlign(align, dir) returns 'left', 'center' or 'right'. Add dir: 'auto' to the shape's default props and the style panel offers it. See Custom shapes.