feat(vscode): add Display setting for prompt navigator rail position - #13338
feat(vscode): add Display setting for prompt navigator rail position#13338sylwester-liljegren wants to merge 2 commits into
Conversation
The prompt navigator rail was hardcoded to the left edge of the transcript. Add a Prompt Navigator Position setting under Settings > Display so it can be moved to the right edge instead, with left kept as the default. The rail, its hover card placement, tick growth direction, and open animation all mirror to the selected side. The new prompt_rail_position key is added to the shared config schema so the backend accepts it, and to the generated SDK contract.
| const min = Math.max(EDGE, rect.top + 4) | ||
| const max = Math.min(window.innerHeight - EDGE, rect.bottom - 4) - height | ||
| const center = rect.top + rect.height / 2 - height / 2 | ||
| const isRight = props.position() === "right" |
There was a problem hiding this comment.
WARNING: Right-edge placement mixes logical CSS with physical card math, which breaks RTL
ar/fa set document.documentElement.dir = "rtl". The new right-edge CSS uses inset-inline-end, so choosing Right puts the rail on the physical left. This place() path then sets right: window.innerWidth - rect.left + GAP; with the rail already on the left that value is roughly 100vw and the hover card is pushed off-screen. Tick transform-origin: right and prompt-rail-in-right have the same physical assumption.
Suggestion: use physical left/right in CSS to match the setting labels, or keep logical insets and derive the card side from getBoundingClientRect() (open toward the larger gap).
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
|
|
||
| .prompt-rail[data-position="right"] { | ||
| inset-inline-start: auto; | ||
| inset-inline-end: var(--prompt-rail-edge); |
There was a problem hiding this comment.
SUGGESTION: 8px end gutter sits on the transcript scrollbar and scroll-to-bottom control
--prompt-rail-edge was sized for Agent Manager's left splitter. On the right, .message-list paints a 10px scrollbar (scrollbar-gutter: stable / ::-webkit-scrollbar { width: 10px }) and .scroll-to-bottom-button is right: 12px with no z-index, while the rail is z-index: 2 with pointer-events: auto on ticks. On long sessions those ticks can cover the inner scrollbar edge and the scroll-to-bottom hit target.
Suggestion: inset the right rail by the scrollbar as well, e.g. calc(var(--chat-scrollbar-width, 10px) + var(--prompt-rail-edge)).
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| opacity: 1; | ||
| } | ||
|
|
||
| .prompt-rail[data-position="right"] { |
There was a problem hiding this comment.
SUGGESTION: Add a Storybook story for the right-edge rail
Existing PromptRailWide / PromptRailSidebar / PromptRailManyPrompts stories only exercise the default left rail. This is a significant layout change; a PromptRail - right edge story with config={{ prompt_rail_position: "right" }} would cover ticks, hover-card direction, and the scrollbar relationship. StoryProviders already accepts config.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| "Controls whether MCP and generic tool blocks are expanded or collapsed by default in the VS Code chat UI", | ||
| }), | ||
| // kilocode_change start | ||
| prompt_rail_position: Schema.optional(Schema.Literals(["left", "right"])).annotate({ |
There was a problem hiding this comment.
SUGGESTION: Mirror prompt_rail_position in the cloud config JSON Schema
This file notes that new kilocode_change keys on Config.Info must also be added in apps/web/src/app/config.json/extras.ts in the cloud repo. Until that lands, $schema: https://app.kilo.ai/config.json will treat the key as unknown. CI does not check this.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Code Review SummaryStatus: 1 Issue Found | Recommendation: Address before merge Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (33 files)
Fix these issues in Kilo Cloud Previous Review Summary (commit 17c2413)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 17c2413)Status: 4 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (31 files)
Reviewed by grok-4.6 · Input: 80.3K · Output: 12.6K · Cached: 652.7K Review guidance: REVIEW.md from base branch |
…rollbar Addresses review feedback on the prompt navigator position setting. The rail placed itself with logical insets while place() anchors the hover card with physical getBoundingClientRect/innerWidth math. Under ar/fa the logical inset flipped the rail without flipping that math, so choosing Right put the rail on the physical left and pushed the card roughly a viewport off-screen. The rail now uses physical left/right, which also makes the Left and Right labels literally true, and the tick row is pinned to ltr so its flex alignment stops fighting the physical transform-origin. The right rail also sat on the transcript's reserved scrollbar gutter and over the scroll-to-bottom button. It now adds the existing --chat-scrollbar-width allowance on whichever physical side the scrollbar is on, and the button is lifted above the rail so ticks cannot swallow its click. Adds a right-edge Storybook story; the default-rail stories keep the real ConfigProvider so their baselines are untouched.
|
Thanks — three of the four are addressed in c9ad36f. Notes below. WARNING — logical CSS vs physical card math (RTL). Confirmed and fixed. I took the first option — physical
SUGGESTION — end gutter over the scrollbar and scroll-to-bottom control. Fixed, using the existing --prompt-rail-left: var(--prompt-rail-edge);
--prompt-rail-right: calc(var(--prompt-rail-edge) + var(--chat-scrollbar-width, 10px));with a The scroll-to-bottom overlap needed a second fix: an 18px inset still overlaps a control at SUGGESTION — Storybook story. Added SUGGESTION — cloud config JSON Schema. Valid and not actionable from this repo: Verification for this round, all agent-executed from |
Issue
No existing issue. This is a small, self-contained follow-up to the prompt navigator rail added in #12632, raised directly as a PR.
Context
The prompt navigator rail is hardcoded to the left edge of the transcript. That edge is not neutral for every layout: with the Kilo panel docked on the left of the editor the rail sits against the window frame, and in Agent Manager it shares an edge with the pane splitter. Users who keep the panel on the right, or who simply want the ticks nearer the scrollbar side, currently have no way to move it.
This adds a Prompt Navigator Position setting under Settings → Display, with Left (the existing behaviour, still the default) and Right.
Implementation
The rail already positions itself with logical properties, so most of the work was making the hover card placement and the growth directions side-aware rather than reworking layout.
prompt_rail_positionis added to the shared config schema (packages/core/src/v1/config/config.ts, marked withkilocode_change), to the webviewConfigtype, and toKNOWN_KEYSfor settings import/export. The schema entry is load-bearing: without it the backend rejects the save withConfigInvalidError, so the key has to exist on both sides of the wire. The generated SDK contract is updated to match.MessageListreads the config and passes an accessor down toPromptRail. The rail renders withdata-position, and CSS keys the right-edge variant off that attribute:inset-inline-endinstead ofinset-inline-start, ticks right-aligned, and tick lines scaling fromright centerso they still grow inward.position: fixedand was anchored withleft: rect.right + GAP. On the right edge it anchors withright: window.innerWidth - rect.left + GAPinstead, so the card opens inward, away from the window edge. The anchor object now carries an optionalleftorright, andcardStyle()emits only the one that is set — emitting both would stretch the card, because a fixed element withleft,right, and nowidthfills the gap between them.transform-originflips toright center, and a mirroredprompt-rail-in-rightkeyframe slides the card in from the opposite direction so the open animation still reads as emerging from the rail.Worth a reviewer's attention: the 8px
--prompt-rail-edgegutter exists to keep the ticks clear of Agent Manager's pane splitter. The right-edge variant deliberately reuses the same gutter on the opposite side rather than dropping it.All 20 non-English locales are translated, reusing each locale's existing wording for the navigator from
session.prompts.navLabelso the setting name matches the control it configures.Screenshots / Video
How to Test
Manual/local verification
ConfigInvalidErrorbecause the backend schema did not yet accept the key; adding it to the config schema resolved it and the save was re-verified.packages/kilo-vscode/:bun run lint,bun run typecheck(bothcheck-typesandcheck-types:webview),bun run knip,bun run format:check,bun esbuild.js(bundle, exit 0), andbun test ./tests/unit/i18n-keys.test.ts ./tests/unit/settings-io.test.ts(42 pass).bun run script/check-opencode-annotations.ts --worktree,bun run script/check-md-table-padding.ts,bun run script/check-workflows.ts, andbun turbo typecheck(29 of 29 TypeScript packages pass).Reviewer test steps
Blocked checks and substitute verification
@kilocode/kilo-jetbrains#typecheck, run as part of thebun turbo typecheckpre-push hook, could not complete: the Gradle toolchain requires Java 21 and this machine has only Java 24 installed with no toolchain download repositories configured. This PR touches no JetBrains files. Substitute verification: the samebun turbo typecheckrun passed for all 29 TypeScript packages, includingkilo-code,@kilocode/cli,@kilocode/sdk, and@opencode-ai/core. The branch was pushed with--no-verifyfor this reason.Checklist