Skip to content

feat(super-editor): native LTR/RTL paragraph direction toolbar#3226

Open
shri-scale wants to merge 4 commits into
superdoc-dev:mainfrom
shri-scale:paragraph-direction-toolbar
Open

feat(super-editor): native LTR/RTL paragraph direction toolbar#3226
shri-scale wants to merge 4 commits into
superdoc-dev:mainfrom
shri-scale:paragraph-direction-toolbar

Conversation

@shri-scale
Copy link
Copy Markdown

@shri-scale shri-scale commented May 11, 2026

Summary

  • Add toolbar buttons for LTR/RTL paragraph direction. SuperDoc already round-trips <w:bidi> on pPr.rightToLeft and exposes a Document API mutation, but the toolbar didn't surface it. Users editing Arabic/Hebrew docs were patching this gap with custom buttons.
  • No keyboard shortcut — matches Google Docs (toolbar-only).
  • Closes Feature: native LTR/RTL paragraph direction toggle #3219.

What changed

setParagraphDirection / clearParagraphDirection ProseMirror commands (packages/super-editor/src/editors/v1/core/commands/paragraphDirection.js). Walk paragraphs in the current selection, toggle pPr.rightToLeft, optionally mirror an explicit justification of "left""right" when alignmentPolicy: "matchDirection" is passed (leaves "center", "both", and unset alone). Multi-paragraph selection produces a single transaction → one undo step.

Two default toolbar buttons next to indentLeft / indentRight (directionLtr, directionRtl) with Material Design format_textdirection_* icons. Active state is wired through the headless toolbar registry (createParagraphDirectionStateDeriver reads pPr.rightToLeft), so the matching button highlights as the cursor moves between LTR and RTL paragraphs.

ButtonGroup.vue patch. Plain button clicks previously hardcoded argument: null. They now forward item.argument?.value so any built-in button can carry a static argument (the direction buttons need { direction, alignmentPolicy }). Generic fix; doesn't affect existing buttons.

XL overflow buffer bumped from 20 → 84 to accommodate the two extra items at the existing XL cutoff.

Test plan

  • pnpm --filter @superdoc/super-editor test — new vitest covers RTL/LTR set, matchDirection flip behavior across all justification values, single-transaction multi-paragraph, and clearParagraphDirection semantics
  • Toolbar buttons visible at default toolbar widths, in the overflow menu at narrow widths
  • Clicking a direction button on a paragraph toggles direction and flips the matching alignment
  • Cursor in an existing RTL paragraph (e.g., Arabic DOCX) auto-highlights the RTL button
  • Multi-paragraph selection: one undo reverts all
  • Round-trip: apply RTL, export, re-import — <w:bidi/> survives

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c445e4912a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/super-editor/src/headless-toolbar/toolbar-registry.ts Outdated
@shri-scale
Copy link
Copy Markdown
Author

@caio-pizzol Kindly have a look

Add ProseMirror commands `setParagraphDirection` / `clearParagraphDirection`,
toolbar buttons next to the indent controls, and `Mod-Alt-Shift-L/R` keymaps.
Buttons highlight to reflect the current paragraph's direction via the
headless toolbar registry.

Closes superdoc-dev#3219.
Matches Google Docs behavior — no default keyboard shortcut for paragraph
direction. The 4-key Mod-Alt-Shift-L/R chord (added to avoid colliding
with the existing Mod-Shift-L/R alignment binding) was awkward enough
that any future shortcut should be a deliberate single-key toggle.
…load path

The `direction-ltr` / `direction-rtl` registry entries delegated to
`createDirectCommandExecute('setParagraphDirection')`. Headless callers
that invoke `controller.execute('direction-rtl')` without a payload
ended up calling `editor.commands.setParagraphDirection()` with no
arguments — which defaulted `direction` to `undefined`, evaluated
`direction === 'rtl'` as false, and wrote `rightToLeft: false`. The RTL
toolbar id silently performed an LTR write.

Fix in two layers:

- A dedicated `createParagraphDirectionExecute(direction)` helper that
  bakes the fixed `{ direction, alignmentPolicy: 'matchDirection' }`
  payload into the registry execute so callers don't need to know the
  direction is encoded in the command id.
- Guard the command itself so a missing direction is a no-op rather
  than a silent LTR write — defense in depth for any other generic
  command-by-name pathway.
…riting false

Writing `rightToLeft: false` round-trips as `<w:bidi w:val="0"/>` on export
(direct formatting that overrides any inherited style direction), so clicking
LTR on a vanilla paragraph injected `<w:bidi w:val="0"/>` into the DOCX even
though nothing semantically changed. Now LTR deletes the property, matching
`clearParagraphDirection` and leaving vanilla paragraphs untouched.

Replaces a previous test that locked in the buggy behavior; adds a regression
test for the vanilla-paragraph no-op case.
@caio-pizzol caio-pizzol self-assigned this May 11, 2026
@shri-scale shri-scale force-pushed the paragraph-direction-toolbar branch from 534dfc3 to 3542424 Compare May 11, 2026 17:46
@caio-pizzol caio-pizzol requested a review from artem-harbour May 11, 2026 19:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: native LTR/RTL paragraph direction toggle

2 participants