Skip to content

Commit 1fd6199

Browse files
author
Bruno Bergher
committed
Visual tweaks
1 parent 31fd2b9 commit 1fd6199

File tree

5 files changed

+96
-137
lines changed

5 files changed

+96
-137
lines changed

webview-ui/src/components/chat/AutoApproveMenu.tsx

Lines changed: 27 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { memo, useCallback, useMemo, useState } from "react"
22
import { Trans } from "react-i18next"
3-
import { VSCodeCheckbox, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
3+
import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
44
import { Stamp, ListChecks, LayoutList } from "lucide-react"
55

66
import { vscode } from "@src/utils/vscode"
@@ -23,8 +23,6 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
2323
const portalContainer = useRooPortal("roo-portal")
2424

2525
const {
26-
autoApprovalEnabled,
27-
setAutoApprovalEnabled,
2826
alwaysApproveResubmit,
2927
setAlwaysAllowReadOnly,
3028
setAlwaysAllowWrite,
@@ -51,7 +49,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
5149
[baseToggles, alwaysApproveResubmit],
5250
)
5351

54-
const { hasEnabledOptions, effectiveAutoApprovalEnabled } = useAutoApprovalState(toggles, autoApprovalEnabled)
52+
const { hasEnabledOptions, effectiveAutoApprovalEnabled } = useAutoApprovalState(toggles, true)
5553

5654
const onAutoApproveToggle = useCallback(
5755
(key: AutoApproveSetting, value: boolean) => {
@@ -90,30 +88,9 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
9088
setAlwaysAllowUpdateTodoList(value)
9189
break
9290
}
93-
94-
// Check if we need to update the master auto-approval state
95-
// Create a new toggles state with the updated value
96-
const updatedToggles = {
97-
...toggles,
98-
[key]: value,
99-
}
100-
101-
const willHaveEnabledOptions = Object.values(updatedToggles).some((v) => !!v)
102-
103-
// If enabling the first option, enable master auto-approval
104-
if (value && !hasEnabledOptions && willHaveEnabledOptions) {
105-
setAutoApprovalEnabled(true)
106-
vscode.postMessage({ type: "autoApprovalEnabled", bool: true })
107-
}
108-
// If disabling the last option, disable master auto-approval
109-
else if (!value && hasEnabledOptions && !willHaveEnabledOptions) {
110-
setAutoApprovalEnabled(false)
111-
vscode.postMessage({ type: "autoApprovalEnabled", bool: false })
112-
}
11391
},
11492
[
11593
toggles,
116-
hasEnabledOptions,
11794
setAlwaysAllowReadOnly,
11895
setAlwaysAllowWrite,
11996
setAlwaysAllowExecute,
@@ -124,7 +101,6 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
124101
setAlwaysApproveResubmit,
125102
setAlwaysAllowFollowupQuestions,
126103
setAlwaysAllowUpdateTodoList,
127-
setAutoApprovalEnabled,
128104
],
129105
)
130106

@@ -170,14 +146,14 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
170146
const trigger = (
171147
<PopoverTrigger
172148
className={cn(
173-
"inline-flex items-center gap-1.5 relative whitespace-nowrap px-2 py-1 text-xs",
149+
"inline-flex items-center gap-1.5 relative whitespace-nowrap px-2 py-1 text-xs flex-shrink-1",
174150
"bg-transparent border border-[rgba(255,255,255,0.08)] rounded-md text-vscode-foreground",
175151
"transition-all duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder focus-visible:ring-inset",
176152
"opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer",
177153
)}
178154
style={style}>
179155
<Stamp className="size-3.5 opacity-80 flex-shrink-0" />
180-
<span className="font-medium">{t("chat:autoApprove.title")}</span>
156+
<span className="font-medium">{t("chat:autoApprove.dropdownTitle")}</span>
181157
<span className="text-vscode-descriptionForeground truncate max-w-[200px]">{displayText}</span>
182158
</PopoverTrigger>
183159
)
@@ -192,50 +168,11 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
192168
container={portalContainer}
193169
className="p-0 overflow-hidden min-w-[400px] max-w-[500px]">
194170
<div className="flex flex-col w-full">
195-
{/* Header with master toggle */}
196-
<div className="flex items-center justify-between p-3 border-b border-vscode-dropdown-border">
197-
<div className="flex items-center gap-2">
198-
<StandardTooltip
199-
content={!hasEnabledOptions ? t("chat:autoApprove.selectOptionsFirst") : undefined}>
200-
<VSCodeCheckbox
201-
checked={effectiveAutoApprovalEnabled}
202-
disabled={!hasEnabledOptions}
203-
aria-label={
204-
hasEnabledOptions
205-
? t("chat:autoApprove.toggleAriaLabel")
206-
: t("chat:autoApprove.disabledAriaLabel")
207-
}
208-
onChange={() => {
209-
if (hasEnabledOptions) {
210-
const newValue = !(autoApprovalEnabled ?? false)
211-
setAutoApprovalEnabled(newValue)
212-
vscode.postMessage({ type: "autoApprovalEnabled", bool: newValue })
213-
}
214-
}}
215-
/>
216-
</StandardTooltip>
217-
<h4 className="m-0 font-medium text-sm">{t("chat:autoApprove.title")}</h4>
218-
</div>
219-
<div className="flex items-center gap-1">
220-
<StandardTooltip content={t("chat:autoApprove.selectAll")}>
221-
<button
222-
onClick={handleSelectAll}
223-
className="p-1 rounded hover:bg-vscode-list-hoverBackground transition-colors">
224-
<ListChecks className="size-4" />
225-
</button>
226-
</StandardTooltip>
227-
<StandardTooltip content={t("chat:autoApprove.selectNone")}>
228-
<button
229-
onClick={handleSelectNone}
230-
className="p-1 rounded hover:bg-vscode-list-hoverBackground transition-colors">
231-
<LayoutList className="size-4" />
232-
</button>
233-
</StandardTooltip>
234-
</div>
235-
</div>
236-
237-
{/* Description */}
238-
<div className="px-3 py-2 border-b border-vscode-dropdown-border">
171+
{/* Header */}
172+
<div className="p-3 border-b border-vscode-dropdown-border">
173+
<h3 className="m-0 font-bold text-sm text-vscode-button-foreground pb-2">
174+
{t("chat:autoApprove.title")}
175+
</h3>
239176
<div
240177
style={{
241178
color: "var(--vscode-descriptionForeground)",
@@ -256,6 +193,24 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
256193
<AutoApproveToggleDropdown {...toggles} onToggle={onAutoApproveToggle} />
257194
</div>
258195
</div>
196+
197+
{/* Footer with buttons on left and title on right */}
198+
<div className="flex items-center justify-between px-3 py-2 border-t border-vscode-dropdown-border">
199+
<div className="flex items-center gap-2">
200+
<button
201+
onClick={handleSelectAll}
202+
className="inline-flex items-center gap-1.5 px-3 py-1 text-xs rounded border border-vscode-button-border bg-vscode-button-secondaryBackground text-vscode-button-secondaryForeground hover:bg-vscode-button-secondaryHoverBackground transition-colors cursor-pointer">
203+
<ListChecks className="size-3.5" />
204+
All
205+
</button>
206+
<button
207+
onClick={handleSelectNone}
208+
className="inline-flex items-center gap-1.5 px-3 py-1 text-xs rounded border border-vscode-button-border bg-vscode-button-secondaryBackground text-vscode-button-secondaryForeground hover:bg-vscode-button-secondaryHoverBackground transition-colors cursor-pointer">
209+
<LayoutList className="size-3.5" />
210+
None
211+
</button>
212+
</div>
213+
</div>
259214
</div>
260215
</PopoverContent>
261216
</Popover>

webview-ui/src/components/chat/AutoApproveToggleDropdown.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,22 @@ export const AutoApproveToggleDropdown = ({ onToggle, ...props }: AutoApproveTog
5656
data-testid={testId}
5757
className={cn(
5858
"w-full flex items-center gap-2 px-2 py-1.5 rounded text-xs text-left",
59-
"transition-colors hover:bg-vscode-list-hoverBackground",
59+
"transition-colors hover:bg-vscode-list-hoverBackground cursor-pointer",
6060
props[key]
6161
? "bg-vscode-list-activeSelectionBackground text-vscode-list-activeSelectionForeground"
6262
: "opacity-70",
6363
)}>
6464
<span className={cn("codicon", `codicon-${icon}`, "text-sm flex-shrink-0")} />
6565
<span className="flex-1 truncate">{t(labelKey)}</span>
66-
<span
67-
className={cn(
68-
"text-[10px] px-1 rounded",
69-
props[key] ? "bg-vscode-badge-background text-vscode-badge-foreground" : "",
70-
)}>
71-
{props[key] ? "✓" : ""}
72-
</span>
66+
{DEFAULT_KEYBOARD_CONFIG.enabled && (
67+
<span
68+
className={cn(
69+
"text-[10px] px-1 rounded",
70+
"bg-vscode-badge-background text-vscode-badge-foreground opacity-60",
71+
)}>
72+
{shortcutDisplay.replace("Alt+", "⌥").replace("Ctrl+Shift+", "⌃⇧")}
73+
</span>
74+
)}
7375
</button>
7476
</StandardTooltip>
7577
)

webview-ui/src/components/chat/ChatTextArea.tsx

Lines changed: 56 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { SlashCommandsPopover } from "./SlashCommandsPopover"
3232
import { cn } from "@/lib/utils"
3333
import { usePromptHistory } from "./hooks/usePromptHistory"
3434
import { EditModeControls } from "./EditModeControls"
35+
import AutoApproveMenu from "./AutoApproveMenu"
3536

3637
interface ChatTextAreaProps {
3738
inputValue: string
@@ -917,31 +918,58 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
917918

918919
// Helper function to render non-edit mode controls
919920
const renderNonEditModeControls = () => (
920-
<div className={cn("flex", "justify-between", "items-center", "mt-auto")}>
921-
<div className={cn("flex", "items-center", "gap-1", "min-w-0")}>
922-
<div className="shrink-0">{renderModeSelector()}</div>
923-
924-
<div className={cn("flex-1", "min-w-0", "overflow-hidden")}>
925-
<ApiConfigSelector
926-
value={currentConfigId}
927-
displayName={displayName}
928-
disabled={selectApiConfigDisabled}
929-
title={t("chat:selectApiConfig")}
930-
onChange={handleApiConfigChange}
931-
triggerClassName="w-full text-ellipsis overflow-hidden"
932-
listApiConfigMeta={listApiConfigMeta || []}
933-
pinnedApiConfigs={pinnedApiConfigs}
934-
togglePinnedApiConfig={togglePinnedApiConfig}
935-
/>
921+
<div className={cn("flex", "flex-col", "gap-1", "mt-auto")}>
922+
<div className={cn("flex", "justify-between", "items-center")}>
923+
<div className={cn("flex", "items-center", "gap-1", "min-w-0", "flex-nowrap")}>
924+
<div>{renderModeSelector()}</div>
925+
926+
<div>
927+
<ApiConfigSelector
928+
value={currentConfigId}
929+
displayName={displayName}
930+
disabled={selectApiConfigDisabled}
931+
title={t("chat:selectApiConfig")}
932+
onChange={handleApiConfigChange}
933+
triggerClassName="w-full text-ellipsis overflow-hidden"
934+
listApiConfigMeta={listApiConfigMeta || []}
935+
pinnedApiConfigs={pinnedApiConfigs}
936+
togglePinnedApiConfig={togglePinnedApiConfig}
937+
/>
938+
</div>
939+
940+
<div className="grow-1 shrink max-w-100% overflow-hidden">
941+
<AutoApproveMenu />
942+
</div>
936943
</div>
937-
</div>
938944

939-
<div className={cn("flex", "items-center", "gap-0.5", "shrink-0")}>
940-
{isTtsPlaying && (
941-
<StandardTooltip content={t("chat:stopTts")}>
945+
<div className={cn("flex", "items-center", "gap-0.5", "shrink-0")}>
946+
{isTtsPlaying && (
947+
<StandardTooltip content={t("chat:stopTts")}>
948+
<button
949+
aria-label={t("chat:stopTts")}
950+
onClick={() => vscode.postMessage({ type: "stopTts" })}
951+
className={cn(
952+
"relative inline-flex items-center justify-center",
953+
"bg-transparent border-none p-1.5",
954+
"rounded-md min-w-[28px] min-h-[28px]",
955+
"text-vscode-foreground opacity-85",
956+
"transition-all duration-150",
957+
"hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
958+
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
959+
"active:bg-[rgba(255,255,255,0.1)]",
960+
"cursor-pointer",
961+
)}>
962+
<VolumeX className="w-4 h-4" />
963+
</button>
964+
</StandardTooltip>
965+
)}
966+
<SlashCommandsPopover />
967+
<IndexingStatusBadge />
968+
<StandardTooltip content={t("chat:addImages")}>
942969
<button
943-
aria-label={t("chat:stopTts")}
944-
onClick={() => vscode.postMessage({ type: "stopTts" })}
970+
aria-label={t("chat:addImages")}
971+
disabled={shouldDisableImages}
972+
onClick={!shouldDisableImages ? onSelectImages : undefined}
945973
className={cn(
946974
"relative inline-flex items-center justify-center",
947975
"bg-transparent border-none p-1.5",
@@ -951,36 +979,15 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
951979
"hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
952980
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
953981
"active:bg-[rgba(255,255,255,0.1)]",
954-
"cursor-pointer",
982+
!shouldDisableImages && "cursor-pointer",
983+
shouldDisableImages &&
984+
"opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent",
985+
"mr-1",
955986
)}>
956-
<VolumeX className="w-4 h-4" />
987+
<Image className="w-4 h-4" />
957988
</button>
958989
</StandardTooltip>
959-
)}
960-
<SlashCommandsPopover />
961-
<IndexingStatusBadge />
962-
<StandardTooltip content={t("chat:addImages")}>
963-
<button
964-
aria-label={t("chat:addImages")}
965-
disabled={shouldDisableImages}
966-
onClick={!shouldDisableImages ? onSelectImages : undefined}
967-
className={cn(
968-
"relative inline-flex items-center justify-center",
969-
"bg-transparent border-none p-1.5",
970-
"rounded-md min-w-[28px] min-h-[28px]",
971-
"text-vscode-foreground opacity-85",
972-
"transition-all duration-150",
973-
"hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
974-
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
975-
"active:bg-[rgba(255,255,255,0.1)]",
976-
!shouldDisableImages && "cursor-pointer",
977-
shouldDisableImages &&
978-
"opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent",
979-
"mr-1",
980-
)}>
981-
<Image className="w-4 h-4" />
982-
</button>
983-
</StandardTooltip>
990+
</div>
984991
</div>
985992
</div>
986993
)

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ import BrowserSessionRow from "./BrowserSessionRow"
5050
import ChatRow from "./ChatRow"
5151
import ChatTextArea from "./ChatTextArea"
5252
import TaskHeader from "./TaskHeader"
53-
import AutoApproveMenu from "./AutoApproveMenu"
5453
import { AutoApproveKeyboardShortcuts } from "./AutoApproveKeyboardShortcuts"
5554
import SystemPromptWarning from "./SystemPromptWarning"
5655
import ProfileViolationWarning from "./ProfileViolationWarning"
@@ -2019,11 +2018,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
20192018
modeShortcutText={modeShortcutText}
20202019
/>
20212020

2022-
{/* Auto-Approve Menu positioned below text area */}
2023-
<div className="px-3 pb-2">
2024-
<AutoApproveMenu />
2025-
</div>
2026-
20272021
{isProfileDisabled && (
20282022
<div className="px-3">
20292023
<ProfileViolationWarning />

webview-ui/src/i18n/locales/en/chat.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,10 @@
265265
"issues": "It seems like you're having Windows PowerShell issues, please see this"
266266
},
267267
"autoApprove": {
268-
"title": "Auto-approve:",
268+
"title": "Auto-Approve",
269+
"dropdownTitle": "Auto:",
269270
"none": "None",
270-
"description": "Auto-approve allows Roo Code to perform actions without asking for permission. Only enable for actions you fully trust. More detailed configuration available in <settingsLink>Settings</settingsLink>.",
271+
"description": "Run these actions without asking for permission.Only enable for actions you fully trust. More in <settingsLink>Settings</settingsLink>.",
271272
"selectOptionsFirst": "Select at least one option below to enable auto-approval",
272273
"toggleAriaLabel": "Toggle auto-approval",
273274
"disabledAriaLabel": "Auto-approval disabled - select options first"

0 commit comments

Comments
 (0)