Date: Fri, 10 Jul 2026 16:40:22 +0530
Subject: [PATCH 06/11] cleanup
---
.../session-ui/src/v2/components/session-review-v2.css | 7 ++++++-
packages/ui/src/components/tabs.css | 6 +++++-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/packages/session-ui/src/v2/components/session-review-v2.css b/packages/session-ui/src/v2/components/session-review-v2.css
index b116ebb43f24..9db2ba580c33 100644
--- a/packages/session-ui/src/v2/components/session-review-v2.css
+++ b/packages/session-ui/src/v2/components/session-review-v2.css
@@ -76,6 +76,11 @@
color: var(--text-strong, var(--v2-text-text-base));
}
+[data-component="session-review-v2-sidebar-root"]
+ [data-slot="session-review-v2-sidebar-title"]:not(:has([data-component="select-v2-root"])) {
+ margin-left: 8px;
+}
+
[data-component="session-review-v2-sidebar-root"]
[data-slot="session-review-v2-sidebar-title"]
[data-component="select-v2-root"] {
@@ -97,7 +102,7 @@
width: 100%;
max-width: 100%;
min-width: 0;
- margin-top: 2px;
+ margin-top: 3px;
}
[data-component="session-review-v2-sidebar-root"] [data-slot="session-review-v2-sidebar-tree"] {
diff --git a/packages/ui/src/components/tabs.css b/packages/ui/src/components/tabs.css
index 3da8cab2cacc..de859f5e7d28 100644
--- a/packages/ui/src/components/tabs.css
+++ b/packages/ui/src/components/tabs.css
@@ -743,7 +743,11 @@ body[data-new-layout] #terminal-panel [data-component="tabs"][data-variant="norm
background-color: var(--background-stronger, var(--v2-background-bg-base));
}
-#review-panel [data-component="tabs"] .session-review-v2-tabs-bar [data-slot="tabs-list"] {
+#review-panel [data-component="tabs"] .session-review-v2-tabs-bar [data-slot="tabs-list"],
+#review-panel
+ [data-component="tabs"][data-variant="normal"][data-orientation="horizontal"]
+ .session-review-v2-tabs-bar
+ [data-slot="tabs-list"] {
flex: 1 1 0;
min-width: 0;
width: auto;
From 2b4c3f3192a917abf36dbdacebac9b8ba32d5fd5 Mon Sep 17 00:00:00 2001
From: Aarav Sareen <96787824+arvsrn@users.noreply.github.com>
Date: Fri, 10 Jul 2026 16:45:21 +0530
Subject: [PATCH 07/11] use LineCommentV2 for unchanged files too
---
packages/app/src/pages/session/file-tabs.tsx | 54 +++++++++----------
.../line-comment-annotations-v2.tsx | 1 +
2 files changed, 25 insertions(+), 30 deletions(-)
diff --git a/packages/app/src/pages/session/file-tabs.tsx b/packages/app/src/pages/session/file-tabs.tsx
index dd51dd05852e..e58da5554cab 100644
--- a/packages/app/src/pages/session/file-tabs.tsx
+++ b/packages/app/src/pages/session/file-tabs.tsx
@@ -5,10 +5,10 @@ import { makeEventListener } from "@solid-primitives/event-listener"
import type { FileSearchHandle } from "@opencode-ai/session-ui/file"
import { useFileComponent } from "@opencode-ai/ui/context/file"
import { cloneSelectedLineRange, previewSelectedLines } from "@opencode-ai/session-ui/pierre/selection-bridge"
-import { createLineCommentController } from "@opencode-ai/session-ui/line-comment-annotations"
+import { createLineCommentControllerV2 } from "@opencode-ai/session-ui/v2/line-comment-annotations-v2"
import { sampledChecksum } from "@opencode-ai/core/util/encode"
-import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
-import { IconButton } from "@opencode-ai/ui/icon-button"
+import { LineCommentV2OverflowIcon } from "@opencode-ai/ui/v2/line-comment-v2"
+import { MenuV2 } from "@opencode-ai/ui/v2/menu-v2"
import { Tabs } from "@opencode-ai/ui/tabs"
import { ScrollView } from "@opencode-ai/ui/scroll-view"
import { showToast } from "@/utils/toast"
@@ -29,26 +29,17 @@ function FileCommentMenu(props: {
}) {
return (
event.stopPropagation()} onClick={(event) => event.stopPropagation()}>
-
-
-
-
-
- {props.editLabel}
-
-
- {props.deleteLabel}
-
-
-
-
+
+
+
+
+
+
+ {props.editLabel}
+ {props.deleteLabel}
+
+
+
)
}
@@ -299,13 +290,11 @@ export function SessionFileView(props: { tab: string }) {
const activeSelection = () => note.selected ?? selectedLines()
- const commentsUi = createLineCommentController({
+ const commentsUi = createLineCommentControllerV2({
comments: fileComments,
label: language.t("ui.lineComment.submit"),
draftKey: () => path() ?? props.tab,
- mention: {
- items: file.searchFilesAndDirectories,
- },
+ getSide: (range) => range.endSide ?? range.side ?? "additions",
state: {
opened: () => note.openedComment,
setOpened: (id) => setNote("openedComment", id),
@@ -316,9 +305,6 @@ export function SessionFileView(props: { tab: string }) {
syncSelected,
hoverSelected: syncSelected,
},
- getHoverSelectedRange: activeSelection,
- cancelDraftOnCommentToggle: true,
- clearSelectionOnSelectionEndNull: true,
onSubmit: ({ comment, selection }) => {
const p = path()
if (!p) return
@@ -426,8 +412,16 @@ export function SessionFileView(props: { tab: string }) {
commentsUi.onLineSelected(range)
}}
onLineSelectionEnd={(range: SelectedLineRange | null) => {
+ if (!range) {
+ commentsUi.note.select(null)
+ commentsUi.note.cancelDraft()
+ return
+ }
commentsUi.onLineSelectionEnd(range)
}}
+ onLineNumberSelectionEnd={(range: SelectedLineRange | null) => {
+ commentsUi.onLineNumberSelectionEnd(range)
+ }}
search={search}
class="select-text"
media={{
diff --git a/packages/session-ui/src/v2/components/line-comment-annotations-v2.tsx b/packages/session-ui/src/v2/components/line-comment-annotations-v2.tsx
index 4e8ed8673220..41fdca2afbbb 100644
--- a/packages/session-ui/src/v2/components/line-comment-annotations-v2.tsx
+++ b/packages/session-ui/src/v2/components/line-comment-annotations-v2.tsx
@@ -202,6 +202,7 @@ export function createLineCommentControllerV2
(props:
}
return {
+ note,
annotations,
renderAnnotation,
renderGutterUtility,
From cb17814be94570b0e74d6bf96b16b20719a32341 Mon Sep 17 00:00:00 2001
From: Aarav Sareen <96787824+arvsrn@users.noreply.github.com>
Date: Fri, 10 Jul 2026 17:03:45 +0530
Subject: [PATCH 08/11] restructure so file sidebar doesn't remount on file
change
---
.../file-browser-sidebar-tab-switch.spec.ts | 150 +++++++++++++++++
.../e2e/regression/review-open-file.spec.ts | 2 +-
.../src/components/session/open-in-app-v2.tsx | 9 +-
packages/app/src/pages/session/file-tabs.tsx | 3 +
.../src/pages/session/session-side-panel.tsx | 50 ++++--
.../session/v2/session-file-browser-tab.tsx | 147 +++++++++--------
.../line-comment-annotations-v2.tsx | 7 +
.../ui/src/v2/components/line-comment-v2.css | 53 ++++++
.../ui/src/v2/components/line-comment-v2.tsx | 154 +++++++++++++++++-
9 files changed, 482 insertions(+), 93 deletions(-)
create mode 100644 packages/app/e2e/regression/file-browser-sidebar-tab-switch.spec.ts
diff --git a/packages/app/e2e/regression/file-browser-sidebar-tab-switch.spec.ts b/packages/app/e2e/regression/file-browser-sidebar-tab-switch.spec.ts
new file mode 100644
index 000000000000..136232c2114b
--- /dev/null
+++ b/packages/app/e2e/regression/file-browser-sidebar-tab-switch.spec.ts
@@ -0,0 +1,150 @@
+import { base64Encode } from "@opencode-ai/core/util/encode"
+import { expect, test, type Page } from "@playwright/test"
+import { mockOpenCodeServer } from "../utils/mock-server"
+import { expectSessionTitle } from "../utils/waits"
+
+const directory = "C:/OpenCode/FileBrowserSidebar"
+const projectID = "proj_file_browser_sidebar"
+const sessionID = "ses_file_browser_sidebar"
+const title = "File browser sidebar"
+const server = `http://${process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1"}:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}`
+const files = Array.from({ length: 80 }, (_, index) => `file-${String(index).padStart(2, "0")}.ts`)
+// Marks the file-browser sidebar DOM node so a remount (fresh node) is detectable.
+const PROBE = "original"
+
+test.use({ viewport: { width: 1440, height: 900 } })
+
+// The file-browser sidebar must stay mounted across preview/pinned file-tab
+// switches. Remounting resets scroll and filter state.
+test("keeps the file-browser sidebar mounted when switching file tabs", async ({ page }) => {
+ await setup(page)
+
+ await page.goto(`/server/${base64Encode(server)}/session/${sessionID}`)
+ await expectSessionTitle(page, title)
+
+ const panel = page.locator("#review-panel")
+ await panel.getByRole("button", { name: "Open file" }).click()
+ await expect(panel.getByRole("tab", { name: "Open file" })).toHaveAttribute("data-selected", "")
+
+ const sidebar = panel.locator('[data-component="session-review-v2-sidebar-root"]')
+ await expect(sidebar).toBeVisible()
+ await expect(panel.getByRole("button", { name: "file-00.ts" })).toBeVisible()
+
+ await panel.getByRole("button", { name: "file-00.ts" }).click()
+ await expect(panel.getByRole("tab", { name: "file-00.ts" })).toHaveAttribute("data-selected", "")
+ await expect(panel.getByText("contents:file-00.ts", { exact: true })).toBeVisible()
+
+ const viewport = panel.locator('[data-slot="session-review-v2-sidebar-tree"] .scroll-view__viewport')
+ await viewport.hover()
+ await page.mouse.wheel(0, 100_000)
+ await expect
+ .poll(() => viewport.evaluate((element) => element.scrollHeight - element.clientHeight - element.scrollTop))
+ .toBeLessThanOrEqual(1)
+ const scrolled = await viewport.evaluate((element) => element.scrollTop)
+ expect(scrolled).toBeGreaterThan(0)
+ await writeProbe(page)
+
+ await panel.getByRole("button", { name: "file-79.ts" }).click()
+ await expect(panel.getByRole("tab", { name: "file-79.ts" })).toHaveAttribute("data-selected", "")
+ await expect(panel.getByText("contents:file-79.ts", { exact: true })).toBeVisible()
+ expect(await readProbe(page)).toBe(PROBE)
+ await expect.poll(() => viewport.evaluate((element) => element.scrollTop)).toBe(scrolled)
+
+ await panel.getByRole("button", { name: "file-78.ts" }).dblclick()
+ await expect(panel.getByRole("tab", { name: "file-78.ts" })).toHaveAttribute("data-selected", "")
+ await panel.getByRole("button", { name: "file-79.ts" }).click()
+ await expect(panel.getByRole("tab", { name: "file-79.ts" })).toHaveAttribute("data-selected", "")
+ await panel.getByRole("tab", { name: "file-78.ts" }).click()
+ await expect(panel.getByRole("tab", { name: "file-78.ts" })).toHaveAttribute("data-selected", "")
+ expect(await readProbe(page)).toBe(PROBE)
+ await expect.poll(() => viewport.evaluate((element) => element.scrollTop)).toBe(scrolled)
+})
+
+type Probed = HTMLElement & { __e2eProbe?: string }
+
+async function writeProbe(page: Page) {
+ await page.locator('#review-panel [data-component="session-review-v2-sidebar-root"]').evaluate((el, probe) => {
+ ;(el as Probed).__e2eProbe = probe
+ }, PROBE)
+}
+
+async function readProbe(page: Page) {
+ return page
+ .locator('#review-panel [data-component="session-review-v2-sidebar-root"]')
+ .evaluate((el) => (el as Probed).__e2eProbe)
+}
+
+async function setup(page: Page) {
+ await mockOpenCodeServer(page, {
+ directory,
+ project: {
+ id: projectID,
+ worktree: directory,
+ vcs: "git",
+ name: "file-browser-sidebar",
+ time: { created: 1700000000000, updated: 1700000000000 },
+ sandboxes: [],
+ },
+ provider: {
+ all: [
+ {
+ id: "opencode",
+ name: "OpenCode",
+ models: { test: { id: "test", name: "Test", limit: { context: 200_000 } } },
+ },
+ ],
+ connected: ["opencode"],
+ default: { providerID: "opencode", modelID: "test" },
+ },
+ sessions: [
+ {
+ id: sessionID,
+ slug: sessionID,
+ projectID,
+ directory,
+ title,
+ version: "dev",
+ time: { created: 1700000000000, updated: 1700000000000 },
+ },
+ ],
+ vcsDiff: [],
+ fileList: (path) => {
+ if (path) return []
+ return files.map((name) => ({
+ name,
+ path: name,
+ absolute: `${directory}/${name}`,
+ type: "file" as const,
+ ignored: false,
+ }))
+ },
+ fileContent: (path) => ({ type: "text", content: `contents:${path}` }),
+ pageMessages: () => ({ items: [] }),
+ })
+
+ await page.addInitScript(
+ ({ directory, server, sessionID }) => {
+ localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: true } }))
+ localStorage.setItem(
+ "opencode.global.dat:server",
+ JSON.stringify({
+ projects: { local: [{ worktree: directory, expanded: true }] },
+ lastProject: { local: directory },
+ }),
+ )
+ localStorage.setItem(
+ "opencode.global.dat:layout",
+ JSON.stringify({ review: { diffStyle: "split", panelOpened: true } }),
+ )
+ localStorage.setItem(
+ "opencode.global.dat:review-panel-v2",
+ JSON.stringify({ sidebarOpened: true, sidebarWidth: 240, expandMode: "collapse" }),
+ )
+ localStorage.setItem(
+ "opencode.window.browser.dat:tabs",
+ JSON.stringify([{ type: "session", server, sessionId: sessionID }]),
+ )
+ },
+ { directory, server, sessionID },
+ )
+}
diff --git a/packages/app/e2e/regression/review-open-file.spec.ts b/packages/app/e2e/regression/review-open-file.spec.ts
index 397c53f248e5..f7265919898d 100644
--- a/packages/app/e2e/regression/review-open-file.spec.ts
+++ b/packages/app/e2e/regression/review-open-file.spec.ts
@@ -99,7 +99,7 @@ test("opens and searches project files inline", async ({ page }) => {
await expect(sidebar).toBeVisible()
await contextButton.click()
await expect(panel.getByRole("tab", { name: "Context" })).toHaveAttribute("data-selected", "")
- await expect(sidebar).toHaveCount(0)
+ await expect(sidebar).toBeHidden()
await panel.getByRole("button", { name: "Open file" }).click()
const filter = panel.getByRole("combobox", { name: "Filter files" })
await expect(filter).toBeFocused()
diff --git a/packages/app/src/components/session/open-in-app-v2.tsx b/packages/app/src/components/session/open-in-app-v2.tsx
index 793b7952ba61..61ffb2331ed2 100644
--- a/packages/app/src/components/session/open-in-app-v2.tsx
+++ b/packages/app/src/components/session/open-in-app-v2.tsx
@@ -7,7 +7,7 @@ import { MenuV2 } from "@opencode-ai/ui/v2/menu-v2"
import { SplitButtonV2, SplitButtonV2Action, SplitButtonV2MenuTrigger } from "@opencode-ai/ui/v2/split-button-v2"
import { TooltipV2 } from "@opencode-ai/ui/v2/tooltip-v2"
import { useLanguage } from "@/context/language"
-import { OPEN_APPS, type OpenApp, useOpenInApp } from "@/components/session/open-in-app"
+import { type OpenApp, useOpenInApp } from "@/components/session/open-in-app"
export function OpenInAppV2(props: { directory: () => string }) {
const language = useLanguage()
@@ -25,9 +25,10 @@ export function OpenInAppV2(props: { directory: () => string }) {
class="flex items-center"
>
{
+ onPointerDown={(event) => event.stopPropagation()}
+ onClick={(event) => {
event.stopPropagation()
- if (event.button !== 0 || state.opening()) return
+ if (state.opening()) return
state.openDir(state.current().id)
}}
disabled={state.opening()}
@@ -60,7 +61,6 @@ export function OpenInAppV2(props: { directory: () => string }) {
{
- if (!OPEN_APPS.includes(value as OpenApp)) return
state.selectApp(value as OpenApp)
}}
>
@@ -70,6 +70,7 @@ export function OpenInAppV2(props: { directory: () => string }) {
value={option.id}
disabled={state.opening()}
onSelect={() => {
+ state.selectApp(option.id)
state.setMenu("open", false)
state.openDir(option.id)
}}
diff --git a/packages/app/src/pages/session/file-tabs.tsx b/packages/app/src/pages/session/file-tabs.tsx
index e58da5554cab..8ee42abee639 100644
--- a/packages/app/src/pages/session/file-tabs.tsx
+++ b/packages/app/src/pages/session/file-tabs.tsx
@@ -294,6 +294,9 @@ export function SessionFileView(props: { tab: string }) {
comments: fileComments,
label: language.t("ui.lineComment.submit"),
draftKey: () => path() ?? props.tab,
+ mention: {
+ items: file.searchFilesAndDirectories,
+ },
getSide: (range) => range.endSide ?? range.side ?? "additions",
state: {
opened: () => note.openedComment,
diff --git a/packages/app/src/pages/session/session-side-panel.tsx b/packages/app/src/pages/session/session-side-panel.tsx
index 4b3bdc26379d..0a042c80af87 100644
--- a/packages/app/src/pages/session/session-side-panel.tsx
+++ b/packages/app/src/pages/session/session-side-panel.tsx
@@ -22,6 +22,7 @@ import { SessionContextUsage } from "@/components/session-context-usage"
const reviewTabID = "session-side-panel-review-tab"
const reviewTabPanelID = "session-side-panel-review-tabpanel"
+const fileBrowserTabPanelID = "session-side-panel-file-browser-tabpanel"
import { SessionContextTab, SortableTab } from "@/components/session"
import { OpenInAppV2 } from "@/components/session/open-in-app-v2"
import { useCommand } from "@/context/command"
@@ -167,6 +168,7 @@ export function SessionSidePanel(props: {
fileBrowser: () => !!props.fileBrowserState,
})
const contextOpen = tabState.contextOpen
+ const openFileOpen = tabState.openFileOpen
const panelTabs = tabState.panelTabs
const openedTabs = tabState.openedTabs
const activeTab = tabState.activeTab
@@ -208,9 +210,22 @@ export function SessionSidePanel(props: {
}
const browserTab = createMemo(() => {
if (!props.fileBrowserState) return undefined
- if (activeTab() === SESSION_OPEN_FILE_TAB) return SESSION_OPEN_FILE_TAB
+ const active = activeTab()
+ if (active === SESSION_OPEN_FILE_TAB) return SESSION_OPEN_FILE_TAB
+ if (active && file.pathFromTab(active)) return active
return activeFileTab()
})
+ // Keep the file-browser shell mounted while any file tab exists. Kobalte briefly
+ // selects Review while the tab For replaces a preview trigger, which would
+ // otherwise dispose the sidebar and reset scroll.
+ const fileBrowserMounted = createMemo(() => {
+ if (!props.fileBrowserState) return false
+ return openedTabs().length > 0 || openFileOpen() || !!browserTab()
+ })
+ const fileBrowserVisible = createMemo(() => {
+ const active = activeTab()
+ return active !== "review" && active !== "context" && active !== "empty"
+ })
const browserKinds = createMemo(() => new Map([...kinds()].filter(([, kind]) => kind !== "mix")))
const openFileKeybind = createMemo(() => command.keybindParts("file.open"))
@@ -479,17 +494,28 @@ export function SessionSidePanel(props: {
-
- previewTab(file.tab(path))}
- onSelectPermanent={(path) => openTab(file.tab(path))}
- filterRef={(element) => (fileFilter = element)}
- />
+
+
+ previewTab(file.tab(path))}
+ onSelectPermanent={(path) => openTab(file.tab(path))}
+ filterRef={(element) => (fileFilter = element)}
+ />
+
diff --git a/packages/app/src/pages/session/v2/session-file-browser-tab.tsx b/packages/app/src/pages/session/v2/session-file-browser-tab.tsx
index 29272a4fa637..fc9f037232ed 100644
--- a/packages/app/src/pages/session/v2/session-file-browser-tab.tsx
+++ b/packages/app/src/pages/session/v2/session-file-browser-tab.tsx
@@ -1,6 +1,5 @@
import { createMemo, createSignal, createUniqueId, Show } from "solid-js"
import { createQuery } from "@tanstack/solid-query"
-import { Tabs } from "@opencode-ai/ui/tabs"
import { Icon } from "@opencode-ai/ui/icon"
import { SessionFilePanelV2, SessionFilePanelV2Empty } from "@opencode-ai/session-ui/v2/session-file-panel-v2"
import { SessionReviewV2Sidebar } from "@opencode-ai/session-ui/v2/session-review-v2"
@@ -89,94 +88,94 @@ export function SessionFileBrowserTab(props: {
})
}
+ // Keep the sidebar outside Kobalte Tabs.Content: a morphing content value
+ // unmounts the whole panel on every file-tab switch and resets sidebar scroll.
return (
-
- {title()}}
- filter={filter()}
- onFilterChange={setFilter}
- onFilterKeyDown={onFilterKeyDown}
- filterAutofocus={props.placeholder}
- filterRef={props.filterRef}
- filterControls={resultsID}
- filterActiveDescendant={highlighted() ? optionID(highlighted()!) : undefined}
- filterExpanded={query().length > 0 && files().length > 0}
- width={props.state.sidebarWidth()}
- onWidthChange={props.state.resizeSidebar}
+ {title()}}
+ filter={filter()}
+ onFilterChange={setFilter}
+ onFilterKeyDown={onFilterKeyDown}
+ filterAutofocus={props.placeholder}
+ filterRef={props.filterRef}
+ filterControls={resultsID}
+ filterActiveDescendant={highlighted() ? optionID(highlighted()!) : undefined}
+ filterExpanded={query().length > 0 && files().length > 0}
+ width={props.state.sidebarWidth()}
+ onWidthChange={props.state.resizeSidebar}
+ >
+ props.onSelect(node.path)}
+ onFileDoubleClick={(node) => props.onSelectPermanent(node.path)}
+ />
+ }
>
props.onSelect(node.path)}
- onFileDoubleClick={(node) => props.onSelectPermanent(node.path)}
- />
+
+ {language.t("common.loading")}
+ {language.t("common.loading.ellipsis")}
+
}
>
0}
fallback={
- {language.t("common.loading")}
- {language.t("common.loading.ellipsis")}
+ {language.t("palette.empty")}
}
>
- 0}
- fallback={
-
- {language.t("palette.empty")}
-
- }
- >
- {
- setExplicitHighlight(path)
- props.onSelect(path)
- }}
- onFileDoubleClick={props.onSelectPermanent}
- />
-
+ {
+ setExplicitHighlight(path)
+ props.onSelect(path)
+ }}
+ onFileDoubleClick={props.onSelectPermanent}
+ />
-
+
+
+ }
+ >
+
+
+
+
{language.t("command.file.open")}
+
{language.t("session.files.selectToOpen")}
+
+
}
>
-
-
-
-
{language.t("command.file.open")}
-
{language.t("session.files.selectToOpen")}
-
-
- }
- >
-
-
- {(tab) => }
-
-
-
-
-
+
+
+ {(tab) => }
+
+
+
+
)
}
diff --git a/packages/session-ui/src/v2/components/line-comment-annotations-v2.tsx b/packages/session-ui/src/v2/components/line-comment-annotations-v2.tsx
index 41fdca2afbbb..cd27a1ecc7b5 100644
--- a/packages/session-ui/src/v2/components/line-comment-annotations-v2.tsx
+++ b/packages/session-ui/src/v2/components/line-comment-annotations-v2.tsx
@@ -11,6 +11,7 @@ import {
import { useI18n } from "@opencode-ai/ui/context/i18n"
import { cloneSelectedLineRange, formatSelectedLineLabel } from "../../pierre/selection-bridge"
import { LineCommentEditorV2, LineCommentV2 } from "@opencode-ai/ui/v2/line-comment-v2"
+import type { LineCommentEditorV2Mention } from "@opencode-ai/ui/v2/line-comment-v2"
type LineCommentControllerV2Props = {
comments: Accessor
@@ -23,6 +24,7 @@ type LineCommentControllerV2Props = {
onDelete?: (comment: T) => void
renderCommentActions?: (comment: T, controls: { edit: VoidFunction; remove: VoidFunction }) => JSX.Element
editSubmitLabel?: string
+ mention?: LineCommentEditorV2Mention
}
type CommentProps = {
@@ -43,6 +45,7 @@ type DraftProps = {
onSubmit: (value: string) => void
cancelLabel?: string
submitLabel?: string
+ mention?: LineCommentEditorV2Mention
}
function lineCommentElementV2(view: Accessor) {
@@ -70,6 +73,7 @@ function lineCommentElementV2(view: Accessor) {
onSubmit={view().editor!.onSubmit}
cancelLabel={view().editor!.cancelLabel}
submitLabel={view().editor!.submitLabel}
+ mention={view().editor!.mention}
/>