authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-17 12:33:44-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-02-17 19:47:09-08:00
log60ed67e5e1e5b983c0d6f0315baeb98b6372daea
treecabe996b2d94d44ce4934caf90be31daeaa9a40a
parentbd6a5c85e6f873997a3e0fc8dd3f773f9acc7893

Use bot icon for slash commands and normalize YAML file icons

- Replace slash-command menu glyph in ChatView with `BotIcon` - Map `yml`/`yaml` to base YAML language id to avoid overly specific icons - Add test coverage for GitHub workflow YAML icon selection

3 files changed, 9 insertions(+), 1 deletions(-)

apps/web/src/components/ChatView.tsx+2-1
...@@ -75,6 +75,7 @@ import ThreadTerminalDrawer from "./ThreadTerminalDrawer";...@@ -75,6 +75,7 @@ import ThreadTerminalDrawer from "./ThreadTerminalDrawer";
75import { useNativeApi } from "../hooks/useNativeApi";75import { useNativeApi } from "../hooks/useNativeApi";
76import { Alert, AlertAction, AlertDescription, AlertTitle } from "./ui/alert";76import { Alert, AlertAction, AlertDescription, AlertTitle } from "./ui/alert";
77import {77import {
78 BotIcon,
78 ChevronDownIcon,79 ChevronDownIcon,
79 CircleAlertIcon,80 CircleAlertIcon,
80 FileIcon,81 FileIcon,
...@@ -259,7 +260,7 @@ const ComposerCommandMenuItem = memo(function ComposerCommandMenuItem(props: {...@@ -259,7 +260,7 @@ const ComposerCommandMenuItem = memo(function ComposerCommandMenuItem(props: {
259 />260 />
260 ) : null}261 ) : null}
261 {props.item.type === "slash-command" ? (262 {props.item.type === "slash-command" ? (
262 <CursorIcon className="size-4 text-muted-foreground/80" />263 <BotIcon className="size-4 text-muted-foreground/80" />
263 ) : null}264 ) : null}
264 {props.item.type === "model" ? (265 {props.item.type === "model" ? (
265 <Badge variant="outline" className="px-1.5 py-0 text-[10px]">266 <Badge variant="outline" className="px-1.5 py-0 text-[10px]">
apps/web/src/vscode-icons.test.ts+2
...@@ -31,11 +31,13 @@ describe("getVscodeIconUrlForEntry", () => {...@@ -31,11 +31,13 @@ describe("getVscodeIconUrlForEntry", () => {
31 const dockerfileUrl = getVscodeIconUrlForEntry("Dockerfile", "file", "dark");31 const dockerfileUrl = getVscodeIconUrlForEntry("Dockerfile", "file", "dark");
32 const shellUrl = getVscodeIconUrlForEntry("entrypoint.sh", "file", "dark");32 const shellUrl = getVscodeIconUrlForEntry("entrypoint.sh", "file", "dark");
33 const cursorRulesUrl = getVscodeIconUrlForEntry("general.mdc", "file", "dark");33 const cursorRulesUrl = getVscodeIconUrlForEntry("general.mdc", "file", "dark");
34 const githubWorkflowUrl = getVscodeIconUrlForEntry(".github/workflows/ci.yml", "file", "light");
3435
35 assert.isTrue(tsxUrl.endsWith("/file_type_reactts.svg"));36 assert.isTrue(tsxUrl.endsWith("/file_type_reactts.svg"));
36 assert.isTrue(dockerfileUrl.endsWith("/file_type_docker.svg"));37 assert.isTrue(dockerfileUrl.endsWith("/file_type_docker.svg"));
37 assert.isTrue(shellUrl.endsWith("/file_type_shell.svg"));38 assert.isTrue(shellUrl.endsWith("/file_type_shell.svg"));
38 assert.isTrue(cursorRulesUrl.endsWith("/file_type_markdown.svg"));39 assert.isTrue(cursorRulesUrl.endsWith("/file_type_markdown.svg"));
40 assert.isTrue(githubWorkflowUrl.endsWith("/file_type_light_yaml.svg"));
39 });41 });
4042
41 it("falls back to defaults when there is no match", () => {43 it("falls back to defaults when there is no match", () => {
apps/web/src/vscode-icons.ts+5
...@@ -45,6 +45,11 @@ const languageIdByFileName = toLowercaseLookup(languageAssociations.fileNameToLa...@@ -45,6 +45,11 @@ const languageIdByFileName = toLowercaseLookup(languageAssociations.fileNameToLa
45const localLanguageIdByExtensionOverrides = {45const localLanguageIdByExtensionOverrides = {
46 // Cursor rules files (*.mdc) are commonly treated as markdown in VSCode/Cursor.46 // Cursor rules files (*.mdc) are commonly treated as markdown in VSCode/Cursor.
47 mdc: "markdown",47 mdc: "markdown",
48 // Upstream languages.ts maps yml/yaml to specialized language ids that can produce
49 // non-generic YAML icons (for example cloudfoundry/esphome). Prefer the base YAML icon
50 // unless a more specific basename/extension match (e.g. azure-pipelines.yml) is found.
51 yml: "yaml",
52 yaml: "yaml",
48} as const;53} as const;
4954
50const defaultDarkFileIconDefinition = manifest.file ?? "_file";55const defaultDarkFileIconDefinition = manifest.file ?? "_file";