android, desktop: fix several RTL layout issues#6908
Draft
Narasimha-sc wants to merge 2 commits into
Draft
Conversation
Fixes #5448 The original report documents four user-visible regressions under an RTL locale (Arabic, Persian, Hebrew): chat bubble tails on the wrong side, chat header call/menu buttons not mirrored, settings back arrow pointing the wrong way, and the chat list profile avatar / signal icon laid out in their LTR positions. This commit addresses all of them and a handful of related directional-icon mirroring sites discovered during the audit. - Chat bubble tail direction: chatItemShape now reads layoutDirection from the GenericShape lambda and conditions the matrix mirror on sent != isRtl, so sent-bubble tails point toward the user's profile and received-bubble tails toward the contact's profile under both LTR and RTL. The bubble-tail paddings in FramedItemView and ChatView already use direction-aware start/end and now align with the mirrored shape automatically. - App-bar slot mirroring: CenteredRowLayout in FramedItemView switches from place(...) to placeRelative(...) so the navigation icon and the action buttons swap visual sides under RTL. Both the chat header (call/menu buttons) and the chat list header (profile avatar, signal icon) flow through this layout, so one fix covers both. - Asymmetric directional drawables: add Modifier.mirrorIfRtl() (Modifier.scale(-1f, 1f) when LocalLayoutDirection.current is Rtl) and apply it to the back arrow in NavigationButtonBack, every variant of the SubscriptionStatusIcon waves, the WhatsNewView pagination arrows, the back arrow and submenu chevron in CommandsMenuView, the back arrow in OnboardingCards and ImageFullScreenView.desktop, the share-profile chevron in NewChatView, and the sent-via-proxy arrow in CIMetaView and ChatItemInfoView. DropdownMenu offsets in ChatView (DpOffset(-width, ...)) are left unchanged: DropdownMenuPositionProvider already negates the content offset under RTL, so menus anchor and open correctly once CenteredRowLayout is fixed.
Surgical refinements on top of the initial RTL fix, plus a design doc
in plans/.
- chatItemShape (ChatItemView.kt): extract `val tailOnRight = ...` so
the predicate names what the conditional does. Comment trimmed to
the single load-bearing invariant ("default path draws tail at
bottom-left") since the rest is implied by the variable name.
- SubscriptionStatusIcon.kt: hoist `val iconModifier =
modifier.mirrorIfRtl()` once at the top of the composable and reuse
it at all five Icon call sites. Calling mirrorIfRtl five times or
once produces the same Modifier within one composition.
- GoToItemInnerButton (ChatItemView.kt): add `mirror: Boolean = false`
parameter and pass `mirror = true` at the directional call site
(ic_arrow_forward, "go to forwarded source"). The other call site
(ic_search) keeps the default and is unchanged.
- Modifiers.kt, FramedItemView.kt: drop two explanatory comments that
restated framework-primitive behavior (mirrorIfRtl's own name, and
the documented behavior of placeRelative).
plans/2026-05-13-rtl-layout-issues.md documents the three independent
mechanisms behind the fix (bubble shape, app-bar slot placement,
asymmetric drawables), the bubble-tail XOR predicate, and four
considered-and-rejected alternatives.
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.
Fixes #5448.
The issue documents four user-visible regressions under an RTL locale
(Arabic, Persian, Hebrew). This PR addresses all of them and a handful
of related directional-icon mirroring sites discovered while auditing.
Changes
Chat bubble tail direction (
chatItemShapeinChatItemView.kt). Theshape's
GenericShapeblock now uses thelayoutDirectionparameter thatCompose already passes in. The matrix-mirror predicate flips from
sentto
sent != isRtl, so sent-bubble tails point toward the user's profileand received-bubble tails toward the contact's profile under both LTR and
RTL. The bubble-tail
padding(start, end)inFramedItemView.ktandChatView.ktis already direction-aware, so it falls into place againstthe corrected shape automatically.
App-bar slot mirroring (
CenteredRowLayoutinFramedItemView.kt).Switched the three placements from
place(...)toplaceRelative(...).Both the chat header (call + 3-dot-menu buttons, back arrow) and the chat
list header (profile avatar, signal icon, "Chats" title) route through
this layout, so one edit covers both panes.
Asymmetric directional drawables. Added
Modifier.mirrorIfRtl()(
Modifier.scale(-1f, 1f)whenLocalLayoutDirection.currentisRtl)in
views/helpers/Modifiers.ktand applied it to:NavigationButtonBackSubscriptionStatusIconwavesWhatsNewViewCommandsMenuViewOnboardingCardsImageFullScreenView.desktopNewChatViewCIMetaViewandChatItemInfoViewNotes
DropdownMenuDpOffset(-width.value, ...)calls inChatView.ktareintentionally left as-is.
DropdownMenuPositionProvideralready negatesthe content offset under RTL, so once
CenteredRowLayoutis fixed thechat-header menus anchor correctly and open in the right direction
without any code change at the call sites.
(
SimpleButtonIconEnded,SettingsPreferenceItem) that don't accept aper-icon
Modifier. They are not addressed in this PR — fixing themwould require extending those helper signatures and is out of scope for
the user-visible bugs reported in the issue.
these cases via UIKit's RTL support and SwiftUI's semantic edges.
Test plan
Switch the in-app language to Arabic / Persian / Hebrew (or system locale
to RTL) and walk through the screens called out in the issue:
side closest to your avatar in 2-pane mode); received-message tails
point to the contact's avatar.
the visual right and pointing right (
>). Tapping the 3-dot menuopens a dropdown that anchors on the left and stays on-screen.
>and is on theright edge of the navigation header.
signal/wifi icon on the left, with the signal icon's "waves"
mirrored.
mirrors.
behavior; no LTR regression.