Skip to content

Commit f4abdf4

Browse files
Use the Slider component everywhere (#1786)
* Use the Slider component everywhere * onValueCommit -> onValueChange * More cleanup * Fix tests * Add missing translations * Update webview-ui/src/components/settings/ContextManagementSettings.tsx Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * SelectDropdown fixes * Fix tests --------- Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
1 parent 2267cad commit f4abdf4

40 files changed

+689
-751
lines changed

scripts/find-missing-translations.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,17 @@ function checkAreaTranslations(area) {
141141
}
142142

143143
// Load file contents
144-
const englishFileContents = englishFiles.map((file) => ({
145-
name: file,
146-
content: JSON.parse(fs.readFileSync(path.join(englishDir, file), "utf8")),
147-
}))
144+
let englishFileContents
145+
146+
try {
147+
englishFileContents = englishFiles.map((file) => ({
148+
name: file,
149+
content: JSON.parse(fs.readFileSync(path.join(englishDir, file), "utf8")),
150+
}))
151+
} catch (e) {
152+
console.error(`Error: File '${englishDir}' is not a valid JSON file`)
153+
process.exit(1)
154+
}
148155

149156
console.log(
150157
`Checking ${englishFileContents.length} translation file(s): ${englishFileContents.map((f) => f.name).join(", ")}`,
@@ -167,7 +174,14 @@ function checkAreaTranslations(area) {
167174
}
168175

169176
// Load the locale file
170-
const localeContent = JSON.parse(fs.readFileSync(localeFilePath, "utf8"))
177+
let localeContent
178+
179+
try {
180+
localeContent = JSON.parse(fs.readFileSync(localeFilePath, "utf8"))
181+
} catch (e) {
182+
console.error(`Error: File '${localeFilePath}' is not a valid JSON file`)
183+
process.exit(1)
184+
}
171185

172186
// Find all keys in the English file
173187
const englishKeys = findKeys(englishContent)

webview-ui/src/__mocks__/@vscode/webview-ui-toolkit/react.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,3 @@ export const VSCodeRadio: React.FC<VSCodeProps> = ({ children, value, checked, o
103103

104104
export const VSCodeRadioGroup: React.FC<VSCodeProps> = ({ children, onChange, ...props }) =>
105105
React.createElement("div", { role: "radiogroup", onChange, ...props }, children)
106-
107-
export const VSCodeSlider: React.FC<VSCodeProps> = ({ value, onChange, ...props }) =>
108-
React.createElement("input", {
109-
type: "range",
110-
value,
111-
onChange: (e: any) => onChange?.({ target: { value: Number(e.target.value) } }),
112-
min: 0,
113-
max: 1,
114-
step: 0.01,
115-
style: { flexGrow: 1, height: "2px" },
116-
...props,
117-
})

webview-ui/src/__mocks__/vscrui.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React from "react"
22

3-
export const Checkbox = ({ children, checked, onChange }: any) =>
3+
export const Checkbox = ({ children, onChange }: any) =>
44
React.createElement("div", { "data-testid": "mock-checkbox", onClick: onChange }, children)
55

6-
export const Dropdown = ({ children, value, onChange }: any) =>
6+
export const Dropdown = ({ children, onChange }: any) =>
77
React.createElement("div", { "data-testid": "mock-dropdown", onClick: onChange }, children)
88

99
export const Pane = ({ children }: any) => React.createElement("div", { "data-testid": "mock-pane" }, children)

webview-ui/src/components/settings/AdvancedSettings.tsx

Lines changed: 70 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,22 @@ import { Cog } from "lucide-react"
66
import { EXPERIMENT_IDS, ExperimentId } from "../../../../src/shared/experiments"
77

88
import { cn } from "@/lib/utils"
9+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Slider } from "@/components/ui"
910

1011
import { SetCachedStateField, SetExperimentEnabled } from "./types"
11-
import { sliderLabelStyle } from "./styles"
1212
import { SectionHeader } from "./SectionHeader"
1313
import { Section } from "./Section"
1414

1515
type AdvancedSettingsProps = HTMLAttributes<HTMLDivElement> & {
1616
rateLimitSeconds: number
17-
terminalShellIntegrationTimeout: number | undefined
1817
diffEnabled?: boolean
1918
fuzzyMatchThreshold?: number
20-
setCachedStateField: SetCachedStateField<
21-
"rateLimitSeconds" | "diffEnabled" | "fuzzyMatchThreshold" | "terminalShellIntegrationTimeout"
22-
>
19+
setCachedStateField: SetCachedStateField<"rateLimitSeconds" | "diffEnabled" | "fuzzyMatchThreshold">
2320
experiments: Record<ExperimentId, boolean>
2421
setExperimentEnabled: SetExperimentEnabled
2522
}
2623
export const AdvancedSettings = ({
2724
rateLimitSeconds,
28-
terminalShellIntegrationTimeout,
2925
diffEnabled,
3026
fuzzyMatchThreshold,
3127
setCachedStateField,
@@ -35,6 +31,7 @@ export const AdvancedSettings = ({
3531
...props
3632
}: AdvancedSettingsProps) => {
3733
const { t } = useAppTranslation()
34+
3835
return (
3936
<div className={cn("flex flex-col gap-2", className)} {...props}>
4037
<SectionHeader>
@@ -49,50 +46,18 @@ export const AdvancedSettings = ({
4946
<div className="flex flex-col gap-2">
5047
<span className="font-medium">{t("settings:advanced.rateLimit.label")}</span>
5148
<div className="flex items-center gap-2">
52-
<input
53-
type="range"
54-
min="0"
55-
max="60"
56-
step="1"
57-
value={rateLimitSeconds}
58-
onChange={(e) => setCachedStateField("rateLimitSeconds", parseInt(e.target.value))}
59-
className="h-2 focus:outline-0 w-4/5 accent-vscode-button-background"
49+
<Slider
50+
min={0}
51+
max={60}
52+
step={1}
53+
value={[rateLimitSeconds]}
54+
onValueChange={([value]) => setCachedStateField("rateLimitSeconds", value)}
6055
/>
61-
<span style={{ ...sliderLabelStyle }}>{rateLimitSeconds}s</span>
56+
<span className="w-10">{rateLimitSeconds}s</span>
6257
</div>
6358
</div>
64-
<p className="text-vscode-descriptionForeground text-sm mt-0">
59+
<div className="text-vscode-descriptionForeground text-sm mt-1">
6560
{t("settings:advanced.rateLimit.description")}
66-
</p>
67-
</div>
68-
69-
<div>
70-
<div className="flex flex-col gap-2">
71-
<span className="font-medium">Terminal shell integration timeout</span>
72-
<div className="flex items-center gap-2">
73-
<input
74-
type="range"
75-
min="1000"
76-
max="60000"
77-
step="1000"
78-
value={terminalShellIntegrationTimeout}
79-
onChange={(e) =>
80-
setCachedStateField(
81-
"terminalShellIntegrationTimeout",
82-
Math.min(60000, Math.max(1000, parseInt(e.target.value))),
83-
)
84-
}
85-
className="h-2 focus:outline-0 w-4/5 accent-vscode-button-background"
86-
/>
87-
<span style={{ ...sliderLabelStyle }}>
88-
{(terminalShellIntegrationTimeout ?? 4000) / 1000}s
89-
</span>
90-
</div>
91-
<p className="text-vscode-descriptionForeground text-sm mt-0">
92-
Maximum time to wait for shell integration to initialize before executing commands. For
93-
users with long shell startup times, this value may need to be increased if you see "Shell
94-
Integration Unavailable" errors in the terminal.
95-
</p>
9661
</div>
9762
</div>
9863

@@ -109,80 +74,83 @@ export const AdvancedSettings = ({
10974
}}>
11075
<span className="font-medium">{t("settings:advanced.diff.label")}</span>
11176
</VSCodeCheckbox>
112-
<p className="text-vscode-descriptionForeground text-sm mt-0">
77+
<div className="text-vscode-descriptionForeground text-sm">
11378
{t("settings:advanced.diff.description")}
114-
</p>
115-
{diffEnabled && (
116-
<div className="flex flex-col gap-2 mt-3 mb-2 pl-3 border-l-2 border-vscode-button-background">
117-
<div className="flex flex-col gap-2">
118-
<span className="font-medium">{t("settings:advanced.diff.strategy.label")}</span>
119-
<select
120-
value={
121-
experiments[EXPERIMENT_IDS.DIFF_STRATEGY]
122-
? "unified"
123-
: experiments[EXPERIMENT_IDS.MULTI_SEARCH_AND_REPLACE]
124-
? "multiBlock"
125-
: "standard"
79+
</div>
80+
</div>
81+
82+
{diffEnabled && (
83+
<div className="flex flex-col gap-3 pl-3 border-l-2 border-vscode-button-background">
84+
<div>
85+
<label className="block font-medium mb-1">
86+
{t("settings:advanced.diff.strategy.label")}
87+
</label>
88+
<Select
89+
value={
90+
experiments[EXPERIMENT_IDS.DIFF_STRATEGY]
91+
? "unified"
92+
: experiments[EXPERIMENT_IDS.MULTI_SEARCH_AND_REPLACE]
93+
? "multiBlock"
94+
: "standard"
95+
}
96+
onValueChange={(value) => {
97+
if (value === "standard") {
98+
setExperimentEnabled(EXPERIMENT_IDS.DIFF_STRATEGY, false)
99+
setExperimentEnabled(EXPERIMENT_IDS.MULTI_SEARCH_AND_REPLACE, false)
100+
} else if (value === "unified") {
101+
setExperimentEnabled(EXPERIMENT_IDS.DIFF_STRATEGY, true)
102+
setExperimentEnabled(EXPERIMENT_IDS.MULTI_SEARCH_AND_REPLACE, false)
103+
} else if (value === "multiBlock") {
104+
setExperimentEnabled(EXPERIMENT_IDS.DIFF_STRATEGY, false)
105+
setExperimentEnabled(EXPERIMENT_IDS.MULTI_SEARCH_AND_REPLACE, true)
126106
}
127-
onChange={(e) => {
128-
const value = e.target.value
129-
if (value === "standard") {
130-
setExperimentEnabled(EXPERIMENT_IDS.DIFF_STRATEGY, false)
131-
setExperimentEnabled(EXPERIMENT_IDS.MULTI_SEARCH_AND_REPLACE, false)
132-
} else if (value === "unified") {
133-
setExperimentEnabled(EXPERIMENT_IDS.DIFF_STRATEGY, true)
134-
setExperimentEnabled(EXPERIMENT_IDS.MULTI_SEARCH_AND_REPLACE, false)
135-
} else if (value === "multiBlock") {
136-
setExperimentEnabled(EXPERIMENT_IDS.DIFF_STRATEGY, false)
137-
setExperimentEnabled(EXPERIMENT_IDS.MULTI_SEARCH_AND_REPLACE, true)
138-
}
139-
}}
140-
className="p-2 rounded w-full bg-vscode-input-background text-vscode-input-foreground border border-vscode-input-border outline-none focus:border-vscode-focusBorder">
141-
<option value="standard">
107+
}}>
108+
<SelectTrigger className="w-full">
109+
<SelectValue />
110+
</SelectTrigger>
111+
<SelectContent>
112+
<SelectItem value="standard">
142113
{t("settings:advanced.diff.strategy.options.standard")}
143-
</option>
144-
<option value="multiBlock">
114+
</SelectItem>
115+
<SelectItem value="multiBlock">
145116
{t("settings:advanced.diff.strategy.options.multiBlock")}
146-
</option>
147-
<option value="unified">
117+
</SelectItem>
118+
<SelectItem value="unified">
148119
{t("settings:advanced.diff.strategy.options.unified")}
149-
</option>
150-
</select>
151-
</div>
152-
153-
<p className="text-vscode-descriptionForeground text-sm mt-1">
120+
</SelectItem>
121+
</SelectContent>
122+
</Select>
123+
<div className="text-vscode-descriptionForeground text-sm mt-1">
154124
{!experiments[EXPERIMENT_IDS.DIFF_STRATEGY] &&
155125
!experiments[EXPERIMENT_IDS.MULTI_SEARCH_AND_REPLACE] &&
156126
t("settings:advanced.diff.strategy.descriptions.standard")}
157127
{experiments[EXPERIMENT_IDS.DIFF_STRATEGY] &&
158128
t("settings:advanced.diff.strategy.descriptions.unified")}
159129
{experiments[EXPERIMENT_IDS.MULTI_SEARCH_AND_REPLACE] &&
160130
t("settings:advanced.diff.strategy.descriptions.multiBlock")}
161-
</p>
131+
</div>
132+
</div>
162133

163-
<span className="font-medium mt-3">{t("settings:advanced.diff.matchPrecision.label")}</span>
134+
<div>
135+
<label className="block font-medium mb-1">
136+
{t("settings:advanced.diff.matchPrecision.label")}
137+
</label>
164138
<div className="flex items-center gap-2">
165-
<input
166-
type="range"
167-
min="0.8"
168-
max="1"
169-
step="0.005"
170-
value={fuzzyMatchThreshold ?? 1.0}
171-
onChange={(e) => {
172-
setCachedStateField("fuzzyMatchThreshold", parseFloat(e.target.value))
173-
}}
174-
className="h-2 focus:outline-0 w-4/5 accent-vscode-button-background"
139+
<Slider
140+
min={0.8}
141+
max={1}
142+
step={0.005}
143+
value={[fuzzyMatchThreshold ?? 1.0]}
144+
onValueChange={([value]) => setCachedStateField("fuzzyMatchThreshold", value)}
175145
/>
176-
<span style={{ ...sliderLabelStyle }}>
177-
{Math.round((fuzzyMatchThreshold || 1) * 100)}%
178-
</span>
146+
<span className="w-10">{Math.round((fuzzyMatchThreshold || 1) * 100)}%</span>
179147
</div>
180-
<p className="text-vscode-descriptionForeground text-sm mt-0">
148+
<div className="text-vscode-descriptionForeground text-sm mt-1">
181149
{t("settings:advanced.diff.matchPrecision.description")}
182-
</p>
150+
</div>
183151
</div>
184-
)}
185-
</div>
152+
</div>
153+
)}
186154
</Section>
187155
</div>
188156
)

0 commit comments

Comments
 (0)