Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/web/src/components/ChatMarkdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,10 @@ function ChatMarkdown({ text, cwd, isStreaming = false }: ChatMarkdownProps) {
);

return (
<div className="chat-markdown w-full min-w-0 text-sm leading-relaxed text-foreground/80">
<div
dir="auto"
className="chat-markdown w-full min-w-0 text-sm leading-relaxed text-foreground/80"
>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={markdownComponents}
Expand Down
3 changes: 2 additions & 1 deletion apps/web/src/components/ComposerPromptEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1623,8 +1623,9 @@ function ComposerPromptEditorInner({
<PlainTextPlugin
contentEditable={
<ContentEditable
dir="auto"
className={cn(
"block max-h-[200px] min-h-17.5 w-full overflow-y-auto whitespace-pre-wrap break-words bg-transparent text-[14px] leading-relaxed text-foreground focus:outline-none",
"composer-editor-bidi block max-h-[200px] min-h-17.5 w-full overflow-y-auto whitespace-pre-wrap break-words bg-transparent text-[14px] leading-relaxed text-foreground focus:outline-none",
className,
)}
data-testid="composer-editor"
Expand Down
10 changes: 7 additions & 3 deletions apps/web/src/components/PlanSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ const PlanSidebar = memo(function PlanSidebar({
<div className="p-3 space-y-4">
{/* Explanation */}
{activePlan?.explanation ? (
<p className="text-[13px] leading-relaxed text-muted-foreground/80">
<p dir="auto" className="text-[13px] leading-relaxed text-muted-foreground/80">
{activePlan.explanation}
</p>
) : null}
Expand All @@ -216,6 +216,7 @@ const PlanSidebar = memo(function PlanSidebar({
>
<div className="mt-0.5">{stepStatusIcon(step.status)}</div>
<p
dir="auto"
className={cn(
"text-[13px] leading-snug",
step.status === "completed"
Expand All @@ -237,15 +238,18 @@ const PlanSidebar = memo(function PlanSidebar({
<div className="space-y-2">
<button
type="button"
className="group flex w-full items-center gap-1.5 text-left"
className="group flex w-full items-center gap-1.5 text-start"
onClick={() => setProposedPlanExpanded((v) => !v)}
>
{proposedPlanExpanded ? (
<ChevronDownIcon className="size-3 shrink-0 text-muted-foreground/40 transition-transform" />
) : (
<ChevronRightIcon className="size-3 shrink-0 text-muted-foreground/40 transition-transform" />
)}
<span className="text-[10px] font-semibold tracking-widest text-muted-foreground/40 uppercase group-hover:text-muted-foreground/60">
<span
dir="auto"
className="text-[10px] font-semibold tracking-widest text-muted-foreground/40 uppercase group-hover:text-muted-foreground/60"
>
{planTitle ?? "Full Plan"}
</span>
</button>
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP
<TooltipTrigger
render={
<span
dir="auto"
className="min-w-0 flex-1 truncate text-xs"
data-testid={`thread-title-${thread.id}`}
>
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/components/chat/ChatHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export const ChatHeader = memo(function ChatHeader({
<div className="flex min-w-0 flex-1 items-center gap-2 overflow-hidden sm:gap-3">
<SidebarTrigger className="size-7 shrink-0 md:hidden" />
<h2
dir="auto"
className="min-w-0 shrink truncate text-sm font-medium text-foreground"
title={activeThreadTitle}
>
Expand Down
18 changes: 12 additions & 6 deletions apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,13 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard(
</span>
</div>
</div>
<p className="mt-1.5 text-sm text-foreground/90">{activeQuestion.question}</p>
<p dir="auto" className="mt-1.5 text-sm text-foreground/90">
{activeQuestion.question}
</p>
{activeQuestion.multiSelect ? (
<p className="mt-1 text-xs text-muted-foreground/65">Select one or more options.</p>
<p dir="auto" className="mt-1 text-xs text-muted-foreground/65">
Select one or more options.
</p>
) : null}
<div className="mt-3 space-y-1">
{activeQuestion.options.map((option, index) => {
Expand All @@ -152,7 +156,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard(
disabled={isResponding}
onClick={() => handleOptionSelection(activeQuestion.id, option.label)}
className={cn(
"group flex w-full items-center gap-3 rounded-lg border px-3 py-2 text-left transition-all duration-150",
"group flex w-full items-center gap-3 rounded-lg border px-3 py-2 text-start transition-all duration-150",
isSelected
? "border-blue-500/40 bg-blue-500/8 text-foreground"
: "border-transparent bg-muted/20 text-foreground/80 hover:bg-muted/40 hover:border-border/40",
Expand All @@ -171,10 +175,12 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard(
{shortcutKey}
</kbd>
) : null}
<div className="min-w-0 flex-1">
<span className="text-sm font-medium">{option.label}</span>
<div className="flex min-w-0 flex-1 flex-wrap items-baseline gap-x-2">
<span dir="auto" className="text-sm font-medium">
{option.label}
</span>
{option.description && option.description !== option.label ? (
<span className="ml-2 text-xs text-muted-foreground/50">
<span dir="auto" className="text-xs text-muted-foreground/50">
{option.description}
</span>
) : null}
Expand Down
4 changes: 3 additions & 1 deletion apps/web/src/components/chat/ComposerPlanFollowUpBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ export const ComposerPlanFollowUpBanner = memo(function ComposerPlanFollowUpBann
<div className="flex flex-wrap items-center gap-2">
<span className="uppercase text-sm tracking-[0.2em]">Plan ready</span>
{planTitle ? (
<span className="min-w-0 flex-1 truncate text-sm font-medium">{planTitle}</span>
<span dir="auto" className="min-w-0 flex-1 truncate text-sm font-medium">
{planTitle}
</span>
) : null}
</div>
{/* <div className="mt-2 text-xs text-muted-foreground">
Expand Down
15 changes: 12 additions & 3 deletions apps/web/src/components/chat/MessagesTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,10 @@ const UserMessageBody = memo(function UserMessageBody(props: {
}

return (
<div className="whitespace-pre-wrap wrap-break-word text-sm leading-relaxed text-foreground">
<div
dir="auto"
className="user-message-text whitespace-pre-wrap wrap-break-word text-sm leading-relaxed text-foreground"
>
{inlineNodes}
</div>
);
Expand Down Expand Up @@ -757,7 +760,10 @@ const UserMessageBody = memo(function UserMessageBody(props: {
}

return (
<div className="whitespace-pre-wrap wrap-break-word text-sm leading-relaxed text-foreground">
<div
dir="auto"
className="user-message-text whitespace-pre-wrap wrap-break-word text-sm leading-relaxed text-foreground"
>
{inlineNodes}
</div>
);
Expand All @@ -768,7 +774,10 @@ const UserMessageBody = memo(function UserMessageBody(props: {
}

return (
<div className="whitespace-pre-wrap wrap-break-word text-sm leading-relaxed text-foreground">
<div
dir="auto"
className="user-message-text whitespace-pre-wrap wrap-break-word text-sm leading-relaxed text-foreground"
>
{props.text}
</div>
);
Expand Down
4 changes: 3 additions & 1 deletion apps/web/src/components/chat/ProposedPlanCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ export const ProposedPlanCard = memo(function ProposedPlanCard({
<div className="flex flex-wrap items-center justify-between gap-3">
<div className="flex min-w-0 items-center gap-2">
<Badge variant="secondary">Plan</Badge>
<p className="truncate text-sm font-medium text-foreground">{title}</p>
<p dir="auto" className="truncate text-sm font-medium text-foreground">
{title}
</p>
</div>
<Menu>
<MenuTrigger
Expand Down
4 changes: 3 additions & 1 deletion apps/web/src/components/settings/SettingsPanels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1603,7 +1603,9 @@ export function ArchivedThreadsPanel() {
}}
>
<div className="min-w-0 flex-1">
<h3 className="truncate text-sm font-medium text-foreground">{thread.title}</h3>
<h3 dir="auto" className="truncate text-sm font-medium text-foreground">
{thread.title}
</h3>
<p className="text-xs text-muted-foreground">
Archived {formatRelativeTimeLabel(thread.archivedAt ?? thread.createdAt)}
{" \u00b7 Created "}
Expand Down
40 changes: 35 additions & 5 deletions apps/web/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,36 @@ label:has(> select#reasoning-effort) select {
word-break: break-word;
}

/* Bidirectional text direction detection for mixed RTL/LTR content */
.chat-markdown p,
.chat-markdown li,
.chat-markdown td,
.chat-markdown th,
.chat-markdown h1,
.chat-markdown h2,
.chat-markdown h3,
.chat-markdown h4,
.chat-markdown h5,
.chat-markdown h6,
.chat-markdown blockquote {
unicode-bidi: plaintext;
}
Comment thread
cursor[bot] marked this conversation as resolved.

/* Code and tables remain LTR regardless of surrounding text direction */
.chat-markdown pre,
.chat-markdown code,
.chat-markdown table {
direction: ltr;
unicode-bidi: isolate;
}

/* Per-line direction detection for pre-wrap user messages and composer */
.user-message-text,
.composer-editor-bidi,
.composer-editor-bidi p {
unicode-bidi: plaintext;
}
Comment thread
darkyeg marked this conversation as resolved.

.chat-markdown > :first-child {
margin-top: 0;
}
Expand All @@ -270,12 +300,12 @@ label:has(> select#reasoning-effort) select {
}

.chat-markdown ul {
padding-left: 1.25rem;
padding-inline-start: 1.25rem;
list-style-type: disc;
}

.chat-markdown ol {
padding-left: 1.25rem;
padding-inline-start: 1.25rem;
list-style-type: decimal;
}

Expand Down Expand Up @@ -310,8 +340,8 @@ label:has(> select#reasoning-effort) select {
}

.chat-markdown blockquote {
border-left: 2px solid var(--border);
padding-left: 0.8rem;
border-inline-start: 2px solid var(--border);
padding-inline-start: 0.8rem;
color: var(--muted-foreground);
}

Expand Down Expand Up @@ -457,7 +487,7 @@ label:has(> select#reasoning-effort) select {
.chat-markdown td {
border: 1px solid var(--border);
padding: 0.35rem 0.45rem;
text-align: left;
text-align: start;
}

/* Diffs theme bridge (match diff surfaces to app palette) */
Expand Down
Loading