Skip to content

feat(vscode): add Display setting for prompt navigator rail position - #13338

Open
sylwester-liljegren wants to merge 2 commits into
Kilo-Org:mainfrom
sylwester-liljegren:feat/prompt-navigator-position
Open

feat(vscode): add Display setting for prompt navigator rail position#13338
sylwester-liljegren wants to merge 2 commits into
Kilo-Org:mainfrom
sylwester-liljegren:feat/prompt-navigator-position

Conversation

@sylwester-liljegren

@sylwester-liljegren sylwester-liljegren commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

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_position is added to the shared config schema (packages/core/src/v1/config/config.ts, marked with kilocode_change), to the webview Config type, and to KNOWN_KEYS for settings import/export. The schema entry is load-bearing: without it the backend rejects the save with ConfigInvalidError, so the key has to exist on both sides of the wire. The generated SDK contract is updated to match.
  • MessageList reads the config and passes an accessor down to PromptRail. The rail renders with data-position, and CSS keys the right-edge variant off that attribute: inset-inline-end instead of inset-inline-start, ticks right-aligned, and tick lines scaling from right center so they still grow inward.
  • The hover card needed the only real logic change. It is position: fixed and was anchored with left: rect.right + GAP. On the right edge it anchors with right: window.innerWidth - rect.left + GAP instead, so the card opens inward, away from the window edge. The anchor object now carries an optional left or right, and cardStyle() emits only the one that is set — emitting both would stretch the card, because a fixed element with left, right, and no width fills the gap between them.
  • transform-origin flips to right center, and a mirrored prompt-rail-in-right keyframe 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-edge gutter 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.navLabel so the setting name matches the control it configures.

Screenshots / Video

image

How to Test

Manual/local verification

  • Human (PR author), in the Extension Development Host: set Settings → Display → Prompt Navigator Position to Right, saved, and confirmed the setting persists and the rail renders on the right edge of the chat. An earlier attempt surfaced ConfigInvalidError because the backend schema did not yet accept the key; adding it to the config schema resolved it and the save was re-verified.
  • Agent-executed, from packages/kilo-vscode/: bun run lint, bun run typecheck (both check-types and check-types:webview), bun run knip, bun run format:check, bun esbuild.js (bundle, exit 0), and bun test ./tests/unit/i18n-keys.test.ts ./tests/unit/settings-io.test.ts (42 pass).
  • Agent-executed, from the repo root: bun run script/check-opencode-annotations.ts --worktree, bun run script/check-md-table-padding.ts, bun run script/check-workflows.ts, and bun turbo typecheck (29 of 29 TypeScript packages pass).

Reviewer test steps

  1. Open the Kilo sidebar on a session with at least two prompts so the rail renders.
  2. Open Settings → Display, set Prompt Navigator Position to Right, and save.
  3. Confirm the tick rail moves to the right edge of the transcript and the readable lane width is unchanged.
  4. Hover a tick and confirm the preview card opens to the left of the rail, stays inside the viewport, and animates in from the right.
  5. Switch back to Left and confirm the original behaviour is restored.
  6. Repeat steps 2-4 in an Agent Manager tab and confirm the rail still clears the pane splitter while resizing.

Blocked checks and substitute verification

  • @kilocode/kilo-jetbrains#typecheck, run as part of the bun turbo typecheck pre-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 same bun turbo typecheck run passed for all 29 TypeScript packages, including kilo-code, @kilocode/cli, @kilocode/sdk, and @opencode-ai/core. The branch was pushed with --no-verify for this reason.

Checklist

  • Issue linked above, or exception explained
  • Tests/verification described
  • Screenshots/video included for visual changes, or marked N/A
  • Changeset considered for user-facing changes
  • I personally reviewed the diff and can explain the changes, including any AI-assisted work.

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.
@sylwester-liljegren
sylwester-liljegren marked this pull request as ready for review August 23, 2026 19:16
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"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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"] {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@kilo-code-bot

kilo-code-bot Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/core/src/v1/config/config.ts 137 Mirror prompt_rail_position in the cloud config JSON Schema
Files Reviewed (33 files)
  • .changeset/prompt-navigator-position.md
  • packages/core/src/v1/config/config.ts - 1 issue
  • packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx
  • packages/kilo-vscode/webview-ui/src/components/chat/PromptRail.tsx
  • packages/kilo-vscode/webview-ui/src/components/settings/DisplayTab.tsx
  • packages/kilo-vscode/webview-ui/src/components/settings/settings-io.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ar.ts
  • packages/kilo-vscode/webview-ui/src/i18n/br.ts
  • packages/kilo-vscode/webview-ui/src/i18n/bs.ts
  • packages/kilo-vscode/webview-ui/src/i18n/da.ts
  • packages/kilo-vscode/webview-ui/src/i18n/de.ts
  • packages/kilo-vscode/webview-ui/src/i18n/en.ts
  • packages/kilo-vscode/webview-ui/src/i18n/es.ts
  • packages/kilo-vscode/webview-ui/src/i18n/fa.ts
  • packages/kilo-vscode/webview-ui/src/i18n/fr.ts
  • packages/kilo-vscode/webview-ui/src/i18n/it.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ja.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ko.ts
  • packages/kilo-vscode/webview-ui/src/i18n/nl.ts
  • packages/kilo-vscode/webview-ui/src/i18n/no.ts
  • packages/kilo-vscode/webview-ui/src/i18n/pl.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ru.ts
  • packages/kilo-vscode/webview-ui/src/i18n/th.ts
  • packages/kilo-vscode/webview-ui/src/i18n/tr.ts
  • packages/kilo-vscode/webview-ui/src/i18n/uk.ts
  • packages/kilo-vscode/webview-ui/src/i18n/zh.ts
  • packages/kilo-vscode/webview-ui/src/i18n/zht.ts
  • packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx
  • packages/kilo-vscode/webview-ui/src/styles/chat-layout.css
  • packages/kilo-vscode/webview-ui/src/styles/prompt-rail.css
  • packages/kilo-vscode/webview-ui/src/types/messages/config.ts
  • packages/sdk/js/src/v2/gen/types.gen.ts
  • packages/sdk/openapi.json

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

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 3
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/webview-ui/src/components/chat/PromptRail.tsx 101 Right-edge placement mixes logical CSS with physical card math, which breaks RTL

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/src/styles/prompt-rail.css 45 8px end gutter sits on the transcript scrollbar and scroll-to-bottom control
packages/kilo-vscode/webview-ui/src/styles/prompt-rail.css 43 Add a Storybook story for the right-edge rail
packages/core/src/v1/config/config.ts 137 Mirror prompt_rail_position in the cloud config JSON Schema
Files Reviewed (31 files)
  • .changeset/prompt-navigator-position.md
  • packages/core/src/v1/config/config.ts - 1 issue
  • packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx
  • packages/kilo-vscode/webview-ui/src/components/chat/PromptRail.tsx - 1 issue
  • packages/kilo-vscode/webview-ui/src/components/settings/DisplayTab.tsx
  • packages/kilo-vscode/webview-ui/src/components/settings/settings-io.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ar.ts
  • packages/kilo-vscode/webview-ui/src/i18n/br.ts
  • packages/kilo-vscode/webview-ui/src/i18n/bs.ts
  • packages/kilo-vscode/webview-ui/src/i18n/da.ts
  • packages/kilo-vscode/webview-ui/src/i18n/de.ts
  • packages/kilo-vscode/webview-ui/src/i18n/en.ts
  • packages/kilo-vscode/webview-ui/src/i18n/es.ts
  • packages/kilo-vscode/webview-ui/src/i18n/fa.ts
  • packages/kilo-vscode/webview-ui/src/i18n/fr.ts
  • packages/kilo-vscode/webview-ui/src/i18n/it.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ja.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ko.ts
  • packages/kilo-vscode/webview-ui/src/i18n/nl.ts
  • packages/kilo-vscode/webview-ui/src/i18n/no.ts
  • packages/kilo-vscode/webview-ui/src/i18n/pl.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ru.ts
  • packages/kilo-vscode/webview-ui/src/i18n/th.ts
  • packages/kilo-vscode/webview-ui/src/i18n/tr.ts
  • packages/kilo-vscode/webview-ui/src/i18n/uk.ts
  • packages/kilo-vscode/webview-ui/src/i18n/zh.ts
  • packages/kilo-vscode/webview-ui/src/i18n/zht.ts
  • packages/kilo-vscode/webview-ui/src/styles/prompt-rail.css - 2 issues
  • packages/kilo-vscode/webview-ui/src/types/messages/config.ts
  • packages/sdk/js/src/v2/gen/types.gen.ts
  • packages/sdk/openapi.json

Fix these issues in Kilo Cloud


Reviewed by grok-4.6 · Input: 80.3K · Output: 12.6K · Cached: 652.7K

Review guidance: REVIEW.md from base branch main

…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.
@sylwester-liljegren

Copy link
Copy Markdown
Contributor Author

Thanks — three of the four are addressed in c9ad36f. Notes below.

WARNING — logical CSS vs physical card math (RTL). Confirmed and fixed. RTL_LOCALES is ["ar", "fa"], so this was real: inset-inline-end put the rail on the physical left under RTL while place() still computed right: window.innerWidth - rect.left + GAP, which is roughly a full viewport and threw the card off-screen.

I took the first option — physical left/right in CSS — because the setting is labelled Left/Right, so physical placement is what makes those labels literally true, and it lets the CSS and the inherently physical place() math agree in both directions. Two related mismatches came along with it:

  • .prompt-rail-tick is a row flex container, so its justify-content: flex-start followed text direction and pulled the hairline to the far side of the column under RTL, against the physical transform-origin. The tick row is now pinned to direction: ltr; it is a decorative line with an aria-label, never text.
  • This also repairs a latent pre-existing bug: the rail was already logical while place() was already physical, so the hover card was mispositioned under RTL before this PR too.

SUGGESTION — end gutter over the scrollbar and scroll-to-bottom control. Fixed, using the existing --chat-scrollbar-width token as suggested. Rather than hardcoding the right side, the allowance is applied to whichever physical side actually carries the scrollbar, since that is inline-end and therefore flips under RTL:

--prompt-rail-left: var(--prompt-rail-edge);
--prompt-rail-right: calc(var(--prompt-rail-edge) + var(--chat-scrollbar-width, 10px));

with a .prompt-rail:dir(rtl) rule swapping the two. The default left rail in LTR keeps its bare 8px gutter, so existing appearance is unchanged.

The scroll-to-bottom overlap needed a second fix: an 18px inset still overlaps a control at right: 12px that is 32px wide. .scroll-to-bottom-button now gets z-index: 3 so it sits above the rail's z-index: 2 and its click can't be swallowed by a tick hit target.

SUGGESTION — Storybook story. Added PromptRail - right edge (chat--prompt-rail-right-edge). StoryProviders does accept config, as you noted. The position is only forwarded when a story asks for it, so PromptRailWide / PromptRailSidebar / PromptRailManyPrompts keep using the real ConfigProvider and their baselines are untouched.

SUGGESTION — cloud config JSON Schema. Valid and not actionable from this repo: apps/web/src/app/config.json/extras.ts lives in Kilo-Org/cloud. Flagging it here so it isn't lost — prompt_rail_position needs a matching entry there before $schema: https://app.kilo.ai/config.json stops treating the key as unknown. Happy to open that PR if someone points me at the right place, otherwise it needs a maintainer with cloud-repo access.

Verification for this round, all agent-executed from packages/kilo-vscode/: bun run lint, bun run check-types, bun run check-types:webview, bun run knip, bun run format:check, bun esbuild.js (exit 0), and bun test ./tests/unit/i18n-keys.test.ts ./tests/unit/settings-io.test.ts (42 pass). The right-edge rendering itself still needs the CI baseline for the new story, plus human confirmation under an RTL locale — I have not verified the RTL fix visually, only by reasoning about the placement math.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant