diff --git a/apps/desktop/src/features/workspace/SectionRoadmap.test.tsx b/apps/desktop/src/features/workspace/SectionRoadmap.test.tsx index 5b32019d2..fe4583873 100644 --- a/apps/desktop/src/features/workspace/SectionRoadmap.test.tsx +++ b/apps/desktop/src/features/workspace/SectionRoadmap.test.tsx @@ -36,6 +36,24 @@ describe("SectionRoadmap", () => { expect(screen.getAllByText("verse 들어가기 전에 이 음역을 악기로 확인해 보세요.").length).toBeGreaterThan(0); }); + it("keeps unavailable chord edits focusable, visibly described, semantically disabled, and inert", () => { + setNavigatorLanguage("ko-KR"); + const song = createDemoRehearsalSong(); + const promptSpy = vi.spyOn(window, "prompt"); + + render(); + + const description = screen.getByText("이 화면에서는 코드를 수정할 수 없습니다."); + const button = screen.getByRole("button", { name: "Bass Guitar의 verse 코드 수정, 현재 C#m7" }); + expect(button.getAttribute("aria-disabled")).toBe("true"); + expect(button.hasAttribute("disabled")).toBe(false); + expect(button.tabIndex).toBe(0); + expect(button.getAttribute("aria-describedby")).toBe(description.id); + + fireEvent.click(button); + expect(promptSpy).not.toHaveBeenCalled(); + }); + it("omits the range row when both notes are unnamed", () => { setNavigatorLanguage("en-US"); const song = createDemoRehearsalSong(); @@ -90,7 +108,6 @@ describe("SectionRoadmap", () => { fireEvent.click(screen.getByRole("button", { name: "Bass Guitar의 verse 코드 수정, 현재 C#m7" })); expect(promptSpy).toHaveBeenCalledWith("새 코드 입력:", "C#m7"); - expect(screen.getAllByTitle("코드 수정").length).toBeGreaterThan(0); expect(onSongUpdate).toHaveBeenCalledTimes(1); }); diff --git a/apps/desktop/src/features/workspace/SectionRoadmap.tsx b/apps/desktop/src/features/workspace/SectionRoadmap.tsx index 834d1e8f0..35daff920 100644 --- a/apps/desktop/src/features/workspace/SectionRoadmap.tsx +++ b/apps/desktop/src/features/workspace/SectionRoadmap.tsx @@ -6,6 +6,7 @@ import { fillRangeCopy, playableRange } from "./firstRangeSqueeze"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Separator } from "@/components/ui/separator"; +import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { AlertCircle, CheckCircle2, Music2, Wand2, Lightbulb, Info } from "lucide-react"; interface SectionRoadmapProps { @@ -17,6 +18,7 @@ interface SectionRoadmapProps { /** Documented. */ export function SectionRoadmap({ song, activeRole, onSongUpdate }: SectionRoadmapProps) { const sectionRoadmapTitleId = useId(); + const chordEditDisabledDescriptionId = useId(); const locale = useMemo(() => detectPreferredLocale(), []); const t = useMemo(() => createTranslator(locale), [locale]); @@ -90,12 +92,19 @@ export function SectionRoadmap({ song, activeRole, onSongUpdate }: SectionRoadma return (
-
-

-

- {t("sectionRoadmapScrollHint")} +
+
+

+

+ {!onSongUpdate && ( +

+ {t("chordEditDisabledExplanation")} +

+ )} +
+ {t("sectionRoadmapScrollHint")}
{t("sectionChordLabel")} - + + { + if (!onSongUpdate) return; + handleChordEdit(section.id, role); + }} + aria-disabled={!onSongUpdate ? "true" : undefined} + > + {role.harmony.chord} + + + {onSongUpdate ? t("chordEditTitle") : t("chordEditDisabledExplanation")} + + {role.harmony.source === "user" && ( {t("harmonySourceUserBadge")} diff --git a/apps/desktop/src/locales/en/common.json b/apps/desktop/src/locales/en/common.json index d803a765e..c7d4ab595 100644 --- a/apps/desktop/src/locales/en/common.json +++ b/apps/desktop/src/locales/en/common.json @@ -59,6 +59,7 @@ "chordEditAriaLabel": "Edit chord for {roleName} in {sectionLabel}, current {chord}", "chordEditPrompt": "Enter new chord:", "chordEditTitle": "Click to edit chord", + "chordEditDisabledExplanation": "Chord editing is not available in this view.", "harmonySourceUserBadge": "User", "roleSwitcherTitle": "Role-specific View", "allRoles": "All Roles", diff --git a/apps/desktop/src/locales/ko/common.json b/apps/desktop/src/locales/ko/common.json index 0f6c6c66d..b50bbef06 100644 --- a/apps/desktop/src/locales/ko/common.json +++ b/apps/desktop/src/locales/ko/common.json @@ -59,6 +59,7 @@ "chordEditAriaLabel": "{roleName}의 {sectionLabel} 코드 수정, 현재 {chord}", "chordEditPrompt": "새 코드 입력:", "chordEditTitle": "코드 수정", + "chordEditDisabledExplanation": "이 화면에서는 코드를 수정할 수 없습니다.", "harmonySourceUserBadge": "사용자", "roleSwitcherTitle": "악기/보컬 역할", "allRoles": "전체 보기",