ux: Toolbar cleanup and settings consolidation (#9710)

Co-authored-by: Roo Code <roomote@roocode.com>
This commit is contained in:
Bruno Bergher 2025-12-01 14:43:15 +00:00 • committed by GitHub
parent f26d5a479f
commit 49aad8576e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
50 changed files with 1093 additions and 1168 deletions

View file

@ -15,8 +15,6 @@ suite("Roo Code Extension", function () {
"SidebarProvider.removeView",
"activationCompleted",
"plusButtonClicked",
"mcpButtonClicked",
"promptsButtonClicked",
"popoutButtonClicked",
"openInNewTab",
"settingsButtonClicked",

View file

@ -30,8 +30,6 @@ export const commandIds = [
"activationCompleted",
"plusButtonClicked",
"promptsButtonClicked",
"mcpButtonClicked",
"historyButtonClicked",
"marketplaceButtonClicked",
"popoutButtonClicked",

View file

@ -101,28 +101,6 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
// This ensures the focus happens after the view has switched
await visibleProvider.postMessageToWebview({ type: "action", action: "focusInput" })
},
mcpButtonClicked: () => {
const visibleProvider = getVisibleProviderOrLog(outputChannel)
if (!visibleProvider) {
return
}
TelemetryService.instance.captureTitleButtonClicked("mcp")
visibleProvider.postMessageToWebview({ type: "action", action: "mcpButtonClicked" })
},
promptsButtonClicked: () => {
const visibleProvider = getVisibleProviderOrLog(outputChannel)
if (!visibleProvider) {
return
}
TelemetryService.instance.captureTitleButtonClicked("prompts")
visibleProvider.postMessageToWebview({ type: "action", action: "promptsButtonClicked" })
},
popoutButtonClicked: () => {
TelemetryService.instance.captureTitleButtonClicked("popout")

View file

@ -75,16 +75,6 @@
"title": "%command.newTask.title%",
"icon": "$(edit)"
},
{
"command": "roo-cline.promptsButtonClicked",
"title": "%command.prompts.title%",
"icon": "$(organization)"
},
{
"command": "roo-cline.mcpButtonClicked",
"title": "%command.mcpServers.title%",
"icon": "$(server)"
},
{
"command": "roo-cline.historyButtonClicked",
"title": "%command.history.title%",
@ -229,17 +219,17 @@
"when": "view == roo-cline.SidebarProvider"
},
{
"command": "roo-cline.marketplaceButtonClicked",
"command": "roo-cline.settingsButtonClicked",
"group": "navigation@2",
"when": "view == roo-cline.SidebarProvider"
},
{
"command": "roo-cline.settingsButtonClicked",
"command": "roo-cline.cloudButtonClicked",
"group": "navigation@3",
"when": "view == roo-cline.SidebarProvider"
},
{
"command": "roo-cline.cloudButtonClicked",
"command": "roo-cline.marketplaceButtonClicked",
"group": "navigation@4",
"when": "view == roo-cline.SidebarProvider"
},
@ -248,19 +238,9 @@
"group": "overflow@1",
"when": "view == roo-cline.SidebarProvider"
},
{
"command": "roo-cline.promptsButtonClicked",
"group": "overflow@2",
"when": "view == roo-cline.SidebarProvider"
},
{
"command": "roo-cline.mcpButtonClicked",
"group": "overflow@3",
"when": "view == roo-cline.SidebarProvider"
},
{
"command": "roo-cline.popoutButtonClicked",
"group": "overflow@4",
"group": "overflow@2",
"when": "view == roo-cline.SidebarProvider"
}
],
@ -271,17 +251,17 @@
"when": "activeWebviewPanelId == roo-cline.TabPanelProvider"
},
{
"command": "roo-cline.marketplaceButtonClicked",
"command": "roo-cline.settingsButtonClicked",
"group": "navigation@2",
"when": "activeWebviewPanelId == roo-cline.TabPanelProvider"
},
{
"command": "roo-cline.settingsButtonClicked",
"command": "roo-cline.cloudButtonClicked",
"group": "navigation@3",
"when": "activeWebviewPanelId == roo-cline.TabPanelProvider"
},
{
"command": "roo-cline.cloudButtonClicked",
"command": "roo-cline.marketplaceButtonClicked",
"group": "navigation@4",
"when": "activeWebviewPanelId == roo-cline.TabPanelProvider"
},
@ -290,19 +270,9 @@
"group": "overflow@1",
"when": "activeWebviewPanelId == roo-cline.TabPanelProvider"
},
{
"command": "roo-cline.promptsButtonClicked",
"group": "overflow@2",
"when": "activeWebviewPanelId == roo-cline.TabPanelProvider"
},
{
"command": "roo-cline.mcpButtonClicked",
"group": "overflow@3",
"when": "activeWebviewPanelId == roo-cline.TabPanelProvider"
},
{
"command": "roo-cline.popoutButtonClicked",
"group": "overflow@4",
"group": "overflow@2",
"when": "activeWebviewPanelId == roo-cline.TabPanelProvider"
}
]

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "Servidors MCP",
"command.prompts.title": "Modes",
"command.history.title": "Historial",
"command.history.title": "Historial de Tasques",
"command.marketplace.title": "Mercat",
"command.openInEditor.title": "Obrir a l'Editor",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "MCP Server",
"command.prompts.title": "Modi",
"command.history.title": "Verlauf",
"command.history.title": "Aufgabenverlauf",
"command.marketplace.title": "Marktplatz",
"command.openInEditor.title": "Im Editor Öffnen",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "Servidores MCP",
"command.prompts.title": "Modos",
"command.history.title": "Historial",
"command.history.title": "Historial de Tareas",
"command.marketplace.title": "Mercado",
"command.openInEditor.title": "Abrir en Editor",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "Serveurs MCP",
"command.prompts.title": "Modes",
"command.history.title": "Historique",
"command.history.title": "Historique des Tâches",
"command.marketplace.title": "Marché",
"command.openInEditor.title": "Ouvrir dans l'Éditeur",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "एमसीपी सर्वर",
"command.prompts.title": "मोड्स",
"command.history.title": "इतिहास",
"command.history.title": "कार्य इतिहास",
"command.marketplace.title": "मार्केटप्लेस",
"command.openInEditor.title": "एडिटर में खोलें",
"command.cloud.title": "Cloud",

View file

@ -6,9 +6,7 @@
"views.activitybar.title": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.newTask.title": "Tugas Baru",
"command.mcpServers.title": "Server MCP",
"command.prompts.title": "Mode",
"command.history.title": "Riwayat",
"command.history.title": "Riwayat Tugas",
"command.marketplace.title": "Marketplace",
"command.openInEditor.title": "Buka di Editor",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "Server MCP",
"command.prompts.title": "Modi",
"command.history.title": "Cronologia",
"command.history.title": "Cronologia Attività",
"command.marketplace.title": "Marketplace",
"command.openInEditor.title": "Apri nell'Editor",
"command.cloud.title": "Cloud",

View file

@ -6,9 +6,7 @@
"views.activitybar.title": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.newTask.title": "新しいタスク",
"command.mcpServers.title": "MCPサーバー",
"command.prompts.title": "モード",
"command.history.title": "履歴",
"command.history.title": "タスク履歴",
"command.marketplace.title": "マーケットプレイス",
"command.openInEditor.title": "エディタで開く",
"command.cloud.title": "Cloud",

View file

@ -6,9 +6,7 @@
"views.activitybar.title": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.newTask.title": "New Task",
"command.mcpServers.title": "MCP Servers",
"command.prompts.title": "Modes",
"command.history.title": "History",
"command.history.title": "Task History",
"command.marketplace.title": "Marketplace",
"command.openInEditor.title": "Open in Editor",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "MCP 서버",
"command.prompts.title": "모드",
"command.history.title": "기록",
"command.history.title": "작업 기록",
"command.marketplace.title": "마켓플레이스",
"command.openInEditor.title": "에디터에서 열기",
"command.cloud.title": "Cloud",

View file

@ -6,9 +6,7 @@
"views.activitybar.title": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.newTask.title": "Nieuwe Taak",
"command.mcpServers.title": "MCP Servers",
"command.prompts.title": "Modi",
"command.history.title": "Geschiedenis",
"command.history.title": "Taakgeschiedenis",
"command.marketplace.title": "Marktplaats",
"command.openInEditor.title": "Openen in Editor",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "Serwery MCP",
"command.prompts.title": "Tryby",
"command.history.title": "Historia",
"command.history.title": "Historia Zadań",
"command.marketplace.title": "Marketplace",
"command.openInEditor.title": "Otwórz w Edytorze",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "Servidores MCP",
"command.prompts.title": "Modos",
"command.history.title": "Histórico",
"command.history.title": "Histórico de Tarefas",
"command.marketplace.title": "Marketplace",
"command.openInEditor.title": "Abrir no Editor",
"command.cloud.title": "Cloud",

View file

@ -6,9 +6,7 @@
"views.activitybar.title": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.newTask.title": "Новая задача",
"command.mcpServers.title": "MCP серверы",
"command.prompts.title": "Режимы",
"command.history.title": "История",
"command.history.title": "История задач",
"command.marketplace.title": "Маркетплейс",
"command.openInEditor.title": "Открыть в редакторе",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "MCP Sunucuları",
"command.prompts.title": "Modlar",
"command.history.title": "Geçmiş",
"command.history.title": "Görev Geçmişi",
"command.marketplace.title": "Marketplace",
"command.openInEditor.title": "Düzenleyicide Aç",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "Máy Chủ MCP",
"command.prompts.title": "Chế Độ",
"command.history.title": "Lịch Sử",
"command.history.title": "Lịch Sử Tác Vụ",
"command.marketplace.title": "Marketplace",
"command.openInEditor.title": "Mở trong Trình Soạn Thảo",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "MCP 服务器",
"command.prompts.title": "模式",
"command.history.title": "历史记录",
"command.history.title": "任务历史记录",
"command.marketplace.title": "应用市场",
"command.openInEditor.title": "在编辑器中打开",
"command.cloud.title": "Cloud",

View file

@ -19,9 +19,7 @@
"views.contextMenu.label": "Roo Code",
"views.terminalMenu.label": "Roo Code",
"views.sidebar.name": "Roo Code",
"command.mcpServers.title": "MCP 伺服器",
"command.prompts.title": "模式",
"command.history.title": "歷史記錄",
"command.history.title": "工作歷史記錄",
"command.marketplace.title": "應用市場",
"command.openInEditor.title": "在編輯器中開啟",
"command.cloud.title": "Cloud",

View file

@ -140,10 +140,8 @@ export interface ExtensionMessage {
}
action?:
| "chatButtonClicked"
| "mcpButtonClicked"
| "settingsButtonClicked"
| "historyButtonClicked"
| "promptsButtonClicked"
| "marketplaceButtonClicked"
| "cloudButtonClicked"
| "didBecomeVisible"

View file

@ -17,9 +17,7 @@ import HistoryView from "./components/history/HistoryView"
import SettingsView, { SettingsViewRef } from "./components/settings/SettingsView"
import WelcomeView from "./components/welcome/WelcomeView"
import WelcomeViewProvider from "./components/welcome/WelcomeViewProvider"
import McpView from "./components/mcp/McpView"
import { MarketplaceView } from "./components/marketplace/MarketplaceView"
import ModesView from "./components/modes/ModesView"
import { HumanRelayDialog } from "./components/human-relay/HumanRelayDialog"
import { CheckpointRestoreDialog } from "./components/chat/CheckpointRestoreDialog"
import { DeleteMessageDialog, EditMessageDialog } from "./components/chat/MessageModificationConfirmationDialog"
@ -29,7 +27,7 @@ import { useAddNonInteractiveClickListener } from "./components/ui/hooks/useNonI
import { TooltipProvider } from "./components/ui/tooltip"
import { STANDARD_TOOLTIP_DELAY } from "./components/ui/standard-tooltip"
type Tab = "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "cloud"
type Tab = "settings" | "history" | "chat" | "marketplace" | "cloud"
interface HumanRelayDialogState {
isOpen: boolean
@ -60,8 +58,6 @@ const MemoizedHumanRelayDialog = React.memo(HumanRelayDialog)
const tabsByMessageAction: Partial<Record<NonNullable<ExtensionMessage["action"]>, Tab>> = {
chatButtonClicked: "chat",
settingsButtonClicked: "settings",
promptsButtonClicked: "modes",
mcpButtonClicked: "mcp",
historyButtonClicked: "history",
marketplaceButtonClicked: "marketplace",
cloudButtonClicked: "cloud",
@ -271,8 +267,6 @@ const App = () => {
)
) : (
<>
{tab === "modes" && <ModesView onDone={() => switchTab("chat")} />}
{tab === "mcp" && <McpView onDone={() => switchTab("chat")} />}
{tab === "history" && <HistoryView onDone={() => switchTab("chat")} />}
{tab === "settings" && (
<SettingsView ref={settingsRef} onDone={() => setTab("chat")} targetSection={currentSection} />

View file

@ -69,23 +69,15 @@ vi.mock("@src/components/history/HistoryView", () => ({
vi.mock("@src/components/mcp/McpView", () => ({
__esModule: true,
default: function McpView({ onDone }: { onDone: () => void }) {
return (
<div data-testid="mcp-view" onClick={onDone}>
MCP View
</div>
)
default: function McpView() {
return <div data-testid="mcp-view">MCP View</div>
},
}))
vi.mock("@src/components/modes/ModesView", () => ({
__esModule: true,
default: function ModesView({ onDone }: { onDone: () => void }) {
return (
<div data-testid="prompts-view" onClick={onDone}>
Modes View
</div>
)
default: function ModesView() {
return <div data-testid="prompts-view">Modes View</div>
},
}))
@ -253,34 +245,6 @@ describe("App", () => {
expect(chatView.getAttribute("data-hidden")).toBe("true")
})
it("switches to MCP view when receiving mcpButtonClicked action", async () => {
render(<AppWithProviders />)
act(() => {
triggerMessage("mcpButtonClicked")
})
const mcpView = await screen.findByTestId("mcp-view")
expect(mcpView).toBeInTheDocument()
const chatView = screen.getByTestId("chat-view")
expect(chatView.getAttribute("data-hidden")).toBe("true")
})
it("switches to prompts view when receiving promptsButtonClicked action", async () => {
render(<AppWithProviders />)
act(() => {
triggerMessage("promptsButtonClicked")
})
const promptsView = await screen.findByTestId("prompts-view")
expect(promptsView).toBeInTheDocument()
const chatView = screen.getByTestId("chat-view")
expect(chatView.getAttribute("data-hidden")).toBe("true")
})
it("returns to chat view when clicking done in settings view", async () => {
render(<AppWithProviders />)
@ -299,7 +263,7 @@ describe("App", () => {
expect(screen.queryByTestId("settings-view")).not.toBeInTheDocument()
})
it.each(["history", "mcp", "prompts"])("returns to chat view when clicking done in %s view", async (view) => {
it.each(["history"])("returns to chat view when clicking done in %s view", async (view) => {
render(<AppWithProviders />)
act(() => {

View file

@ -306,7 +306,11 @@ export const ModeSelector = ({
iconClass="codicon-settings-gear"
title={t("chat:modeSelector.settings")}
onClick={() => {
vscode.postMessage({ type: "switchTab", tab: "modes" })
vscode.postMessage({
type: "switchTab",
tab: "settings",
values: { section: "modes" },
})
setOpen(false)
}}
/>

View file

@ -195,25 +195,14 @@ export const MarketplaceInstallModal: React.FC<MarketplaceInstallModalProps> = (
}
const handlePostInstallAction = (tab: "mcp" | "modes") => {
if (tab === "mcp") {
// Navigate to MCP tab
window.postMessage(
{
type: "action",
action: "mcpButtonClicked",
},
"*",
)
} else {
// Navigate to Modes tab
window.postMessage(
{
type: "action",
action: "promptsButtonClicked",
},
"*",
)
}
const section = tab === "mcp" ? "mcp" : "modes"
vscode.postMessage({
type: "switchTab",
tab: "settings",
values: { section },
})
// Close the modal
onClose()
}

View file

@ -7,6 +7,7 @@ import {
VSCodePanelTab,
VSCodePanelView,
} from "@vscode/webview-ui-toolkit/react"
import { Webhook } from "lucide-react"
import { McpServer } from "@roo/mcp"
@ -25,19 +26,17 @@ import {
StandardTooltip,
} from "@src/components/ui"
import { buildDocLink } from "@src/utils/docLinks"
import { Section } from "@src/components/settings/Section"
import { SectionHeader } from "@src/components/settings/SectionHeader"
import { Tab, TabContent, TabHeader } from "../common/Tab"
import { TabContent } from "../common/Tab"
import McpToolRow from "./McpToolRow"
import McpResourceRow from "./McpResourceRow"
import McpEnabledToggle from "./McpEnabledToggle"
import { McpErrorRow } from "./McpErrorRow"
type McpViewProps = {
onDone: () => void
}
const McpView = ({ onDone }: McpViewProps) => {
const McpView = () => {
const {
mcpServers: servers,
alwaysAllowMcp,
@ -49,150 +48,156 @@ const McpView = ({ onDone }: McpViewProps) => {
const { t } = useAppTranslation()
return (
<Tab>
<TabHeader className="flex justify-between items-center">
<h3 className="text-vscode-foreground m-0">{t("mcp:title")}</h3>
<Button onClick={onDone}>{t("mcp:done")}</Button>
</TabHeader>
<TabContent>
<div
style={{
color: "var(--vscode-foreground)",
fontSize: "13px",
marginBottom: "10px",
marginTop: "5px",
}}>
<Trans i18nKey="mcp:description">
<VSCodeLink
href={buildDocLink("features/mcp/using-mcp-in-roo", "mcp_settings")}
style={{ display: "inline" }}>
Learn More
</VSCodeLink>
</Trans>
<div>
<SectionHeader>
<div className="flex items-center gap-2">
<Webhook className="w-4" />
<div>{t("mcp:title")}</div>
</div>
</SectionHeader>
<McpEnabledToggle />
<Section>
<TabContent>
<div
style={{
color: "var(--vscode-foreground)",
fontSize: "13px",
marginBottom: "10px",
marginTop: "5px",
}}>
<Trans i18nKey="mcp:description">
<VSCodeLink
href={buildDocLink("features/mcp/using-mcp-in-roo", "mcp_settings")}
style={{ display: "inline" }}>
Learn More
</VSCodeLink>
</Trans>
</div>
{mcpEnabled && (
<>
<div style={{ marginBottom: 15 }}>
<VSCodeCheckbox
checked={enableMcpServerCreation}
onChange={(e: any) => {
setEnableMcpServerCreation(e.target.checked)
vscode.postMessage({ type: "enableMcpServerCreation", bool: e.target.checked })
}}>
<span style={{ fontWeight: "500" }}>{t("mcp:enableServerCreation.title")}</span>
</VSCodeCheckbox>
<McpEnabledToggle />
{mcpEnabled && (
<>
<div style={{ marginBottom: 15 }}>
<VSCodeCheckbox
checked={enableMcpServerCreation}
onChange={(e: any) => {
setEnableMcpServerCreation(e.target.checked)
vscode.postMessage({ type: "enableMcpServerCreation", bool: e.target.checked })
}}>
<span style={{ fontWeight: "500" }}>{t("mcp:enableServerCreation.title")}</span>
</VSCodeCheckbox>
<div
style={{
fontSize: "12px",
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
<Trans i18nKey="mcp:enableServerCreation.description">
<VSCodeLink
href={buildDocLink(
"features/mcp/using-mcp-in-roo#how-to-use-roo-to-create-an-mcp-server",
"mcp_server_creation",
)}
style={{ display: "inline" }}>
Learn about server creation
</VSCodeLink>
<strong>new</strong>
</Trans>
<p style={{ marginTop: "8px" }}>{t("mcp:enableServerCreation.hint")}</p>
</div>
</div>
{/* Server List */}
{servers.length > 0 && (
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>
{servers.map((server) => (
<ServerRow
key={`${server.name}-${server.source || "global"}`}
server={server}
alwaysAllowMcp={alwaysAllowMcp}
/>
))}
</div>
)}
{/* Edit Settings Buttons */}
<div
style={{
fontSize: "12px",
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
marginTop: "10px",
width: "100%",
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
gap: "10px",
}}>
<Trans i18nKey="mcp:enableServerCreation.description">
<VSCodeLink
href={buildDocLink(
"features/mcp/using-mcp-in-roo#how-to-use-roo-to-create-an-mcp-server",
"mcp_server_creation",
)}
style={{ display: "inline" }}>
Learn about server creation
</VSCodeLink>
<strong>new</strong>
</Trans>
<p style={{ marginTop: "8px" }}>{t("mcp:enableServerCreation.hint")}</p>
</div>
</div>
{/* Server List */}
{servers.length > 0 && (
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>
{servers.map((server) => (
<ServerRow
key={`${server.name}-${server.source || "global"}`}
server={server}
alwaysAllowMcp={alwaysAllowMcp}
/>
))}
</div>
)}
{/* Edit Settings Buttons */}
<div
style={{
marginTop: "10px",
width: "100%",
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
gap: "10px",
}}>
<Button
variant="secondary"
style={{ width: "100%" }}
onClick={() => {
vscode.postMessage({ type: "openMcpSettings" })
}}>
<span className="codicon codicon-edit" style={{ marginRight: "6px" }}></span>
{t("mcp:editGlobalMCP")}
</Button>
<Button
variant="secondary"
style={{ width: "100%" }}
onClick={() => {
vscode.postMessage({ type: "openProjectMcpSettings" })
}}>
<span className="codicon codicon-edit" style={{ marginRight: "6px" }}></span>
{t("mcp:editProjectMCP")}
</Button>
<Button
variant="secondary"
style={{ width: "100%" }}
onClick={() => {
vscode.postMessage({ type: "refreshAllMcpServers" })
}}>
<span className="codicon codicon-refresh" style={{ marginRight: "6px" }}></span>
{t("mcp:refreshMCP")}
</Button>
<StandardTooltip content={t("mcp:marketplace")}>
<Button
variant="secondary"
style={{ width: "100%" }}
onClick={() => {
window.postMessage(
{
type: "action",
action: "marketplaceButtonClicked",
values: { marketplaceTab: "mcp" },
},
"*",
)
vscode.postMessage({ type: "openMcpSettings" })
}}>
<span className="codicon codicon-extensions" style={{ marginRight: "6px" }}></span>
{t("mcp:marketplace")}
<span className="codicon codicon-edit" style={{ marginRight: "6px" }}></span>
{t("mcp:editGlobalMCP")}
</Button>
</StandardTooltip>
</div>
<div
style={{
marginTop: "15px",
fontSize: "12px",
color: "var(--vscode-descriptionForeground)",
}}>
<VSCodeLink
href={buildDocLink(
"features/mcp/using-mcp-in-roo#editing-mcp-settings-files",
"mcp_edit_settings",
)}
style={{ display: "inline" }}>
{t("mcp:learnMoreEditingSettings")}
</VSCodeLink>
</div>
</>
)}
</TabContent>
</Tab>
<Button
variant="secondary"
style={{ width: "100%" }}
onClick={() => {
vscode.postMessage({ type: "openProjectMcpSettings" })
}}>
<span className="codicon codicon-edit" style={{ marginRight: "6px" }}></span>
{t("mcp:editProjectMCP")}
</Button>
<Button
variant="secondary"
style={{ width: "100%" }}
onClick={() => {
vscode.postMessage({ type: "refreshAllMcpServers" })
}}>
<span className="codicon codicon-refresh" style={{ marginRight: "6px" }}></span>
{t("mcp:refreshMCP")}
</Button>
<StandardTooltip content={t("mcp:marketplace")}>
<Button
variant="secondary"
style={{ width: "100%" }}
onClick={() => {
window.postMessage(
{
type: "action",
action: "marketplaceButtonClicked",
values: { marketplaceTab: "mcp" },
},
"*",
)
}}>
<span
className="codicon codicon-extensions"
style={{ marginRight: "6px" }}></span>
{t("mcp:marketplace")}
</Button>
</StandardTooltip>
</div>
<div
style={{
marginTop: "15px",
fontSize: "12px",
color: "var(--vscode-descriptionForeground)",
}}>
<VSCodeLink
href={buildDocLink(
"features/mcp/using-mcp-in-roo#editing-mcp-settings-files",
"mcp_edit_settings",
)}
style={{ display: "inline" }}>
{t("mcp:learnMoreEditingSettings")}
</VSCodeLink>
</div>
</>
)}
</TabContent>
</Section>
</div>
)
}

File diff suppressed because it is too large Load diff

View file

@ -30,10 +30,9 @@ const mockExtensionState = {
}
const renderModesView = (props = {}) => {
const mockOnDone = vitest.fn()
return render(
<ExtensionStateContext.Provider value={{ ...mockExtensionState, ...props } as any}>
<ModesView onDone={mockOnDone} />
<ModesView />
</ExtensionStateContext.Provider>,
)
}

View file

@ -29,10 +29,9 @@ const mockExtensionState = {
}
const renderPromptsView = (props = {}) => {
const mockOnDone = vitest.fn()
return render(
<ExtensionStateContext.Provider value={{ ...mockExtensionState, ...props } as any}>
<ModesView onDone={mockOnDone} />
<ModesView />
</ExtensionStateContext.Provider>,
)
}
@ -128,7 +127,7 @@ describe("PromptsView", () => {
const { unmount } = render(
<ExtensionStateContext.Provider
value={{ ...mockExtensionState, mode: "code", customModes: [customMode] } as any}>
<ModesView onDone={vitest.fn()} />
<ModesView />
</ExtensionStateContext.Provider>,
)
@ -154,7 +153,7 @@ describe("PromptsView", () => {
render(
<ExtensionStateContext.Provider
value={{ ...mockExtensionState, mode: "custom-mode", customModes: [customMode] } as any}>
<ModesView onDone={vitest.fn()} />
<ModesView />
</ExtensionStateContext.Provider>,
)
@ -175,7 +174,7 @@ describe("PromptsView", () => {
const { unmount } = render(
<ExtensionStateContext.Provider
value={{ ...mockExtensionState, mode: "code", customModes: [customMode] } as any}>
<ModesView onDone={vitest.fn()} />
<ModesView />
</ExtensionStateContext.Provider>,
)
@ -190,7 +189,7 @@ describe("PromptsView", () => {
render(
<ExtensionStateContext.Provider
value={{ ...mockExtensionState, mode: "custom-mode", customModes: [customMode] } as any}>
<ModesView onDone={vitest.fn()} />
<ModesView />
</ExtensionStateContext.Provider>,
)

View file

@ -25,6 +25,9 @@ import {
LucideIcon,
SquareSlash,
Glasses,
Plug,
Server,
Users2,
} from "lucide-react"
import {
@ -74,6 +77,8 @@ import { Section } from "./Section"
import PromptsSettings from "./PromptsSettings"
import { SlashCommandsSettings } from "./SlashCommandsSettings"
import { UISettings } from "./UISettings"
import ModesView from "../modes/ModesView"
import McpView from "../mcp/McpView"
export const settingsTabsContainer = "flex flex-1 overflow-hidden [&.narrow_.tab-label]:hidden"
export const settingsTabList =
@ -95,6 +100,8 @@ const sectionNames = [
"notifications",
"contextManagement",
"terminal",
"modes",
"mcp",
"prompts",
"ui",
"experimental",
@ -501,7 +508,9 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
const sections: { id: SectionName; icon: LucideIcon }[] = useMemo(
() => [
{ id: "providers", icon: Webhook },
{ id: "providers", icon: Plug },
{ id: "modes", icon: Users2 },
{ id: "mcp", icon: Server },
{ id: "autoApprove", icon: CheckCheck },
{ id: "slashCommands", icon: SquareSlash },
{ id: "browser", icon: SquareMousePointer },
@ -614,7 +623,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
isSelected // Use manual isSelected for styling
? `${settingsTabTrigger} ${settingsTabTriggerActive}`
: settingsTabTrigger,
"focus:ring-0", // Remove the focus ring styling
"cursor-pointer focus:ring-0", // Remove the focus ring styling
)}
data-testid={`tab-${id}`}
data-compact={isCompactMode}>
@ -802,6 +811,12 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
/>
)}
{/* Modes Section */}
{activeTab === "modes" && <ModesView />}
{/* MCP Section */}
{activeTab === "mcp" && <McpView />}
{/* Prompts Section */}
{activeTab === "prompts" && (
<PromptsSettings

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Proveïdors",
"modes": "Modes",
"mcp": "Servidors MCP",
"autoApprove": "Auto-aprovació",
"browser": "Accés a l'ordinador",
"checkpoints": "Punts de control",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Anbieter",
"modes": "Modi",
"mcp": "MCP-Server",
"autoApprove": "Auto-Genehmigung",
"browser": "Computerzugriff",
"checkpoints": "Kontrollpunkte",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Providers",
"modes": "Modes",
"mcp": "MCP Servers",
"autoApprove": "Auto-Approve",
"browser": "Browser",
"checkpoints": "Checkpoints",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Proveedores",
"modes": "Modos",
"mcp": "Servidores MCP",
"autoApprove": "Auto-aprobación",
"browser": "Acceso al ordenador",
"checkpoints": "Puntos de control",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Fournisseurs",
"modes": "Modes",
"mcp": "Serveurs MCP",
"autoApprove": "Auto-approbation",
"browser": "Accès ordinateur",
"checkpoints": "Points de contrôle",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "प्रदाता",
"modes": "मोड",
"mcp": "एमसीपी सर्वर",
"autoApprove": "अनुमोदन",
"browser": "ब्राउज़र",
"checkpoints": "चेकपॉइंट",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Provider",
"modes": "Mode",
"mcp": "Server MCP",
"autoApprove": "Auto-Approve",
"browser": "Browser",
"checkpoints": "Checkpoint",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Fornitori",
"modes": "Modalità",
"mcp": "Server MCP",
"autoApprove": "Auto-approvazione",
"browser": "Accesso computer",
"checkpoints": "Punti di controllo",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "プロバイダー",
"modes": "モード",
"mcp": "MCPサーバー",
"autoApprove": "自動承認",
"browser": "コンピューターアクセス",
"checkpoints": "チェックポイント",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "공급자",
"modes": "모드",
"mcp": "MCP 서버",
"autoApprove": "자동 승인",
"browser": "컴퓨터 접근",
"checkpoints": "체크포인트",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Providers",
"modes": "Modi",
"mcp": "MCP-servers",
"autoApprove": "Auto-goedkeuren",
"browser": "Browser",
"checkpoints": "Checkpoints",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Dostawcy",
"modes": "Tryby",
"mcp": "Serwery MCP",
"autoApprove": "Auto-zatwierdzanie",
"browser": "Dostęp komputera",
"checkpoints": "Punkty kontrolne",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Provedores",
"modes": "Modos",
"mcp": "Servidores MCP",
"autoApprove": "Aprovação",
"browser": "Navegador",
"checkpoints": "Checkpoints",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Провайдеры",
"modes": "Режимы",
"mcp": "Серверы MCP",
"autoApprove": "Автоодобрение",
"browser": "Доступ к компьютеру",
"checkpoints": "Контрольные точки",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Sağlayıcılar",
"modes": "Modlar",
"mcp": "MCP Sunucuları",
"autoApprove": "Oto-Onay",
"browser": "Bilgisayar Erişimi",
"checkpoints": "Kontrol Noktaları",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "Nhà cung cấp",
"modes": "Chế độ",
"mcp": "Máy chủ MCP",
"autoApprove": "Phê duyệt",
"browser": "Trình duyệt",
"checkpoints": "Điểm kiểm tra",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "提供商",
"modes": "模式",
"mcp": "MCP 服务",
"autoApprove": "自动批准",
"browser": "计算机交互",
"checkpoints": "存档点",

View file

@ -22,6 +22,8 @@
},
"sections": {
"providers": "供應商",
"modes": "模式",
"mcp": "MCP 伺服器",
"autoApprove": "自動核准",
"browser": "電腦存取",
"checkpoints": "檢查點",