Repository navigation
UI Consistency: 2 issues found
Two direction-inheritance gaps in the web markdown chrome, both introduced by the new per-block RTL resolution:
apps/web/src/index.css(L1797-1799):.chat-markdown preis pinned todirection: ltr, but the.chat-markdown-codeblockwrapper around it is not. Inside an Arabicli,blockquote, or table cell the wrapper inherits RTL, so thejustify-betweencode-block header mirrors while its physicalpr-1.5/pl-3padding does not. The table container is pinned as a whole (L1612) and mobile wraps the entire code block in an LTR view; suggested pinning.chat-markdown .chat-markdown-codeblock.apps/web/src/components/ChatMarkdown.tsx(L566):dir="auto"onCollapsibleTriggermirrors only the summary row; the panel body still inherits LTR from theCollapsibleroot and keeps itsps-6inset on the left, so an Arabic details title and its body hang off opposite edges. Suggested movingdir="auto"to theCollapsibleroot.
Previously flagged items (raw-HTML-only plugin wiring, unconditional list end padding, dropped summary dir, table scroller direction, inline-code bidi isolation, the shared margin selector pinning p/blockquote) are resolved in this revision.
Details
Note
Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.
Reviewed files in scope: apps/web/src/index.css, apps/web/src/components/ChatMarkdown.tsx, apps/web/src/markdown-text-direction.ts, apps/web/src/markdown-text-direction.test.tsx. Mobile changes were read for cross-client consistency only.
Checks performed:
- Traced
dirprop forwarding through thep,li,ol,blockquote,td/thcomponent overrides inChatMarkdown(all spread props, so the plugin'sdirreaches the DOM; the alert branch drops props but the plugin deliberately skipsdata-alertblockquotes). - Verified
data-rtl-itemnaming survives hast property casing (dataRtlItem->data-rtl-item) and matches the new CSS attribute selectors. - Checked the list gutter model:
ul/olpinned LTR,padding-inline-startunchanged for LTR lists, end-side gutter added only where an RTL item exists, and the task-list checkboxmargin-inlinereproducing the previous physical margins in LTR. - Checked table path:
.chat-markdown-table-containerpinned LTR covers the Base UIScrollAreaviewport and the footer chrome row;text-align: starton cells resolves against each cell's owndir="auto". - Checked inline code isolation (
direction: ltr; unicode-bidi: isolate) against the RTL-paragraph neutral-reordering case. - Searched for other
.chat-markdowndescendants with physical-side layout that can now inherit RTL; the code-block chrome and the details panel inset were the two that mirror inconsistently.
🔍 Agent activity — 1 tool call
💭 Looking at the PR changes to see if they've resolved the earlier issues—the table container rule, inline code isolation, and list padding via the data-rtl-item attribute all seem to be in place. Now I'm checking the current head for any new problems, particularly around how the direction rules interact with RTL content. The list container is pinned to LTR with
direction: ltr, but individual items havedir="auto"so they should resolve their own text direction independently—though I need to verify this doesn't break RTL item markers. nt this is — if it's a table cell, the start alignment works fine since the table container has direction ltr. For the MarkdownDetails component, I added dir="auto" and text-start, but now I'm noticing the CollapsibleTrigger is a flex row with a chevron icon that might not behave as intended in RTL contexts — the flex direction would flip but the chevron glyph itself might still point the wrong way. Also realizing the mobile files are outside the scope of these changes anyway. For the task list checkbox margins, I'm checking the conversion from the original shorthand to the new margin-inline approach — the values map correctly for LTR (left gets the negative gutter, right gets 0.35em), but I need to verify how this behaves when the list item has dir="auto" and resolves to RTL. The blockquote styling looks good with border-inline-start and padding-inline-start handling the directional rail properly. But I'm noticing line 1663 changed from a hardcodedpadding-left: 1.25remto using the CSS variable with a fallback — that's a subtle behavior shift I should investigate by looking at the actual file and checking what selector that applies to. I also need to verify how thedata-rtl-itemattribute works in the AST. Actually, there's another thing to consider: therehypeAutoTextDirectionplugin sets thedirproperty, but in ChatMarkdown with parseRawHtml enabled, the plugin runs after sanitization. Without raw HTML, the plugin array only contains the direction plugin, whereas before it was undefined. I should check if there were other rehype plugins being applied in the non-raw case that I might be missing. I'm noticing a potential issue with how direction properties cascade when there are nested lists. Settingdirection: ltron the parent ul or ol works fine, but when a list item hasdir="auto", nested lists inside it might not behave as expected—the LTR direction could conflict with the RTL context of the parent li. For tables, I need to verify that the.chat-markdown-table-containerclass is actually applied to the outer wrapper, and I'm checking howtext-align: startresolves for table cells withdir="auto". Since the cell's own direction determines howstartaligns, an Arabic cell would correctly align right, which seems intentional. For task list items, the checkbox margin uses the list gutter variable, and when the item is RTL, the negative margin-inline-start hangs the checkbox into the right gutter as expected. The first-letter detection correctly identifies Arabic text in the task item to set the RTL flag. I'm noticing a minor divergence:firstLetterchecks the first letter, butdir="auto"technically uses the first strong character, though this is acknowledged in the comments. Now I need to verify whether the plugin actually runs ondata-alertblockquotes by checking the property name used in this codebase, and I should also look at whether other markdown renderers exist that use the.chat-markdownclass without the plugin applied. I'm looking at specific sections of the ChatMarkdown file to understand the table container structure, details section, and plugin configuration across different line ranges. Looking at the CollapsibleTrigger with the chevron icon in a flex row — when the summary is in Arabic and the layout flips to RTL, the chevron ends up on the right side of the text, but it still points rightward when collapsed, which creates a visual inconsistency since in RTL a collapsed disclosure should point left instead. The rotation animation works fine for the open state, pointing downward, but that initial chevron direction in the collapsed state feels off. I'm weighing whether this counts as a concrete regression or just an aesthetic inconsistency. Before this change, Arabic details were rendered LTR, so this RTL mirroring is actually new behavior. The real issue is that the chevron iconography needs special handling — either applying a 180-degree rotation in RTL mode or flipping it horizontally so that when the 90-degree open rotation is applied, it points upward instead of downward. It's a subtle but important detail for proper RTL support. Now I'm checking the padding on the CollapsiblePanel content — theps-6is already using logical spacing, which is correct. In fact, if I putdir="auto"only on the root and remove it from the trigger, the root would skip over descendants that have their owndirattribute set, so it would read the first strong character from the summary text itself — which should give me the right directionality for the whole component without the mismatch between the chevron and the body indent. I should verify that the Collapsible root actually forwards thedirprop through to the rendered div, and then check whether this inconsistency is worth fixing — it's a real issue introduced by the change, though the visual impact depends on how the RTL layout actually renders with the current padding and alignment. Let me scan for other potential problems with the CSS rules, particularly around how inline styles and CSS variables interact with directional properties. Adding more styles... I should also check if ChatMarkdown is the only place where ReactMarkdown gets used with these rehypePlugins, or if there are other instances where the configuration might be overridden. I need to check whether the customlirenderer in ChatMarkdown is passing through thedirprop, especially for task list items that might have their own checkbox handler. The blockquote renderer for alerts also needs to be examined to see if it's properly forwarding props rather than destructuring them away. The renderers pass through thedirattribute for regular elements like paragraphs, list items, and non-alert blockquotes. For alert blockquotes, the plugin sets adataAlertproperty that survives sanitization since the schema allows it on blockquotes. I'm checking whether this property persists correctly in both the raw path and the non-raw path where remarkGithubAlerts is applied. The alert container itself uses physical padding and borders, which is fine since it's not RTL-aware. List items properly pass through thedirattribute, and I'm now examining the interaction between the globaldirection: ltrrule on lists and RTL task items — specifically how the checkbox positioning works withmargin-inline-startin RTL contexts. I'm also considering whether thetext-align: startchange on table cells might be over-reaching: GFM tables with mixed Arabic and English content could become visually ragged if cells align differently per-language, whereas previously they all aligned left. This could be a regression depending on the desired behavior. TheMarkdownDetailstrigger withdir="auto"andtext-startshould work correctly for Arabic text, and I'm continuing to verify other components likeScrollAreastyling. I'm noticing that the CSS rule for.chat-markdown presets direction to left-to-right, and since shiki generates<pre class="shiki">elements, that selector applies to the code blocks. The.chat-markdown-codeblockwrapper also contains a header with the code title. When a fenced code block appears inside an RTL list item or blockquote, the wrapper div inherits the RTL direction. The header uses flexbox with justify-between, which reverses the flex direction in RTL, so the title and action buttons swap sides. But the padding values likepr-1.5andpl-3are physical units that don't flip with the direction change—so now I'm seeing an inconsistency where the layout mirrors but the padding doesn't adjust accordingly, creating misalignment in the code block header when it's nested in RTL content. The PR author pinned thepreelement itself todirection: ltron web, but the wrapper div (.chat-markdown-codeblock) that contains the header and pre isn't pinned. This means the header row still mirrors in RTL contexts, whereas the table container got the full treatment withdirection: ltrapplied to the whole thing including its footer chrome. The fix should applydirection: ltrto the code block wrapper, not just the inner pre element, to match how tables are handled. The code block header uses padding and flexbox to maintain proper alignment in both LTR and RTL contexts, though the header itself doesn't inherit the direction property. Thepreelements are explicitly set to LTR direction to ensure the scroll starts from the left, which is applied consistently across both the general markdown code blocks and the specific chat markdown code blocks. The fix would be to applydirection: ltrto the.chat-markdown .chat-markdown-codeblockcontainer itself rather than just thepreelement, matching the approach used for table containers. This is important because code blocks commonly appear inside RTL list items or blockquotes in chat (like numbered lists with code examples), so the direction inheritance from parent RTL elements is a realistic scenario introduced by the recent changes. For inline elements like file-link chips within RTL paragraphs, the mirroring behavior is probably acceptable. Now I'm checking theMarkdownDetailscomponent — the trigger hasdir="auto"while the panel usesps-6padding, which means the trigger gets mirrored in RTL but the body content inherits LTR from the document root, creating a mismatch where the chevron and title appear on the right but the body stays indented from the left. The solution is to movedir="auto"to theCollapsibleroot element instead of just the trigger, so both the trigger and panel resolve their direction together. Since the root's auto resolution reads the first strong character from the trigger text (skipping descendants with their owndir), this should work correctly. The Base UICollapsiblecomponent spreads unknown props to its rendered element, so forwardingdirshould be fine. I'll suggest this as a small unified diff since the root element isn't in the current diff but the trigger is. I'm weighing whether this is worth flagging—I've already reported three rounds of issues and they've fixed them, so I don't want to be too aggressive with noise. But the check defaults to failure and this is a concrete violation introduced by the changed line: thedir="auto"on the trigger creates a mirrored header over a non-mirrored body, plus the chevron points right in RTL. Let me verify the codeblock issue is solid and scan for other violations of equal weight. Looking at other candidates: theMarkdownTablecontainer direction is fine, but the Alert callout has a similar problem—the container stays LTR while individual paragraphs getdir="auto", creating a mix of left border rail with right-aligned text in Arabic. ely, so the physical border would stay on the left even in RTL. The PR updated the blockquote's border to use logical properties but left the alert variant with physical borders—an inconsistency since alerts are blockquote-based. Now I'm checking the other elements: headings getdir="auto", which is fine, and the rest likehrand paragraphs look good. So my main findings are the codeblock chrome mirroring issue and the details panel's inconsistent handling between the indent and trigger. Let me verify whether the codeblock is actually affected by RTL ancestors. The ancestors that could resolve to RTL are list items withdir="auto", blockquotes withdir="auto", and table cells that might havedir="auto"even though the table container is pinned to LTR. A codeblock inside a table cell is definitely possible. This confirms the issue. The mobile client explicitly wraps code blocks indirection: "ltr", so the web version should match that for consistency across clients. Now I need to find the right line numbers in the diff to add comments—they have to be on the RIGHT side of the changed lines. The codeblock fix is around line 1797-1799 in index.css wheredirection: ltr;is being added to the pre element. Nested lists in RTL items get left padding even though they're marked as LTR, creating an extra 1.25rem gap on the left side—visually minor but the comment acknowledges this trade-off. Top-level Arabic lists also have unnecessary left inset since the ul itself is LTR, though this is acceptable for the overall approach. TheholdsRightToLeftItemcheck correctly looks only at direct children, but there's a potential issue: the plugin setsdataRtlItemon lists after rehypeSanitize runs, which could strip that attribute in the raw-HTML path. Actually, that's fine since the plugin runs after sanitization. ThedataRtlItemproperty serializes correctly todata-rtl-itemin the hast-to-jsx output, which the tests confirm. Now checking whetherdir="auto"applies properly to list items inside.chat-markdown-details. Looking at the padding issue more carefully —ps-6on line 577 means padding-inline-start, which resolves to left padding in LTR context since the panel inherits the Collapsible root's direction. The fix is to movedir="auto"to the Collapsible root itself, then provide a unified diff showing the addition. Since this spans multiple hunks across the component structure, I'll describe the fix in prose instead. Now I need to write out the two comments concisely — the first one addresses thepreelement being pinned LTR while theMarkdownCodeBlockwrapper uses physical padding properties that flip incorrectly in RTL contexts. Adding a CSS rule... The hunk includes the replaced className and three added lines, so line 566 is definitely part of the diff. Now I'm marking this as a failure due to the findings and posting the review.
1. modify_pr — Two direction-inheritance gaps in the web markdown chrome, both introduced by this PR's new RTL blocks.
Agent Credits: 110 credits