fix(desktop): tables follow RTL message direction - #47911
Open
Adolanium wants to merge 1 commit into
Open
Conversation
Adolanium
force-pushed
the
fix/desktop-rtl-table-direction
branch
from
June 17, 2026 15:12
50610a7 to
63e8e18
Compare
Markdown tables were left out of the bidi work from NousResearch#44596: an RTL table (Hebrew, Arabic, ...) kept LTR column order with headers and cells pinned to the left, because the plaintext rules only cover prose blocks and the th was hardcoded text-left. Hang dir="auto" on the table so the browser resolves column order and a single base direction from the cells' content, in practice the column headers (a box-direction property unicode-bidi:plaintext cannot set and no CSS selector can read off the script). Cells then get unicode-bidi:plaintext so a value like "-3%" or "123 units" keeps its authored order instead of being reordered by the surrounding RTL run, and text-align is pinned to the table's resolved edge via :dir() so a column's header and values stay on the same side. English tables are unchanged.
Adolanium
force-pushed
the
fix/desktop-rtl-table-direction
branch
from
June 17, 2026 15:28
6a71dd6 to
6b1d2c1
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Follow-up to #44596. The plaintext rules resolve text direction per prose block (paragraphs, headings, list items, blockquotes), but markdown tables were never covered and the
thoverride was pinned totext-left. The visible result for a right-to-left table (Hebrew, Arabic, or any RTL script): it renders left-to-right with the first column on the left and every header stranded on the left edge, even though all of its content is RTL.CSS alone cannot close this gap. A table's column order is its box
direction, andunicode-bidi: plaintext(the property that resolves per-block text direction) never touches it; there is also no selector that can read direction off the cells' RTL content. So this PR uses the smallest possible HTML hook, plus CSS that follows it, with no JS logic:<table>carriesdir="auto", so the browser's native first-strong algorithm resolves one base direction (and the column order) from the cells' content, in practice the column headers. The resolution is script-agnostic, so it covers any RTL language (Hebrew, Arabic, Persian, ...), not just one. An RTL table flips its columns so the first column sits on the right; a left-to-right table resolvesltrand renders byte-identically to current main.unicode-bidi: plaintext, so each cell keeps its inline content in the order it was written. A value like18 ₪,-3%or123 unitsis never reordered by the surrounding RTL run.:dir()(table:dir(rtl)cells align right,:dir(ltr)left), so a column's header and its values stay on the same edge instead of splitting (an RTL header on the right with its numbers stranded on the left). Thethoverride moves fromtext-leftto the logicaltext-start.Why
:dir()rather thantext-align: start: underunicode-bidi: plaintext,startresolves per cell, so a numeric or LTR cell falls to the opposite edge from its RTL header. Gating a physicaltext-alignon the table's:dir()keeps every cell on the table's edge while plaintext still protects each value's internal order.:dir()is supported by the desktop's Chromium (Electron 40).Direction is resolved per table, not per cell, which matches how RTL word processors lay out a table. Inline code inside a cell keeps the LTR-isolate from #44596, so commands and identifiers are unaffected.
Before (current
main): an RTL table (Hebrew shown) renders left-to-right with its headers stranded on the left.After (this PR): the same table resolves right-to-left. Columns flip, headers and cells align to the right, and values keep their authored order.
Both are captured in the desktop app, on a table generated by the model.
Related Issue
Follow-up to #44596 / #44150. The merged change covers prose blocks and notes that layout chrome stays LTR; this extends the same per-message direction to markdown tables, which it did not touch.
Type of Change
Changes Made
apps/desktop/src/components/assistant-ui/markdown-text.tsx:dir="auto"on thetableoverride;thfromtext-leftto the logicaltext-startapps/desktop/src/styles.css:unicode-bidi: plaintextonth/td, andtext-aligngated ontable:dir(rtl)/:dir(ltr)so cells follow the table's resolved directionapps/desktop/src/components/assistant-ui/table-direction.test.tsx: pins the contract: the table carriesdir="auto", header cells use logical alignment (text-start, nevertext-left), and the hook is content-driven (an English table carries it too)How to Test
cd apps/desktop && npx vitest run --environment jsdom src/components/assistant-ui/table-direction.test.tsx- 3 passednpm run typecheck- clean;npx eslinton the touched files - clean18 ₪,-3%,1,200 ₪) - the values keep their authored order and align with their headerdir="auto"resolves ltr)Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests pass (renderer-only change; desktop vitest suite run instead)npm run dev)Documentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/A