Accessibility & i18n
Folio was built for a bilingual (Arabic / English) university library, so right-to-left and mixed-direction text are first-class, not an afterthought.
Right-to-left documents
- Document direction.
theme.direction: 'rtl'makes blocks without adirattribute right-to-left. Header/footer slots follow it too. - Per-block direction.
dir: 'ltr' | 'rtl'on paragraphs, headings, lists, list items, blockquotes, code blocks and table cells overrides it. - Alignment.
textAlignaccepts logicalstart/end(the default isstart) as well asleft,center,rightandjustify. - Lists put markers on the right in RTL; blockquotes put their border on the start side; tables lay columns out right to left; file cards from the media plugin hug the start edge.
- Indents (
paddingInlineStart,paddingInlineEnd,textIndent) are logical, so they flip with direction. The page-setup rulers count from the right in RTL.
Bidirectional text
Within a line, Folio follows UAX #9 (the Unicode Bidirectional Algorithm, via bidi-js): embeddingLevels(text, dir) resolves levels for a paragraph and visualOrder(levels) reorders runs for display. Text items carry an rtl flag and are drawn in visual order; numbers and Latin words inside Arabic keep their own direction.
Line breaking follows UAX #14 (via linebreak), applied to the logical text before reordering, so a mixed line breaks where a browser would.
Shaping and fonts
Arabic is shaped by HarfBuzz, so joining forms, ligatures and marks are exactly what the font specifies. Per-grapheme fallback sends Arabic clusters to the first font in the stack that covers them (e.g. from Geist to Noto Sans Arabic) while spaces stay in the primary font, as Chrome does. See Fonts & measurement.
Editing RTL text
- Arrow keys are visual: in an RTL line, ArrowLeft moves forward in the text. Shift extends visually too.
- Hit-testing maps clicks through bidi runs and justified spacing to the right logical offset; caret stops are grapheme clusters, so the caret never lands inside an Arabic letter's marks.
- Backspace deletes a whole grapheme cluster (a letter with its harakat).
- IME input arrives through the hidden textarea, which is positioned at the caret so composition windows appear in the right place.
Not yet supported
Kashida (tatweel) justification, hyphenation, vertical writing modes and visual-order caret refinements at bidi run boundaries are on the roadmap.
Accessibility
What exists today in @nextgensoftwares/folio-react:
- Page text is real DOM text (positioned spans), not a canvas, so it can be selected by assistive technology and read by screen readers in reading order within each line.
- Each page is a
role="document"region labelled "Page N"; skeleton pages arearia-hidden. - The input textarea is labelled ("Document editor input") and multi-line.
- Toolbars, menus, dropdowns and pickers use
toolbar,menu,listbox,option,tablist/tab,radiogroup,sliderroles witharia-label,aria-pressed,aria-expanded,aria-selectedandaria-activedescendant, and are keyboard-navigable; toolbar buttons never steal focus from the editor. - The TOC navigator is a keyboard-navigable virtualized list (arrows, Home/End, Enter) with bidi-isolated headings.
- The UI theme follows
prefers-color-schemewhen set tosystem(setFolioTheme).
Known gaps: the caret position and selection changes are not yet announced to screen readers (no live region mirrors the current line), and the document surface does not expose a structured accessibility tree (headings, lists, tables) beyond the text itself. Contributions here are very welcome; see Contributing.
Translating the UI
@nextgensoftwares/folio-react's labels are English strings today. Plugin UI items carry their own labels, and hosts can replace or reorder items by id (mergeItems), so a host can ship translated items. A full i18n layer for built-in labels is not there yet.