Skip to content

Commit 66e036e

Browse files
committed
Fix settings colors for themes that use color transparency
1 parent ee997c8 commit 66e036e

File tree

9 files changed

+663
-953
lines changed

9 files changed

+663
-953
lines changed

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

Lines changed: 515 additions & 777 deletions
Large diffs are not rendered by default.

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

Lines changed: 17 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
22
import { memo, useEffect, useRef, useState } from "react"
33
import { useRemark } from "react-remark"
44

5+
import { cn } from "@/lib/utils"
6+
import { Collapsible, CollapsibleTrigger } from "@/components/ui"
7+
58
import { StyledMarkdown } from "./styles"
69

710
export const ModelDescriptionMarkdown = memo(
811
({
9-
markdown,
12+
markdown = "",
1013
key,
1114
isExpanded,
1215
setIsExpanded,
@@ -16,75 +19,30 @@ export const ModelDescriptionMarkdown = memo(
1619
isExpanded: boolean
1720
setIsExpanded: (isExpanded: boolean) => void
1821
}) => {
19-
const [reactContent, setMarkdown] = useRemark()
20-
const [showSeeMore, setShowSeeMore] = useState(false)
22+
const [content, setContent] = useRemark()
23+
const [isExpandable, setIsExpandable] = useState(false)
2124
const textContainerRef = useRef<HTMLDivElement>(null)
2225
const textRef = useRef<HTMLDivElement>(null)
2326

24-
useEffect(() => {
25-
setMarkdown(markdown || "")
26-
}, [markdown, setMarkdown])
27+
useEffect(() => setContent(markdown), [markdown, setContent])
2728

2829
useEffect(() => {
2930
if (textRef.current && textContainerRef.current) {
30-
const { scrollHeight } = textRef.current
31-
const { clientHeight } = textContainerRef.current
32-
const isOverflowing = scrollHeight > clientHeight
33-
setShowSeeMore(isOverflowing)
31+
setIsExpandable(textRef.current.scrollHeight > textContainerRef.current.clientHeight)
3432
}
35-
}, [reactContent, setIsExpanded])
33+
}, [content])
3634

3735
return (
38-
<StyledMarkdown key={key} style={{ display: "inline-block", marginBottom: 0 }}>
39-
<div
40-
ref={textContainerRef}
41-
style={{
42-
overflowY: isExpanded ? "auto" : "hidden",
43-
position: "relative",
44-
wordBreak: "break-word",
45-
overflowWrap: "anywhere",
46-
}}>
47-
<div
48-
ref={textRef}
49-
style={{
50-
display: "-webkit-box",
51-
WebkitLineClamp: isExpanded ? "unset" : 3,
52-
WebkitBoxOrient: "vertical",
53-
overflow: "hidden",
54-
}}>
55-
{reactContent}
36+
<Collapsible open={isExpanded} onOpenChange={setIsExpanded} className="relative">
37+
<div ref={textContainerRef} className={cn({ "line-clamp-3": !isExpanded })}>
38+
<div ref={textRef}>
39+
<StyledMarkdown key={key}>{content}</StyledMarkdown>
5640
</div>
57-
{!isExpanded && showSeeMore && (
58-
<div
59-
style={{
60-
position: "absolute",
61-
right: 0,
62-
bottom: 0,
63-
display: "flex",
64-
alignItems: "center",
65-
}}>
66-
<div
67-
style={{
68-
width: 30,
69-
height: "1.2em",
70-
background:
71-
"linear-gradient(to right, transparent, var(--vscode-sideBar-background))",
72-
}}
73-
/>
74-
<VSCodeLink
75-
style={{
76-
fontSize: "inherit",
77-
paddingRight: 0,
78-
paddingLeft: 3,
79-
backgroundColor: "var(--vscode-sideBar-background)",
80-
}}
81-
onClick={() => setIsExpanded(true)}>
82-
See more
83-
</VSCodeLink>
84-
</div>
85-
)}
8641
</div>
87-
</StyledMarkdown>
42+
<CollapsibleTrigger asChild className={cn({ hidden: !isExpandable })}>
43+
<VSCodeLink className="text-sm">{isExpanded ? "Less" : "More"}</VSCodeLink>
44+
</CollapsibleTrigger>
45+
</Collapsible>
8846
)
8947
},
9048
)
Lines changed: 57 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
1+
import { useMemo } from "react"
12
import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
2-
import { Fragment } from "react"
3+
4+
import { formatPrice } from "@/utils/formatPrice"
5+
import { cn } from "@/lib/utils"
36

47
import { ModelInfo, geminiModels } from "../../../../src/shared/api"
8+
59
import { ModelDescriptionMarkdown } from "./ModelDescriptionMarkdown"
6-
import { formatPrice } from "../../utils/formatPrice"
10+
11+
type ModelInfoViewProps = {
12+
selectedModelId: string
13+
modelInfo: ModelInfo
14+
isDescriptionExpanded: boolean
15+
setIsDescriptionExpanded: (isExpanded: boolean) => void
16+
}
717

818
export const ModelInfoView = ({
919
selectedModelId,
1020
modelInfo,
1121
isDescriptionExpanded,
1222
setIsDescriptionExpanded,
13-
}: {
14-
selectedModelId: string
15-
modelInfo: ModelInfo
16-
isDescriptionExpanded: boolean
17-
setIsDescriptionExpanded: (isExpanded: boolean) => void
18-
}) => {
19-
const isGemini = Object.keys(geminiModels).includes(selectedModelId)
23+
}: ModelInfoViewProps) => {
24+
const isGemini = useMemo(() => Object.keys(geminiModels).includes(selectedModelId), [selectedModelId])
2025

2126
const infoItems = [
22-
modelInfo.description && (
23-
<ModelDescriptionMarkdown
24-
key="description"
25-
markdown={modelInfo.description}
26-
isExpanded={isDescriptionExpanded}
27-
setIsExpanded={setIsDescriptionExpanded}
28-
/>
29-
),
3027
<ModelInfoSupportsItem
3128
isSupported={modelInfo.supportsImages ?? false}
3229
supportsLabel="Supports images"
@@ -45,53 +42,59 @@ export const ModelInfoView = ({
4542
/>
4643
),
4744
modelInfo.maxTokens !== undefined && modelInfo.maxTokens > 0 && (
48-
<span key="maxTokens">
49-
<span style={{ fontWeight: 500 }}>Max output:</span> {modelInfo.maxTokens?.toLocaleString()} tokens
50-
</span>
45+
<>
46+
<span className="font-medium">Max output:</span> {modelInfo.maxTokens?.toLocaleString()} tokens
47+
</>
5148
),
5249
modelInfo.inputPrice !== undefined && modelInfo.inputPrice > 0 && (
53-
<span key="inputPrice">
54-
<span style={{ fontWeight: 500 }}>Input price:</span> {formatPrice(modelInfo.inputPrice)}/million tokens
55-
</span>
50+
<>
51+
<span className="font-medium">Input price:</span> {formatPrice(modelInfo.inputPrice)} / 1M tokens
52+
</>
5653
),
57-
modelInfo.supportsPromptCache && modelInfo.cacheWritesPrice && (
58-
<span key="cacheWritesPrice">
59-
<span style={{ fontWeight: 500 }}>Cache writes price:</span>{" "}
60-
{formatPrice(modelInfo.cacheWritesPrice || 0)}/million tokens
61-
</span>
54+
modelInfo.outputPrice !== undefined && modelInfo.outputPrice > 0 && (
55+
<>
56+
<span className="font-medium">Output price:</span> {formatPrice(modelInfo.outputPrice)} / 1M tokens
57+
</>
6258
),
6359
modelInfo.supportsPromptCache && modelInfo.cacheReadsPrice && (
64-
<span key="cacheReadsPrice">
65-
<span style={{ fontWeight: 500 }}>Cache reads price:</span>{" "}
66-
{formatPrice(modelInfo.cacheReadsPrice || 0)}/million tokens
67-
</span>
60+
<>
61+
<span className="font-medium">Cache reads price:</span> {formatPrice(modelInfo.cacheReadsPrice || 0)} /
62+
1M tokens
63+
</>
6864
),
69-
modelInfo.outputPrice !== undefined && modelInfo.outputPrice > 0 && (
70-
<span key="outputPrice">
71-
<span style={{ fontWeight: 500 }}>Output price:</span> {formatPrice(modelInfo.outputPrice)}/million
72-
tokens
73-
</span>
65+
modelInfo.supportsPromptCache && modelInfo.cacheWritesPrice && (
66+
<>
67+
<span className="font-medium">Cache writes price:</span> {formatPrice(modelInfo.cacheWritesPrice || 0)}{" "}
68+
/ 1M tokens
69+
</>
7470
),
7571
isGemini && (
76-
<span key="geminiInfo" style={{ fontStyle: "italic" }}>
72+
<span className="italic">
7773
* Free up to {selectedModelId && selectedModelId.includes("flash") ? "15" : "2"} requests per minute.
7874
After that, billing depends on prompt size.{" "}
79-
<VSCodeLink href="https://ai.google.dev/pricing" style={{ display: "inline", fontSize: "inherit" }}>
75+
<VSCodeLink href="https://ai.google.dev/pricing" className="text-sm">
8076
For more info, see pricing details.
8177
</VSCodeLink>
8278
</span>
8379
),
8480
].filter(Boolean)
8581

8682
return (
87-
<div style={{ fontSize: "12px", marginTop: "2px", color: "var(--vscode-descriptionForeground)" }}>
88-
{infoItems.map((item, index) => (
89-
<Fragment key={index}>
90-
{item}
91-
{index < infoItems.length - 1 && <br />}
92-
</Fragment>
93-
))}
94-
</div>
83+
<>
84+
{modelInfo.description && (
85+
<ModelDescriptionMarkdown
86+
key="description"
87+
markdown={modelInfo.description}
88+
isExpanded={isDescriptionExpanded}
89+
setIsExpanded={setIsDescriptionExpanded}
90+
/>
91+
)}
92+
<div className="text-sm text-vscode-descriptionForeground">
93+
{infoItems.map((item, index) => (
94+
<div key={index}>{item}</div>
95+
))}
96+
</div>
97+
</>
9598
)
9699
}
97100

@@ -104,21 +107,12 @@ const ModelInfoSupportsItem = ({
104107
supportsLabel: string
105108
doesNotSupportLabel: string
106109
}) => (
107-
<span
108-
style={{
109-
fontWeight: 500,
110-
color: isSupported ? "var(--vscode-charts-green)" : "var(--vscode-errorForeground)",
111-
}}>
112-
<i
113-
className={`codicon codicon-${isSupported ? "check" : "x"}`}
114-
style={{
115-
marginRight: 4,
116-
marginBottom: isSupported ? 1 : -1,
117-
fontSize: isSupported ? 11 : 13,
118-
fontWeight: 700,
119-
display: "inline-block",
120-
verticalAlign: "bottom",
121-
}}></i>
110+
<div
111+
className={cn(
112+
"flex items-center gap-1 font-medium",
113+
isSupported ? "text-vscode-charts-green" : "text-vscode-errorForeground",
114+
)}>
115+
<span className={cn("codicon", isSupported ? "codicon-check" : "codicon-x")} />
122116
{isSupported ? supportsLabel : doesNotSupportLabel}
123-
</span>
117+
</div>
124118
)

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

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -72,23 +72,20 @@ export const ModelPicker = ({
7272

7373
return (
7474
<>
75-
<div className="font-semibold">Model</div>
76-
<Combobox type="single" inputValue={inputValue} onInputValueChange={onSelect}>
77-
<ComboboxInput placeholder="Search model..." data-testid="model-input" />
78-
<ComboboxContent>
79-
<ComboboxEmpty>No model found.</ComboboxEmpty>
80-
{modelIds.map((model) => (
81-
<ComboboxItem key={model} value={model}>
82-
{model}
83-
</ComboboxItem>
84-
))}
85-
</ComboboxContent>
86-
</Combobox>
87-
<ThinkingBudget
88-
apiConfiguration={apiConfiguration}
89-
setApiConfigurationField={setApiConfigurationField}
90-
modelInfo={selectedModelInfo}
91-
/>
75+
<div>
76+
<div className="font-medium">Model</div>
77+
<Combobox type="single" inputValue={inputValue} onInputValueChange={onSelect}>
78+
<ComboboxInput placeholder="Search model..." data-testid="model-input" />
79+
<ComboboxContent>
80+
<ComboboxEmpty>No model found.</ComboboxEmpty>
81+
{modelIds.map((model) => (
82+
<ComboboxItem key={model} value={model}>
83+
{model}
84+
</ComboboxItem>
85+
))}
86+
</ComboboxContent>
87+
</Combobox>
88+
</div>
9289
{selectedModelId && selectedModelInfo && selectedModelId === inputValue && (
9390
<ModelInfoView
9491
selectedModelId={selectedModelId}
@@ -97,15 +94,22 @@ export const ModelPicker = ({
9794
setIsDescriptionExpanded={setIsDescriptionExpanded}
9895
/>
9996
)}
100-
<p>
97+
<ThinkingBudget
98+
apiConfiguration={apiConfiguration}
99+
setApiConfigurationField={setApiConfigurationField}
100+
modelInfo={selectedModelInfo}
101+
/>
102+
<div className="text-sm text-vscode-descriptionForeground">
101103
The extension automatically fetches the latest list of models available on{" "}
102-
<VSCodeLink style={{ display: "inline", fontSize: "inherit" }} href={serviceUrl}>
103-
{serviceName}.
104+
<VSCodeLink href={serviceUrl} className="text-sm">
105+
{serviceName}
106+
</VSCodeLink>
107+
. If you're unsure which model to choose, Roo Code works best with{" "}
108+
<VSCodeLink onClick={() => onSelect(defaultModelId)} className="text-sm">
109+
{defaultModelId}.
104110
</VSCodeLink>
105-
If you're unsure which model to choose, Roo Code works best with{" "}
106-
<VSCodeLink onClick={() => onSelect(defaultModelId)}>{defaultModelId}.</VSCodeLink>
107111
You can also try searching "free" for no-cost options currently available.
108-
</p>
112+
</div>
109113
</>
110114
)
111115
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ type SectionHeaderProps = HTMLAttributes<HTMLDivElement> & {
88
}
99

1010
export const SectionHeader = ({ description, children, className, ...props }: SectionHeaderProps) => (
11-
<div className={cn("sticky top-0 z-10 bg-vscode-panel-border px-5 py-4", className)} {...props}>
11+
<div
12+
className={cn(
13+
"sticky top-0 z-10 text-vscode-sideBar-foreground bg-vscode-sideBar-background brightness-90 px-5 py-4",
14+
className,
15+
)}
16+
{...props}>
1217
<h4 className="m-0">{children}</h4>
1318
{description && <p className="text-vscode-descriptionForeground text-sm mt-2 mb-0">{description}</p>}
1419
</div>

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ApiConfiguration } from "../../../../src/shared/api"
77

88
import { vscode } from "@/utils/vscode"
99
import { ExtensionStateContextType, useExtensionState } from "@/context/ExtensionStateContext"
10+
import { cn } from "@/lib/utils"
1011
import {
1112
AlertDialog,
1213
AlertDialogContent,
@@ -247,14 +248,13 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone },
247248
<div className="flex justify-between items-center">
248249
<div className="flex items-center gap-2">
249250
<h3 className="text-vscode-foreground m-0">Settings</h3>
250-
<div className="hidden [@media(min-width:430px)]:flex items-center">
251+
<div className="hidden [@media(min-width:400px)]:flex items-center">
251252
{sections.map(({ id, icon: Icon, ref }) => (
252253
<Button
253254
key={id}
254255
variant="ghost"
255-
size="icon"
256-
className={activeSection === id ? "opacity-100" : "opacity-40"}
257-
onClick={() => scrollToSection(ref)}>
256+
onClick={() => scrollToSection(ref)}
257+
className={cn("w-6 h-6", activeSection === id ? "opacity-100" : "opacity-40")}>
258258
<Icon />
259259
</Button>
260260
))}
@@ -287,7 +287,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone },
287287
</div>
288288

289289
<div
290-
className="flex flex-col flex-1 overflow-auto divide-y divide-vscode-panel-border"
290+
className="flex flex-col flex-1 overflow-auto divide-y divide-vscode-sideBar-background"
291291
onScroll={handleScroll}>
292292
<div ref={providersRef}>
293293
<SectionHeader>

0 commit comments

Comments
 (0)