fix(rtl): fix resize direction, path alignment, and i18n gaps

- Invert resize delta in RTL for drawer (useDrawerResize) and split panel (RightPanel)
- Add dir="ltr" to path/code value elements in instance-info panel
- Replace hardcoded English strings with i18n: Hide/Show files, No git changes yet,
  Hide unchanged regions / Show full file, diff toolbar titles, + Create worktree
- Fix sessionList.status.idle: "בסרלה" → "מוכן" in session.ts
- Fix text-align: left → start in message-reasoning-toggle and tool-call-io-toggle
- Fix left: 0 → inset-inline-start: 0 in attachment-chip-preview

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
MusiCode
2026-03-18 01:48:45 +00:00
committed by Shantur Rathore
parent a6cb70ed41
commit eb77c06571
13 changed files with 52 additions and 19 deletions

View File

@@ -82,7 +82,7 @@ const InstanceInfo: Component<InstanceInfoProps> = (props) => {
<div class="panel-body space-y-3"> <div class="panel-body space-y-3">
<div> <div>
<div class="text-xs font-medium text-muted uppercase tracking-wide mb-1">{t("instanceInfo.labels.folder")}</div> <div class="text-xs font-medium text-muted uppercase tracking-wide mb-1">{t("instanceInfo.labels.folder")}</div>
<div class="text-xs text-primary font-mono break-all px-2 py-1.5 rounded border bg-surface-secondary border-base"> <div dir="ltr" class="text-xs text-primary font-mono break-all px-2 py-1.5 rounded border bg-surface-secondary border-base">
{currentInstance().folder} {currentInstance().folder}
</div> </div>
</div> </div>
@@ -94,7 +94,7 @@ const InstanceInfo: Component<InstanceInfoProps> = (props) => {
<div class="text-xs font-medium text-muted uppercase tracking-wide mb-1"> <div class="text-xs font-medium text-muted uppercase tracking-wide mb-1">
{t("instanceInfo.labels.project")} {t("instanceInfo.labels.project")}
</div> </div>
<div class="text-xs font-mono px-2 py-1.5 rounded border truncate bg-surface-secondary border-base text-primary"> <div dir="ltr" class="text-xs font-mono px-2 py-1.5 rounded border truncate bg-surface-secondary border-base text-primary">
{project().id} {project().id}
</div> </div>
</div> </div>
@@ -137,7 +137,7 @@ const InstanceInfo: Component<InstanceInfoProps> = (props) => {
<div class="text-xs font-medium text-muted uppercase tracking-wide mb-1"> <div class="text-xs font-medium text-muted uppercase tracking-wide mb-1">
{t("instanceInfo.labels.binaryPath")} {t("instanceInfo.labels.binaryPath")}
</div> </div>
<div class="text-xs font-mono break-all px-2 py-1.5 rounded border bg-surface-secondary border-base text-primary"> <div dir="ltr" class="text-xs font-mono break-all px-2 py-1.5 rounded border bg-surface-secondary border-base text-primary">
{currentInstance().binaryPath} {currentInstance().binaryPath}
</div> </div>
</div> </div>
@@ -151,7 +151,7 @@ const InstanceInfo: Component<InstanceInfoProps> = (props) => {
<div class="space-y-1"> <div class="space-y-1">
<For each={environmentEntries()}> <For each={environmentEntries()}>
{([key, value]) => ( {([key, value]) => (
<div class="flex items-center gap-2 px-2 py-1.5 rounded border bg-surface-secondary border-base"> <div dir="ltr" class="flex items-center gap-2 px-2 py-1.5 rounded border bg-surface-secondary border-base">
<span class="text-xs font-mono font-medium flex-1 text-primary" title={key}> <span class="text-xs font-mono font-medium flex-1 text-primary" title={key}>
{key} {key}
</span> </span>

View File

@@ -249,7 +249,8 @@ const RightPanel: Component<RightPanelProps> = (props) => {
const mode = activeSplitResize() const mode = activeSplitResize()
if (!mode) return if (!mode) return
event.preventDefault() event.preventDefault()
const delta = event.clientX - splitResizeStartX() const isRtl = typeof document !== "undefined" && document.documentElement.dir === "rtl"
const delta = (event.clientX - splitResizeStartX()) * (isRtl ? -1 : 1)
const next = clampSplitWidth(splitResizeStartWidth() + delta) const next = clampSplitWidth(splitResizeStartWidth() + delta)
if (mode === "changes") setChangesSplitWidth(next) if (mode === "changes") setChangesSplitWidth(next)
else if (mode === "git-changes") setGitChangesSplitWidth(next) else if (mode === "git-changes") setGitChangesSplitWidth(next)
@@ -272,7 +273,8 @@ const RightPanel: Component<RightPanelProps> = (props) => {
const touch = event.touches[0] const touch = event.touches[0]
if (!touch) return if (!touch) return
event.preventDefault() event.preventDefault()
const delta = touch.clientX - splitResizeStartX() const isRtl = typeof document !== "undefined" && document.documentElement.dir === "rtl"
const delta = (touch.clientX - splitResizeStartX()) * (isRtl ? -1 : 1)
const next = clampSplitWidth(splitResizeStartWidth() + delta) const next = clampSplitWidth(splitResizeStartWidth() + delta)
if (mode === "changes") setChangesSplitWidth(next) if (mode === "changes") setChangesSplitWidth(next)
else if (mode === "git-changes") setGitChangesSplitWidth(next) else if (mode === "git-changes") setGitChangesSplitWidth(next)

View File

@@ -2,6 +2,7 @@ import type { Component } from "solid-js"
import { AlignJustify, FoldVertical, Split, UnfoldVertical, WrapText } from "lucide-solid" import { AlignJustify, FoldVertical, Split, UnfoldVertical, WrapText } from "lucide-solid"
import { useI18n } from "../../../../../lib/i18n"
import type { DiffContextMode, DiffViewMode, DiffWordWrapMode } from "../types" import type { DiffContextMode, DiffViewMode, DiffWordWrapMode } from "../types"
interface DiffToolbarProps { interface DiffToolbarProps {
@@ -14,14 +15,15 @@ interface DiffToolbarProps {
} }
const DiffToolbar: Component<DiffToolbarProps> = (props) => { const DiffToolbar: Component<DiffToolbarProps> = (props) => {
const { t } = useI18n()
const nextViewMode = (): DiffViewMode => (props.viewMode === "split" ? "unified" : "split") const nextViewMode = (): DiffViewMode => (props.viewMode === "split" ? "unified" : "split")
const nextContextMode = (): DiffContextMode => (props.contextMode === "collapsed" ? "expanded" : "collapsed") const nextContextMode = (): DiffContextMode => (props.contextMode === "collapsed" ? "expanded" : "collapsed")
const nextWordWrapMode = (): DiffWordWrapMode => (props.wordWrapMode === "on" ? "off" : "on") const nextWordWrapMode = (): DiffWordWrapMode => (props.wordWrapMode === "on" ? "off" : "on")
const viewModeTitle = () => (nextViewMode() === "split" ? "Switch to split view" : "Switch to unified view") const viewModeTitle = () => (nextViewMode() === "split" ? t("instanceShell.diff.switchToSplit") : t("instanceShell.diff.switchToUnified"))
const contextModeTitle = () => const contextModeTitle = () =>
nextContextMode() === "collapsed" ? "Hide unchanged regions" : "Show full file" nextContextMode() === "collapsed" ? t("instanceShell.diff.hideUnchanged") : t("instanceShell.diff.showFull")
const wordWrapTitle = () => (nextWordWrapMode() === "on" ? "Enable word wrap" : "Disable word wrap") const wordWrapTitle = () => (nextWordWrapMode() === "on" ? t("instanceShell.diff.enableWordWrap") : t("instanceShell.diff.disableWordWrap"))
return ( return (
<div class="file-viewer-toolbar"> <div class="file-viewer-toolbar">

View File

@@ -1,5 +1,6 @@
import { Show, type Component, type JSX } from "solid-js" import { Show, type Component, type JSX } from "solid-js"
import { useI18n } from "../../../../../lib/i18n"
import OverlayList from "./OverlayList" import OverlayList from "./OverlayList"
type SplitFilePanelList = { type SplitFilePanelList = {
@@ -24,12 +25,13 @@ interface SplitFilePanelProps {
} }
const SplitFilePanel: Component<SplitFilePanelProps> = (props) => { const SplitFilePanel: Component<SplitFilePanelProps> = (props) => {
const { t } = useI18n()
return ( return (
<div class="files-tab-container"> <div class="files-tab-container">
<div class="files-tab-header"> <div class="files-tab-header">
<div class="files-tab-header-row"> <div class="files-tab-header-row">
<button type="button" class="files-toggle-button" onClick={props.onToggleList}> <button type="button" class="files-toggle-button" onClick={props.onToggleList}>
{props.listOpen ? "Hide files" : "Show files"} {props.listOpen ? t("instanceShell.filesShell.hideFiles") : t("instanceShell.filesShell.showFiles")}
</button> </button>
{props.header} {props.header}

View File

@@ -82,7 +82,7 @@ const GitChangesTab: Component<GitChangesTabProps> = (props) => {
}) })
const emptyViewerMessage = createMemo(() => { const emptyViewerMessage = createMemo(() => {
if (!hasSession()) return props.t("instanceShell.sessionChanges.noSessionSelected") if (!hasSession()) return props.t("instanceShell.gitChanges.noSessionSelected")
const currentEntries = entries() const currentEntries = entries()
if (currentEntries === null) return props.t("instanceShell.gitChanges.loading") if (currentEntries === null) return props.t("instanceShell.gitChanges.loading")
if (nonDeleted().length === 0) return props.t("instanceShell.gitChanges.empty") if (nonDeleted().length === 0) return props.t("instanceShell.gitChanges.empty")

View File

@@ -46,7 +46,9 @@ export function useDrawerResize(options: DrawerResizeOptions): DrawerResizeApi {
if (!side) return if (!side) return
const startWidth = resizeStartWidth() const startWidth = resizeStartWidth()
const clamp = side === "left" ? options.clampLeft : options.clampRight const clamp = side === "left" ? options.clampLeft : options.clampRight
const delta = side === "left" ? clientX - resizeStartX() : resizeStartX() - clientX const isRtl = typeof document !== "undefined" && document.documentElement.dir === "rtl"
const rawDelta = side === "left" ? clientX - resizeStartX() : resizeStartX() - clientX
const delta = isRtl ? -rawDelta : rawDelta
const nextWidth = clamp(startWidth + delta) const nextWidth = clamp(startWidth + delta)
applyDrawerWidth(side, nextWidth) applyDrawerWidth(side, nextWidth)
} }

View File

@@ -18,6 +18,7 @@ import {
setWorktreeSlugForParentSession, setWorktreeSlugForParentSession,
} from "../stores/worktrees" } from "../stores/worktrees"
import { sessions } from "../stores/sessions" import { sessions } from "../stores/sessions"
import { useI18n } from "../lib/i18n"
const log = getLogger("session") const log = getLogger("session")
@@ -25,8 +26,6 @@ type WorktreeOption =
| { kind: "action"; key: "__create__"; label: string } | { kind: "action"; key: "__create__"; label: string }
| { kind: "worktree"; key: string; slug: string; directory: string; raw: WorktreeDescriptor } | { kind: "worktree"; key: string; slug: string; directory: string; raw: WorktreeDescriptor }
const CREATE_OPTION: WorktreeOption = { kind: "action", key: "__create__", label: "+ Create worktree" }
function preventSelectPress(event: PointerEvent | MouseEvent) { function preventSelectPress(event: PointerEvent | MouseEvent) {
// Prevent Select.Item from treating this as a selection. // Prevent Select.Item from treating this as a selection.
// We intentionally prevent default to stop Kobalte's internal press handling. // We intentionally prevent default to stop Kobalte's internal press handling.
@@ -71,6 +70,7 @@ interface WorktreeSelectorProps {
} }
export default function WorktreeSelector(props: WorktreeSelectorProps) { export default function WorktreeSelector(props: WorktreeSelectorProps) {
const { t } = useI18n()
const [isOpen, setIsOpen] = createSignal(false) const [isOpen, setIsOpen] = createSignal(false)
const [createOpen, setCreateOpen] = createSignal(false) const [createOpen, setCreateOpen] = createSignal(false)
const [createSlug, setCreateSlug] = createSignal("") const [createSlug, setCreateSlug] = createSignal("")
@@ -99,7 +99,8 @@ export default function WorktreeSelector(props: WorktreeSelectorProps) {
directory: wt.directory, directory: wt.directory,
raw: wt, raw: wt,
})) }))
return [CREATE_OPTION, ...mapped] const createOption: WorktreeOption = { kind: "action", key: "__create__", label: t("instanceShell.worktree.create") }
return [createOption, ...mapped]
}) })
const selectedOption = createMemo<WorktreeOption | undefined>(() => { const selectedOption = createMemo<WorktreeOption | undefined>(() => {

View File

@@ -124,6 +124,18 @@ export const instanceMessages = {
"instanceShell.filesShell.viewerTitle": "Change viewer", "instanceShell.filesShell.viewerTitle": "Change viewer",
"instanceShell.filesShell.viewerPlaceholder": "Detailed change rendering will be added in the next step.", "instanceShell.filesShell.viewerPlaceholder": "Detailed change rendering will be added in the next step.",
"instanceShell.filesShell.viewerEmpty": "No file selected.", "instanceShell.filesShell.viewerEmpty": "No file selected.",
"instanceShell.filesShell.hideFiles": "Hide files",
"instanceShell.filesShell.showFiles": "Show files",
"instanceShell.gitChanges.noSessionSelected": "Select a session to view git changes.",
"instanceShell.gitChanges.loading": "Loading git changes…",
"instanceShell.gitChanges.empty": "No git changes yet.",
"instanceShell.diff.hideUnchanged": "Hide unchanged regions",
"instanceShell.diff.showFull": "Show full file",
"instanceShell.diff.switchToSplit": "Switch to split view",
"instanceShell.diff.switchToUnified": "Switch to unified view",
"instanceShell.diff.enableWordWrap": "Enable word wrap",
"instanceShell.diff.disableWordWrap": "Disable word wrap",
"instanceShell.worktree.create": "+ Create worktree",
"instanceShell.plan.noSessionSelected": "Select a session to view plan.", "instanceShell.plan.noSessionSelected": "Select a session to view plan.",
"instanceShell.plan.empty": "Nothing planned yet.", "instanceShell.plan.empty": "Nothing planned yet.",

View File

@@ -120,6 +120,18 @@ export const instanceMessages = {
"instanceShell.filesShell.viewerTitle": "מציג שינויים", "instanceShell.filesShell.viewerTitle": "מציג שינויים",
"instanceShell.filesShell.viewerPlaceholder": "תצוגת שינויים מפורטת תתווסף בשלב הבא.", "instanceShell.filesShell.viewerPlaceholder": "תצוגת שינויים מפורטת תתווסף בשלב הבא.",
"instanceShell.filesShell.viewerEmpty": "לא נבחר קובץ.", "instanceShell.filesShell.viewerEmpty": "לא נבחר קובץ.",
"instanceShell.filesShell.hideFiles": "הסתר קבצים",
"instanceShell.filesShell.showFiles": "הצג קבצים",
"instanceShell.gitChanges.noSessionSelected": "בחר סשן לצפייה בשינויי Git.",
"instanceShell.gitChanges.loading": "טוען שינויי Git…",
"instanceShell.gitChanges.empty": "אין שינויי Git עדיין.",
"instanceShell.diff.hideUnchanged": "הסתר אזורים ללא שינוי",
"instanceShell.diff.showFull": "הצג קובץ מלא",
"instanceShell.diff.switchToSplit": "עבור לתצוגה מפוצלת",
"instanceShell.diff.switchToUnified": "עבור לתצוגה מאוחדת",
"instanceShell.diff.enableWordWrap": "הפעל גלישת מילים",
"instanceShell.diff.disableWordWrap": "כבה גלישת מילים",
"instanceShell.worktree.create": "+ צור worktree",
"instanceShell.plan.noSessionSelected": "בחר סשן לצפייה בתוכנית.", "instanceShell.plan.noSessionSelected": "בחר סשן לצפייה בתוכנית.",
"instanceShell.plan.empty": "עדיין לא תוכנן דבר.", "instanceShell.plan.empty": "עדיין לא תוכנן דבר.",

View File

@@ -14,7 +14,7 @@ export const sessionMessages = {
"sessionList.session.untitled": "ללא שם", "sessionList.session.untitled": "ללא שם",
"sessionList.status.working": "עובד", "sessionList.status.working": "עובד",
"sessionList.status.compacting": "מסכם", "sessionList.status.compacting": "מסכם",
"sessionList.status.idle": "בסרלה", "sessionList.status.idle": "מוכן",
"sessionList.status.needsPermission": "נדרש אישור", "sessionList.status.needsPermission": "נדרש אישור",
"sessionList.status.needsInput": "נדרש קלט", "sessionList.status.needsInput": "נדרש קלט",
"sessionList.expand.collapseAriaLabel": "כווץ סשן", "sessionList.expand.collapseAriaLabel": "כווץ סשן",

View File

@@ -424,7 +424,7 @@
padding: 0.25rem 0.6rem; padding: 0.25rem 0.6rem;
font: inherit; font: inherit;
color: inherit; color: inherit;
text-align: left; text-align: start;
cursor: pointer; cursor: pointer;
transition: background-color 0.2s ease, box-shadow 0.2s ease; transition: background-color 0.2s ease, box-shadow 0.2s ease;
} }

View File

@@ -256,7 +256,7 @@
display: none; display: none;
position: absolute; position: absolute;
bottom: calc(100% + 6px); bottom: calc(100% + 6px);
left: 0; inset-inline-start: 0;
padding: 8px; padding: 8px;
background-color: var(--surface-base); background-color: var(--surface-base);
border: 1px solid var(--border-base); border: 1px solid var(--border-base);

View File

@@ -257,7 +257,7 @@
border: none; border: none;
border-bottom: 1px solid var(--tool-call-border-color); border-bottom: 1px solid var(--tool-call-border-color);
width: 100%; width: 100%;
text-align: left; text-align: start;
font-size: 0.875rem; font-size: 0.875rem;
font-weight: normal; font-weight: normal;
color: var(--text-primary); color: var(--text-primary);