From e70b4fa9b9879a6477033ffc7440e79e68eee60c Mon Sep 17 00:00:00 2001 From: kirillk Date: Tue, 7 Jul 2026 13:00:36 -0400 Subject: [PATCH] fix(jetbrains): refine session padding --- .changeset/jetbrains-code-block-inset.md | 5 +++++ .changeset/jetbrains-prompt-input-inset.md | 5 +++++ .../client/session/ui/prompt/PromptPanel.kt | 7 ++++++- .../client/session/ui/style/SessionUiStyle.kt | 11 ++++++++--- .../client/session/views/tool/ShellToolView.kt | 2 +- .../client/session/ui/PromptPanelTest.kt | 12 ++++++++++++ .../session/ui/SessionMessageListPanelTest.kt | 13 +++++++++++++ .../client/session/views/ShellToolViewTest.kt | 7 +++---- .../kilocode/client/ui/md/MdViewHybridTest.kt | 18 ++++++++++++------ 9 files changed, 65 insertions(+), 15 deletions(-) create mode 100644 .changeset/jetbrains-code-block-inset.md create mode 100644 .changeset/jetbrains-prompt-input-inset.md diff --git a/.changeset/jetbrains-code-block-inset.md b/.changeset/jetbrains-code-block-inset.md new file mode 100644 index 00000000000..3e843b59228 --- /dev/null +++ b/.changeset/jetbrains-code-block-inset.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Improve JetBrains session and code block padding alignment. diff --git a/.changeset/jetbrains-prompt-input-inset.md b/.changeset/jetbrains-prompt-input-inset.md new file mode 100644 index 00000000000..443bbd6866d --- /dev/null +++ b/.changeset/jetbrains-prompt-input-inset.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Balance JetBrains prompt input text padding. diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/ui/prompt/PromptPanel.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/ui/prompt/PromptPanel.kt index 6f826046e34..233e075c40b 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/ui/prompt/PromptPanel.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/ui/prompt/PromptPanel.kt @@ -172,7 +172,12 @@ class PromptPanel( style.applyTranscriptToEditor(ed) ed.setBorder(JBUI.Borders.empty()) ed.scrollPane.border = JBUI.Borders.empty() - ed.scrollPane.viewportBorder = JBUI.Borders.empty() + ed.scrollPane.viewportBorder = JBUI.Borders.empty( + 0, + JBUI.scale(SessionUiStyle.View.Prompt.SHELL_VERTICAL_PADDING), + 0, + JBUI.scale(SessionUiStyle.View.Prompt.SHELL_VERTICAL_PADDING), + ) ed.backgroundColor = style.editorScheme.defaultBackground ed.scrollPane.background = style.editorScheme.defaultBackground ed.scrollPane.viewport.background = style.editorScheme.defaultBackground diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/ui/style/SessionUiStyle.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/ui/style/SessionUiStyle.kt index f509c93a92d..afd24afe2ff 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/ui/style/SessionUiStyle.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/ui/style/SessionUiStyle.kt @@ -16,8 +16,13 @@ object SessionUiStyle { /** Geometry for the transcript list and its scroll behavior. */ object SessionLayout { const val GAP = 3 - val InnerInsets = Insets(UiStyle.Gap.md(), UiStyle.Gap.md(), UiStyle.Gap.sm(), UiStyle.Gap.sm()) const val TRANSCRIPT_SCROLLBAR_PADDING = 10 + val InnerInsets = Insets( + UiStyle.Gap.md(), + UiStyle.Gap.sm() + TRANSCRIPT_SCROLLBAR_PADDING, + UiStyle.Gap.sm(), + UiStyle.Gap.sm(), + ) const val USER_PROMPT_INDENT = 100 const val SCROLL_INCREMENT = 48 } @@ -144,12 +149,12 @@ object SessionUiStyle { const val MIN_ROWS = 1 const val BORDER_WIDTH = 1 const val VIEWPORT_TOP_PADDING = 6 - const val VIEWPORT_HORIZONTAL_PADDING = 8 + const val VIEWPORT_HORIZONTAL_PADDING = Layout.HORIZONTAL_PADDING const val VIEWPORT_BOTTOM_PADDING = 6 const val SCROLLBAR_HEIGHT = 12 const val WIDTH_PADDING = 16 - fun topPadding(): Int = VIEWPORT_TOP_PADDING + fun topPadding(): Int = VIEWPORT_TOP_PADDING + UiStyle.Gap.lg() } /** Permission session-view command preview limits. */ diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/views/tool/ShellToolView.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/views/tool/ShellToolView.kt index 9828d91a27b..a08b54a8a7c 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/views/tool/ShellToolView.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/views/tool/ShellToolView.kt @@ -305,7 +305,7 @@ class ShellBody( private fun styleShell() { val root = md.component as? JPanel ?: return root.components.filterIsInstance().forEach { - it.border = JBUI.Borders.emptyLeft(JBUI.scale(SessionUiStyle.View.Code.VIEWPORT_HORIZONTAL_PADDING)) + it.border = JBUI.Borders.emptyLeft(SessionUiStyle.View.Code.VIEWPORT_HORIZONTAL_PADDING) } } diff --git a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/ui/PromptPanelTest.kt b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/ui/PromptPanelTest.kt index d89bf04998a..fa1f42d9ea7 100644 --- a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/ui/PromptPanelTest.kt +++ b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/ui/PromptPanelTest.kt @@ -175,6 +175,18 @@ class PromptPanelTest : BasePlatformTestCase() { assertSame(editor, applied) } + fun `test prompt editor horizontal insets match top padding`() { + val panel = PromptPanel(project = project, onSend = { _, _ -> }, onAbort = {}, onEnhance = { _, _ -> }) + + realize(panel, 260, 400) + val editor = (panel.defaultFocusedComponent as EditorTextField).getEditor(false)!! + val ins = editor.scrollPane.viewportBorder.getBorderInsets(editor.scrollPane) + val pad = JBUI.scale(SessionUiStyle.View.Prompt.SHELL_VERTICAL_PADDING) + + assertEquals(pad, ins.left) + assertEquals(pad, ins.right) + } + fun `test prompt focus outline follows editor focus`() { val panel = PromptPanel(project = project, onSend = { _, _ -> }, onAbort = {}, onEnhance = { _, _ -> }) realize(panel, 260, 400) diff --git a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/ui/SessionMessageListPanelTest.kt b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/ui/SessionMessageListPanelTest.kt index 13b9740f41a..ceecd76baa1 100644 --- a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/ui/SessionMessageListPanelTest.kt +++ b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/ui/SessionMessageListPanelTest.kt @@ -19,6 +19,7 @@ import ai.kilocode.client.session.views.question.QuestionView import ai.kilocode.client.session.views.MessageToolbar import ai.kilocode.client.session.views.MessageView import ai.kilocode.client.session.views.TextView +import ai.kilocode.client.session.views.TurnView import ai.kilocode.client.session.views.base.PartView import ai.kilocode.client.session.views.tool.TaskToolView import ai.kilocode.client.session.views.tool.ToolView @@ -82,6 +83,18 @@ class SessionMessageListPanelTest : BasePlatformTestCase() { assertEquals("", panel.dump()) } + fun `test transcript content has symmetric side padding`() { + model.upsertMessage(msg("a1", "assistant")) + + panel.setSize(600, 400) + panel.doLayout() + val turn = panel.components.first { it is TurnView } + val left = turn.x + val right = panel.width - turn.x - turn.width + + assertEquals(right, left) + } + // ------ TurnAdded ------ fun `test user message creates turn and is findable by message id`() { diff --git a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/views/ShellToolViewTest.kt b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/views/ShellToolViewTest.kt index d903534f450..f9f05fd33d3 100644 --- a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/views/ShellToolViewTest.kt +++ b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/views/ShellToolViewTest.kt @@ -328,7 +328,7 @@ class ShellToolViewTest : BasePlatformTestCase() { assertEquals(2, panes.size) labels.forEach { val label = it.border?.getBorderInsets(it) - assertEquals(JBUI.scale(SessionUiStyle.View.Code.VIEWPORT_HORIZONTAL_PADDING), label?.left ?: 0) + assertEquals(JBUI.scale(SessionUiStyle.View.Layout.HORIZONTAL_PADDING), label?.left ?: 0) assertEquals(0, label?.right ?: 0) } panes.forEach { @@ -347,8 +347,7 @@ class ShellToolViewTest : BasePlatformTestCase() { val output = (1..30).joinToString("\n") { "line $it" } val view = track(ShellToolView(tool().also { it.output = output })) view.toggle() - val root = view.mdComponent()!! - val pane = root.components.filterIsInstance().single() + val pane = view.mdComponent()!!.components.filterIsInstance().single() val editor = view.codeEditors().single() val nested = editor.getEditor(true)!!.scrollPane val line = editor.getEditor(true)!!.lineHeight @@ -408,7 +407,7 @@ class ShellToolViewTest : BasePlatformTestCase() { val editor = field.getEditor(true)!! val lines = field.text.lines().size assertEquals( - SessionUiStyle.View.Code.VIEWPORT_TOP_PADDING, + SessionUiStyle.View.Code.topPadding(), pad.top, ) assertEquals(SessionUiStyle.View.Code.VIEWPORT_BOTTOM_PADDING, pad.bottom) diff --git a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/ui/md/MdViewHybridTest.kt b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/ui/md/MdViewHybridTest.kt index b80b7489614..e78d86f8782 100644 --- a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/ui/md/MdViewHybridTest.kt +++ b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/ui/md/MdViewHybridTest.kt @@ -122,25 +122,31 @@ class MdViewHybridTest : BasePlatformTestCase() { assertTrue(pane.preferredSize.height >= line * 3) } - fun `test fenced code block has symmetric content padding with horizontal scrollbar`() { + fun `test fenced code block balances content padding with horizontal scrollbar`() { view.set("```kotlin\n${"x".repeat(500)}\n```") val pane = scrolls().single() val pad = pane.viewportBorder.getBorderInsets(pane) - assertEquals(SessionUiStyle.View.Code.VIEWPORT_TOP_PADDING, pad.top) + assertEquals(SessionUiStyle.View.Code.topPadding(), pad.top) + assertEquals(SessionUiStyle.View.Layout.HORIZONTAL_PADDING, pad.left) assertEquals(SessionUiStyle.View.Code.VIEWPORT_BOTTOM_PADDING, pad.bottom) - assertEquals(pad.top, pad.bottom) + assertEquals(SessionUiStyle.View.Layout.HORIZONTAL_PADDING, pad.right) + assertTrue(pad.top > pad.bottom) + assertTrue(pad.top < pad.bottom + SessionUiStyle.View.Code.SCROLLBAR_HEIGHT) assertTrue(pane.horizontalScrollBar.preferredSize.height > 0) } - fun `test short code block keeps symmetric content padding`() { + fun `test short code block keeps balanced content padding`() { view.set("```text\n[ALICE, ANNA]\n```") val pane = scrolls().single() val pad = pane.viewportBorder.getBorderInsets(pane) - assertEquals(SessionUiStyle.View.Code.VIEWPORT_TOP_PADDING, pad.top) + assertEquals(SessionUiStyle.View.Code.topPadding(), pad.top) + assertEquals(SessionUiStyle.View.Layout.HORIZONTAL_PADDING, pad.left) assertEquals(SessionUiStyle.View.Code.VIEWPORT_BOTTOM_PADDING, pad.bottom) - assertEquals(pad.top, pad.bottom) + assertEquals(SessionUiStyle.View.Layout.HORIZONTAL_PADDING, pad.right) + assertTrue(pad.top > pad.bottom) + assertTrue(pad.top < pad.bottom + SessionUiStyle.View.Code.SCROLLBAR_HEIGHT) } fun `test fenced code block height is not capped`() {