RTL languages (Hebrew, Arabic) are unusable in the desktop client: no bidi handling in message bodies or composer
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
RTL text is currently unusable in the desktop client. Hebrew and Arabic render with punctuation, brackets and numbers on the wrong edge of every line.
### Steps to reproduce
1. Send a message containing Hebrew or Arabic text ending in a period, parentheses or quotes.
2. Observe the trailing punctuation renders at the wrong edge of the line.
3. Same in the composer while typing.
**Environment:** Buzz 0.5.3, macOS (Apple Silicon). Also reproduced in a dev build at `28ae6cd`.
### Current

The sentence-final period sits at the *start* of line 1, the opening quote is on the wrong side, and the Arabic closing paren has jumped to the left edge.
### With the fix below

The English line is unchanged.
### Root cause
There is no bidi handling anywhere in the desktop client:
- [`desktop/index.html#L2`](https://github.com/block/buzz/blob/28ae6cd2174309529305724e455c7ca082f6fe4b/desktop/index.html#L2) is `` with no `dir`
- `dir="auto"` appears 0 times in the repository
- [`markdown.css`](https://github.com/block/buzz/blob/28ae6cd2174309529305724e455c7ca082f6fe4b/desktop/src/shared/styles/globals/markdown.css) sets no direction on any element
- [`markdown.tsx#L1615`](https://github.com/block/buzz/blob/28ae6cd2174309529305724e455c7ca082f6fe4b/desktop/src/shared/ui/markdown.tsx#L1615) renders a bare `
`
Every block therefore resolves at bidi paragraph level 0 (LTR), so neutral characters at a run boundary take the paragraph direction instead of the surrounding text's.
### Proposed fix
One rule in `markdown.css`, scoped to `.message-markdown`:
```css
.message-markdown p,
.message-markdown li,
.message-markdown blockquote,
.message-markdown h1,
.message-markdown h2,
.message-markdown h3,
.message-markdown h4,
.message-markdown h5,
.message-markdown h6,
.message-markdown td,
.message-markdown th {
unicode-bidi: plaintext;
}
```
`unicode-bidi: plaintext` resolves direction per block from the first strong character, which is the correct behaviour for a client carrying mixed LTR/RTL content. LTR-only messages are unaffected. Code blocks are deliberately excluded, so `pre` and `code` stay LTR.
**This fixes reading and typing with the same rule.** `MESSAGE_MARKDOWN_CLASS` is applied both to the rendered message wrapper ([`markdown.tsx#L1945`](https://github.com/block/buzz/blob/28ae6cd2174309529305724e455c7ca082f6fe4b/desktop/src/shared/ui/markdown.tsx#L1945)) and to the TipTap editor root ([`useRichTextEditor.ts#L492`](https://github.com/block/buzz/blob/28ae6cd2174309529305724e455c7ca082f6fe4b/desktop/src/features/messages/lib/useRichTextEditor.ts#L492)).
### Verification
Screenshots above are from the actual desktop app via `just desktop-screenshot` at `28ae6cd`, with and without the rule, same message and same clip region. `just desktop-check` passes.
Happy to open a PR.
Contributor guide
Assessment
This issue has not been assessed yet.