Skip to content

feat(desktop): auto-detect RTL/bidi text direction in chat#44596

Merged
OutThisLife merged 1 commit into
mainfrom
bb/desktop-rtl-bidi
Jun 12, 2026
Merged

feat(desktop): auto-detect RTL/bidi text direction in chat#44596
OutThisLife merged 1 commit into
mainfrom
bb/desktop-rtl-bidi

Conversation

@OutThisLife

Copy link
Copy Markdown
Collaborator

What does this PR do?

Adds automatic bidirectional text direction to the desktop chat, so Arabic/Hebrew/Persian/Urdu — and the common mixed RTL/English technical case — read and align correctly instead of running left-to-right with mangled punctuation order.

Each chat block resolves its own base direction from its first strong character (UAX#9), purely in CSS, scoped to the chat surfaces only:

  • unicode-bidi: plaintext + text-align: start on assistant prose blocks (p, h1h6, li, blockquote), the user bubble's text lines, and both composers (main + edit share the composer-rich-input slot). RTL blocks read and right-align RTL; English stays LTR; mixed conversations resolve per block. The text-align: start is load-bearing — the user bubble hardcodes text-left (USER_BUBBLE_BASE_CLASS), so without it RTL prose would read right-to-left but cling to the left edge.
  • Inline code and KaTeX are pinned direction: ltr; unicode-bidi: isolate. isolate makes the bidi first-strong heuristic treat each as a single neutral, so a block that starts with a command (`./run.sh -v` followed by Arabic) still resolves RTL, and the command's own neutrals (dots/slashes/dashes) keep their order.
  • Fenced code surfaces (code-card, user fences) are pinned LTR so they never mirror or right-align inside an RTL list item or blockquote.

direction is never set, so app chrome, layout, and list indent stay LTR (the issue explicitly asks not to flip the whole UI). List markers stay on the left by design. English-only content is byte-for-byte unchanged.

Supersedes

This supersedes #44065 and #44169 and unifies them into one minimal change (credited via Co-authored-by):

  • feat(desktop): per-message automatic RTL/bidi text direction #44065 (feat/desktop-rtl-bidi) took the JS route — a text-direction.ts first-strong resolver plus dir-attribute plumbing across markdown-text.tsx, user-message-text.tsx, thread.tsx, and the composer (~280 lines) — specifically to handle the "code-first" paragraph (a block starting with a command shouldn't flip LTR). I verified in Chromium (Electron's engine) that unicode-bidi: isolate already removes inline code from the paragraph's first-strong vote, so that case is handled in CSS and the JS is unnecessary.
  • feat(desktop): auto-detect RTL paragraph direction in chat #44169 (fix/44150-chat-rtl-bidi) was the right pure-CSS approach but didn't text-align: start (so RTL user bubbles read RTL but stayed left-pinned under the bubble's text-left) and didn't pin fenced code blocks against mirroring inside RTL list items.

This PR keeps #44169's CSS-only footprint and fixes both gaps. Please close #44065 and #44169 in favor of this.

Related (out of scope, no overlap)

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)

How to Test

  1. Run the desktop app, send an Arabic message such as مرحبا كيف حالك — the bubble right-aligns.
  2. Ask for an Arabic answer with a heading, a list, and a fenced code block — prose/headings/bullets right-align; the code block stays LTR and un-mirrored even inside an RTL list item.
  3. Send a message that starts with a command, e.g. `./scripts/run.sh -v` ماذا يفعل هذا الأمر؟ — it still right-aligns (code doesn't vote on direction) and the chip keeps its internal order.
  4. Type Arabic in the composer — it right-aligns as you type; switch to English and it flips back. Same for the edit composer.
  5. Send English messages — rendering is identical to main.

Verification

  • npm run typecheck — clean
  • eslint on touched files — clean
  • Empirically validated the bidi behavior (alignment + isolate skipping the code-first vote) in Chromium before implementing.
  • Desktop vitest failures on this branch are identical to clean main (pre-existing, unrelated).

Fixes #44150

Arabic/Hebrew/Persian/Urdu chat text rendered left-to-right and
left-aligned, and mixed RTL/English technical messages (the common case)
read backwards. Resolve each chat block's base direction from its own
first strong character (UAX#9) with pure CSS, scoped to the chat
surfaces only:

- `unicode-bidi: plaintext` + `text-align: start` on assistant prose
  blocks (p, h1-h6, li, blockquote), the user bubble's text lines, and
  both composers (main + edit share the composer-rich-input slot). RTL
  blocks read and right-align RTL; English stays LTR; mixed
  conversations resolve per block. `text-align: start` is required
  because the user bubble hardcodes `text-left`.
- Inline `code` and KaTeX are pinned `direction: ltr; unicode-bidi:
  isolate`, so the bidi first-strong heuristic skips them: a sentence
  that *starts* with a command (`./run.sh ...`) followed by Arabic
  still resolves RTL, and the command's own neutrals keep their order.
- Fenced code surfaces (code-card, user fences) are pinned LTR so they
  never mirror or right-align inside an RTL list item or blockquote.

`direction` is never forced, so app chrome, layout, and list indent
stay LTR per the issue's request not to flip the whole UI. English-only
content is byte-for-byte unchanged.

Salvaged and unified from #44065 and #44169; verified in Chromium that
isolate removes inline code from the paragraph direction vote (the
code-first case), making the JS dir-resolution in #44065 unnecessary.

Fixes #44150

Co-authored-by: Adolanium <Adolanium@users.noreply.github.com>
Co-authored-by: Adalsteinn Helgason <AIalliAI@users.noreply.github.com>
@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: bb/desktop-rtl-bidi vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 10767 on HEAD, 10767 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5640 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@OutThisLife OutThisLife force-pushed the bb/desktop-rtl-bidi branch from 167632c to 6c00077 Compare June 12, 2026 02:39
@OutThisLife OutThisLife merged commit 4d67ac6 into main Jun 12, 2026
49 of 52 checks passed
@OutThisLife OutThisLife deleted the bb/desktop-rtl-bidi branch June 12, 2026 02:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Native RTL support for Arabic and mixed RTL/LTR text in Hermes Chat

1 participant