APP-2983: Fix RTL post alignment on native (#11600)

This commit is contained in:
Eric Bailey
2026-08-31 21:59:24 -05:00
committed by GitHub
parent 4881224d2f
commit 5be7d72011
7 changed files with 74 additions and 3 deletions
+1
View File
@@ -159,6 +159,7 @@
"babel-plugin-transform-remove-console": "^6.9.4",
"bcp-47": "^2.1.0",
"bcp-47-match": "^2.0.3",
"bidi-js": "^1.0.3",
"date-fns": "^4.4.0",
"email-validator": "^2.0.4",
"emoji-mart": "^5.6.0",
+10
View File
@@ -421,6 +421,9 @@ importers:
bcp-47-match:
specifier: ^2.0.3
version: 2.0.3
bidi-js:
specifier: ^1.0.3
version: 1.0.3
date-fns:
specifier: ^4.4.0
version: 4.4.0
@@ -4523,6 +4526,9 @@ packages:
bcp-47@2.1.0:
resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==}
bidi-js@1.0.3:
resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==}
big-integer@1.6.52:
resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==}
engines: {node: '>=0.6'}
@@ -14010,6 +14016,10 @@ snapshots:
is-alphanumerical: 2.0.1
is-decimal: 2.0.1
bidi-js@1.0.3:
dependencies:
require-from-string: 2.0.2
big-integer@1.6.52: {}
big.js@5.2.2: {}
+7 -3
View File
@@ -2,6 +2,7 @@ import {useMemo} from 'react'
import {type StyleProp, type TextStyle} from 'react-native'
import {RichText as RichTextAPI} from '@bsky/sdk/richtext'
import {isRTLText} from '#/lib/strings/text-direction'
import {toShortUrl} from '#/lib/strings/url-helpers'
import {android, atoms as a, flatten, type TextStyleProp} from '#/alf'
import {isOnlyEmoji} from '#/alf/typography'
@@ -9,6 +10,7 @@ import {InlineLinkText, type LinkProps} from '#/components/Link'
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
import {RichTextTag} from '#/components/RichTextTag'
import {Text, type TextProps} from '#/components/Typography'
import {IS_NATIVE} from '#/env'
import {app} from '#/lexicons'
import * as bsky from '#/types/bsky'
@@ -82,15 +84,17 @@ export function RichText({
}
}, [value])
const plainStyles = style
const {text, facets} = richText
const plainStyles: StyleProp<TextStyle> = [
style,
IS_NATIVE && isRTLText(text) ? {textAlign: 'right'} : null,
]
const suffixStyles =
suffix && suffixOffset
? android({paddingBottom: suffixOffset, marginBottom: -suffixOffset})
: null
const interactiveStyles = [plainStyles, interactiveStyle]
const {text, facets} = richText
if (!facets?.length) {
if (isOnlyEmoji(text)) {
const flattenedStyle = flatten(style)
+8
View File
@@ -1,2 +1,10 @@
// TS6.0 enables noUncheckedSideEffectImports
declare module '*.css'
declare module 'bidi-js' {
type Bidi = {
getBidiCharTypeName(character: string): string
}
export default function bidiFactory(): Bidi
}
@@ -0,0 +1,24 @@
import {describe, expect, it} from '@jest/globals'
import {isRTLText} from '../text-direction'
describe('isRTLText', () => {
it('recognizes right-to-left text', () => {
expect(isRTLText('עברית')).toBe(true)
expect(isRTLText('العربية')).toBe(true)
})
it('recognizes left-to-right text', () => {
expect(isRTLText('English')).toBe(false)
})
it('uses the first strong directional character', () => {
expect(isRTLText(' 123 🦋 עברית English')).toBe(true)
expect(isRTLText(' 123 🦋 English עברית')).toBe(false)
})
it('defaults to left-to-right when there are no strong characters', () => {
expect(isRTLText('123 🦋 ...')).toBe(false)
expect(isRTLText('')).toBe(false)
})
})
+17
View File
@@ -0,0 +1,17 @@
import bidiFactory from 'bidi-js'
const bidi = bidiFactory()
/**
* Checks the first strong directional character, matching HTML `dir="auto"`.
*/
export function isRTLText(text: string) {
for (const character of text) {
const type = bidi.getBidiCharTypeName(character)
if (type === 'R' || type === 'AL') return true
if (type === 'L') return false
}
return false
}
+7
View File
@@ -0,0 +1,7 @@
/**
* React Native Web sets `dir="auto"` on root Text elements, so the browser
* handles direction detection without JavaScript.
*/
export function isRTLText(_text: string) {
return false
}