Skip to content

Commit b06025e

Browse files
sandersonstabojuliusmarminge
authored andcommitted
[fix/feat:ui] Preserve open-in editor brand colors (pingdotgg#3225)
Co-authored-by: Julius Marminge <julius0216@outlook.com>
1 parent 8588603 commit b06025e

1 file changed

Lines changed: 51 additions & 5 deletions

File tree

apps/web/src/components/chat/OpenInPicker.tsx

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,111 +31,138 @@ import {
3131
RustRoverIcon,
3232
WebStormIcon,
3333
} from "../JetBrainsIcons";
34-
import { isMacPlatform, isWindowsPlatform } from "~/lib/utils";
34+
import { cn, isMacPlatform, isWindowsPlatform } from "~/lib/utils";
3535
import { shellEnvironment } from "~/state/shell";
3636
import { useAtomCommand } from "~/state/use-atom-command";
3737

38+
type OpenInOption = {
39+
label: string;
40+
Icon: Icon;
41+
value: EditorId;
42+
kind: "brand" | "generic";
43+
};
44+
3845
const resolveOptions = (platform: string, availableEditors: ReadonlyArray<EditorId>) => {
39-
const baseOptions: ReadonlyArray<{ label: string; Icon: Icon; value: EditorId }> = [
46+
const baseOptions: ReadonlyArray<OpenInOption> = [
4047
{
4148
label: "Cursor",
4249
Icon: CursorIcon,
4350
value: "cursor",
51+
kind: "brand",
4452
},
4553
{
4654
label: "Trae",
4755
Icon: TraeIcon,
4856
value: "trae",
57+
kind: "brand",
4958
},
5059
{
5160
label: "Kiro",
5261
Icon: KiroIcon,
5362
value: "kiro",
63+
kind: "brand",
5464
},
5565
{
5666
label: "VS Code",
5767
Icon: VisualStudioCode,
5868
value: "vscode",
69+
kind: "brand",
5970
},
6071
{
6172
label: "VS Code Insiders",
6273
Icon: VisualStudioCodeInsiders,
6374
value: "vscode-insiders",
75+
kind: "brand",
6476
},
6577
{
6678
label: "VSCodium",
6779
Icon: VSCodium,
6880
value: "vscodium",
81+
kind: "brand",
6982
},
7083
{
7184
label: "Zed",
7285
Icon: Zed,
7386
value: "zed",
87+
kind: "brand",
7488
},
7589
{
7690
label: "Antigravity",
7791
Icon: AntigravityIcon,
7892
value: "antigravity",
93+
kind: "brand",
7994
},
8095
{
8196
label: "IntelliJ IDEA",
8297
Icon: IntelliJIdeaIcon,
8398
value: "idea",
99+
kind: "brand",
84100
},
85101
{
86102
label: "Aqua",
87103
Icon: AquaIcon,
88104
value: "aqua",
105+
kind: "brand",
89106
},
90107
{
91108
label: "CLion",
92109
Icon: CLionIcon,
93110
value: "clion",
111+
kind: "brand",
94112
},
95113
{
96114
label: "DataGrip",
97115
Icon: DataGripIcon,
98116
value: "datagrip",
117+
kind: "brand",
99118
},
100119
{
101120
label: "DataSpell",
102121
Icon: DataSpellIcon,
103122
value: "dataspell",
123+
kind: "brand",
104124
},
105125
{
106126
label: "GoLand",
107127
Icon: GoLandIcon,
108128
value: "goland",
129+
kind: "brand",
109130
},
110131
{
111132
label: "PhpStorm",
112133
Icon: PhpStormIcon,
113134
value: "phpstorm",
135+
kind: "brand",
114136
},
115137
{
116138
label: "PyCharm",
117139
Icon: PyCharmIcon,
118140
value: "pycharm",
141+
kind: "brand",
119142
},
120143
{
121144
label: "Rider",
122145
Icon: RiderIcon,
123146
value: "rider",
147+
kind: "brand",
124148
},
125149
{
126150
label: "RubyMine",
127151
Icon: RubyMineIcon,
128152
value: "rubymine",
153+
kind: "brand",
129154
},
130155
{
131156
label: "RustRover",
132157
Icon: RustRoverIcon,
133158
value: "rustrover",
159+
kind: "brand",
134160
},
135161
{
136162
label: "WebStorm",
137163
Icon: WebStormIcon,
138164
value: "webstorm",
165+
kind: "brand",
139166
},
140167
{
141168
label: isMacPlatform(platform)
@@ -145,12 +172,17 @@ const resolveOptions = (platform: string, availableEditors: ReadonlyArray<Editor
145172
: "Files",
146173
Icon: FolderClosedIcon,
147174
value: "file-manager",
175+
kind: "generic",
148176
},
149177
];
150178
const availableEditorSet = new Set(availableEditors);
151179
return baseOptions.filter((option) => availableEditorSet.has(option.value));
152180
};
153181

182+
function getOpenInIconClass(kind: OpenInOption["kind"]) {
183+
return cn(kind === "brand" ? "text-foreground opacity-100" : "text-muted-foreground");
184+
}
185+
154186
export const OpenInPicker = memo(function OpenInPicker({
155187
environmentId,
156188
keybindings,
@@ -233,7 +265,21 @@ export const OpenInPicker = memo(function OpenInPicker({
233265
disabled={!preferredEditor || !openInCwd}
234266
onClick={() => openInEditor(preferredEditor)}
235267
>
236-
{primaryOption?.Icon && <primaryOption.Icon aria-hidden="true" className="size-3.5" />}
268+
{primaryOption?.Icon && (
269+
<primaryOption.Icon
270+
aria-hidden="true"
271+
className={cn("size-3.5", getOpenInIconClass(primaryOption.kind))}
272+
/>
273+
)}
274+
<span
275+
className={
276+
compact
277+
? "sr-only"
278+
: "sr-only @3xl/header-actions:not-sr-only @3xl/header-actions:ml-0.5"
279+
}
280+
>
281+
Open
282+
</span>
237283
</Button>
238284
<GroupSeparator {...(!compact ? { className: "hidden @3xl/header-actions:block" } : {})} />
239285
<Menu>
@@ -250,9 +296,9 @@ export const OpenInPicker = memo(function OpenInPicker({
250296
</MenuTrigger>
251297
<MenuPopup align="end">
252298
{options.length === 0 && <MenuItem disabled>No installed editors found</MenuItem>}
253-
{options.map(({ label, Icon, value }) => (
299+
{options.map(({ label, Icon, value, kind }) => (
254300
<MenuItem key={value} onClick={() => openInEditor(value)}>
255-
<Icon aria-hidden="true" className="text-muted-foreground" />
301+
<Icon aria-hidden="true" className={getOpenInIconClass(kind)} />
256302
{label}
257303
{value === preferredEditor && openFavoriteEditorShortcutLabel && (
258304
<MenuShortcut>{openFavoriteEditorShortcutLabel}</MenuShortcut>

0 commit comments

Comments
 (0)