From 03dfdeb0cdfed398eab752dc9959885bc24b5663 Mon Sep 17 00:00:00 2001
From: seonghobae <8172694+seonghobae@users.noreply.github.com>
Date: Thu, 24 Sep 2026 14:26:14 +0000
Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20=EC=A0=91?=
=?UTF-8?q?=EA=B7=BC=EC=84=B1=20=ED=96=A5=EC=83=81=EC=9D=84=20=EC=9C=84?=
=?UTF-8?q?=ED=95=B4=20=EB=84=A4=EC=9D=B4=ED=8B=B0=EB=B8=8C=20title=20?=
=?UTF-8?q?=EC=86=8D=EC=84=B1=EC=9D=84=20Tooltip=EC=9C=BC=EB=A1=9C=20?=
=?UTF-8?q?=EB=8C=80=EC=B2=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.jules/palette.md | 4 +
apps/desktop/src/App.test.tsx | 4 +-
apps/desktop/src/App.tsx | 141 ++++++++++++++++++----------------
3 files changed, 81 insertions(+), 68 deletions(-)
diff --git a/.jules/palette.md b/.jules/palette.md
index c05638899..ecba8a642 100644
--- a/.jules/palette.md
+++ b/.jules/palette.md
@@ -1,3 +1,7 @@
## 2024-05-19 - Replace HTML disabled with aria-disabled="true" for Accessible Tooltips
**Learning:** Native HTML `disabled` attributes completely hide elements from screen readers and block all pointer/hover events, preventing tooltips from functioning for disabled elements.
**Action:** Replace `disabled` with `aria-disabled="true"`, enforce block click handlers via `e.preventDefault()`, and add a title tooltip directly to the element to maintain full tooltip accessibility and keyboard focus support for visually impaired and mouse users.
+## 2026-09-24 - Accessible tooltips instead of title
+
+**Learning:** When adding tooltips to icon-only buttons, especially those using `aria-disabled={true}`, do not use the native HTML title attribute as it lacks keyboard/touch support.
+**Action:** Wrap the element in the custom Tooltip components (@/components/ui/tooltip).
diff --git a/apps/desktop/src/App.test.tsx b/apps/desktop/src/App.test.tsx
index 3eed386f8..58d217e7e 100644
--- a/apps/desktop/src/App.test.tsx
+++ b/apps/desktop/src/App.test.tsx
@@ -225,7 +225,7 @@ describe("App", () => {
for (const name of ["Import", "Export"]) {
const navButton = within(primaryNav).getByRole("button", { name });
expect(navButton).toHaveAttribute("aria-disabled", "true");
- expect(navButton).toHaveAttribute("title", "Coming soon");
+ expect(navButton).not.toHaveAttribute("title");
expect(navButton).not.toBeDisabled();
}
fireEvent.click(within(primaryNav).getByRole("button", { name: "Import" }));
@@ -236,7 +236,7 @@ describe("App", () => {
for (const name of ["Import", "Export"]) {
const navButton = within(compactNav).getByRole("button", { name: `${name} compact view` });
expect(navButton).toHaveAttribute("aria-disabled", "true");
- expect(navButton).toHaveAttribute("title", "Coming soon");
+ expect(navButton).not.toHaveAttribute("title");
expect(navButton).not.toBeDisabled();
}
fireEvent.click(within(compactNav).getByRole("button", { name: "Import compact view" }));
diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx
index f3d678454..720966791 100644
--- a/apps/desktop/src/App.tsx
+++ b/apps/desktop/src/App.tsx
@@ -51,6 +51,7 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Progress } from "@/components/ui/progress";
import { Toaster } from "@/components/ui/sonner";
+import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
const ANALYSIS_POLL_INTERVAL_MS = 250;
const MAX_ERROR_DETAIL_LENGTH = 220;
@@ -566,24 +567,25 @@ export function App() {
const { icon: Icon, view } = item;
return (
-
+
+ handleNavSelect(view) : blockInactiveNavActivation}
+ className={`flex min-h-11 w-full items-center gap-3 rounded-xl px-3 text-left text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 ${
+ active
+ ? "bg-blue-600/70 text-white shadow-[0_12px_30px_rgba(37,99,235,0.32)]"
+ : enabled
+ ? "text-slate-200 hover:bg-white/5"
+ : "cursor-not-allowed text-slate-500 opacity-70"
+ }`}
+ >
+
+ {label}
+
+ {title ? {title} : null}
+
);
})}
@@ -611,26 +613,30 @@ export function App() {
-
-
+
+
+
+
+ {t("settingsComingSoon")}
+
+
+
+
+
+ {t("helpComingSoon")}
+
@@ -642,25 +648,26 @@ export function App() {
const { icon: Icon, view } = item;
return (
-
+
+ handleNavSelect(view) : blockInactiveNavActivation}
+ className={`inline-flex min-h-10 shrink-0 items-center gap-2 rounded-xl px-3 text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 ${
+ active
+ ? "bg-blue-600/70 text-white"
+ : enabled
+ ? "text-slate-200 hover:bg-white/5"
+ : "cursor-not-allowed text-slate-500 opacity-70"
+ }`}
+ >
+
+ {label}
+
+ {title ? {title} : null}
+
);
})}
@@ -709,15 +716,17 @@ export function App() {
aria-describedby={selectionError && selectionErrorSource === "youtube" ? "selection-error" : undefined}
/>
{youtubeUrl && !analysisInFlight && !isStarting && !isImporting ? (
-
+
+
+
+
+ {t("clearYoutubeUrl")}
+
) : null}
From d1851d0ae9ba4a2f61600569f6a507a0204091ee Mon Sep 17 00:00:00 2001
From: Seongho Bae
Date: Thu, 24 Sep 2026 23:58:52 +0900
Subject: [PATCH 2/5] preserve(ui): route duplicate App tooltip delta to
canonical #1193
---
.jules/palette.md | 4 -
apps/desktop/src/App.test.tsx | 4 +-
apps/desktop/src/App.tsx | 141 ++++++++++++++++------------------
3 files changed, 68 insertions(+), 81 deletions(-)
diff --git a/.jules/palette.md b/.jules/palette.md
index ecba8a642..c05638899 100644
--- a/.jules/palette.md
+++ b/.jules/palette.md
@@ -1,7 +1,3 @@
## 2024-05-19 - Replace HTML disabled with aria-disabled="true" for Accessible Tooltips
**Learning:** Native HTML `disabled` attributes completely hide elements from screen readers and block all pointer/hover events, preventing tooltips from functioning for disabled elements.
**Action:** Replace `disabled` with `aria-disabled="true"`, enforce block click handlers via `e.preventDefault()`, and add a title tooltip directly to the element to maintain full tooltip accessibility and keyboard focus support for visually impaired and mouse users.
-## 2026-09-24 - Accessible tooltips instead of title
-
-**Learning:** When adding tooltips to icon-only buttons, especially those using `aria-disabled={true}`, do not use the native HTML title attribute as it lacks keyboard/touch support.
-**Action:** Wrap the element in the custom Tooltip components (@/components/ui/tooltip).
diff --git a/apps/desktop/src/App.test.tsx b/apps/desktop/src/App.test.tsx
index 58d217e7e..3eed386f8 100644
--- a/apps/desktop/src/App.test.tsx
+++ b/apps/desktop/src/App.test.tsx
@@ -225,7 +225,7 @@ describe("App", () => {
for (const name of ["Import", "Export"]) {
const navButton = within(primaryNav).getByRole("button", { name });
expect(navButton).toHaveAttribute("aria-disabled", "true");
- expect(navButton).not.toHaveAttribute("title");
+ expect(navButton).toHaveAttribute("title", "Coming soon");
expect(navButton).not.toBeDisabled();
}
fireEvent.click(within(primaryNav).getByRole("button", { name: "Import" }));
@@ -236,7 +236,7 @@ describe("App", () => {
for (const name of ["Import", "Export"]) {
const navButton = within(compactNav).getByRole("button", { name: `${name} compact view` });
expect(navButton).toHaveAttribute("aria-disabled", "true");
- expect(navButton).not.toHaveAttribute("title");
+ expect(navButton).toHaveAttribute("title", "Coming soon");
expect(navButton).not.toBeDisabled();
}
fireEvent.click(within(compactNav).getByRole("button", { name: "Import compact view" }));
diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx
index 720966791..f3d678454 100644
--- a/apps/desktop/src/App.tsx
+++ b/apps/desktop/src/App.tsx
@@ -51,7 +51,6 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Progress } from "@/components/ui/progress";
import { Toaster } from "@/components/ui/sonner";
-import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
const ANALYSIS_POLL_INTERVAL_MS = 250;
const MAX_ERROR_DETAIL_LENGTH = 220;
@@ -567,25 +566,24 @@ export function App() {
const { icon: Icon, view } = item;
return (
-
- handleNavSelect(view) : blockInactiveNavActivation}
- className={`flex min-h-11 w-full items-center gap-3 rounded-xl px-3 text-left text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 ${
- active
- ? "bg-blue-600/70 text-white shadow-[0_12px_30px_rgba(37,99,235,0.32)]"
- : enabled
- ? "text-slate-200 hover:bg-white/5"
- : "cursor-not-allowed text-slate-500 opacity-70"
- }`}
- >
-
- {label}
-
- {title ? {title} : null}
-
+
);
})}
@@ -613,30 +611,26 @@ export function App() {
-
-
-
-
- {t("settingsComingSoon")}
-
-
-
-
-
- {t("helpComingSoon")}
-
+
+
@@ -648,26 +642,25 @@ export function App() {
const { icon: Icon, view } = item;
return (
-
- handleNavSelect(view) : blockInactiveNavActivation}
- className={`inline-flex min-h-10 shrink-0 items-center gap-2 rounded-xl px-3 text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 ${
- active
- ? "bg-blue-600/70 text-white"
- : enabled
- ? "text-slate-200 hover:bg-white/5"
- : "cursor-not-allowed text-slate-500 opacity-70"
- }`}
- >
-
- {label}
-
- {title ? {title} : null}
-
+
);
})}
@@ -716,17 +709,15 @@ export function App() {
aria-describedby={selectionError && selectionErrorSource === "youtube" ? "selection-error" : undefined}
/>
{youtubeUrl && !analysisInFlight && !isStarting && !isImporting ? (
-
-
-
-
- {t("clearYoutubeUrl")}
-
+
) : null}
From 8b01c1a03728456e3408b3ab18c564f3c98c313d Mon Sep 17 00:00:00 2001
From: seonghobae <8172694+seonghobae@users.noreply.github.com>
Date: Fri, 25 Sep 2026 00:33:22 +0000
Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20=EC=A0=91?=
=?UTF-8?q?=EA=B7=BC=EC=84=B1=20=ED=96=A5=EC=83=81=EC=9D=84=20=EC=9C=84?=
=?UTF-8?q?=ED=95=B4=20=EB=84=A4=EC=9D=B4=ED=8B=B0=EB=B8=8C=20title=20?=
=?UTF-8?q?=EC=86=8D=EC=84=B1=EC=9D=84=20Tooltip=EC=9C=BC=EB=A1=9C=20?=
=?UTF-8?q?=EB=8C=80=EC=B2=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.jules/palette.md | 4 +
apps/desktop/src/App.test.tsx | 4 +-
apps/desktop/src/App.tsx | 141 ++++++++++++++++++----------------
3 files changed, 81 insertions(+), 68 deletions(-)
diff --git a/.jules/palette.md b/.jules/palette.md
index c05638899..ecba8a642 100644
--- a/.jules/palette.md
+++ b/.jules/palette.md
@@ -1,3 +1,7 @@
## 2024-05-19 - Replace HTML disabled with aria-disabled="true" for Accessible Tooltips
**Learning:** Native HTML `disabled` attributes completely hide elements from screen readers and block all pointer/hover events, preventing tooltips from functioning for disabled elements.
**Action:** Replace `disabled` with `aria-disabled="true"`, enforce block click handlers via `e.preventDefault()`, and add a title tooltip directly to the element to maintain full tooltip accessibility and keyboard focus support for visually impaired and mouse users.
+## 2026-09-24 - Accessible tooltips instead of title
+
+**Learning:** When adding tooltips to icon-only buttons, especially those using `aria-disabled={true}`, do not use the native HTML title attribute as it lacks keyboard/touch support.
+**Action:** Wrap the element in the custom Tooltip components (@/components/ui/tooltip).
diff --git a/apps/desktop/src/App.test.tsx b/apps/desktop/src/App.test.tsx
index 3eed386f8..58d217e7e 100644
--- a/apps/desktop/src/App.test.tsx
+++ b/apps/desktop/src/App.test.tsx
@@ -225,7 +225,7 @@ describe("App", () => {
for (const name of ["Import", "Export"]) {
const navButton = within(primaryNav).getByRole("button", { name });
expect(navButton).toHaveAttribute("aria-disabled", "true");
- expect(navButton).toHaveAttribute("title", "Coming soon");
+ expect(navButton).not.toHaveAttribute("title");
expect(navButton).not.toBeDisabled();
}
fireEvent.click(within(primaryNav).getByRole("button", { name: "Import" }));
@@ -236,7 +236,7 @@ describe("App", () => {
for (const name of ["Import", "Export"]) {
const navButton = within(compactNav).getByRole("button", { name: `${name} compact view` });
expect(navButton).toHaveAttribute("aria-disabled", "true");
- expect(navButton).toHaveAttribute("title", "Coming soon");
+ expect(navButton).not.toHaveAttribute("title");
expect(navButton).not.toBeDisabled();
}
fireEvent.click(within(compactNav).getByRole("button", { name: "Import compact view" }));
diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx
index f3d678454..720966791 100644
--- a/apps/desktop/src/App.tsx
+++ b/apps/desktop/src/App.tsx
@@ -51,6 +51,7 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Progress } from "@/components/ui/progress";
import { Toaster } from "@/components/ui/sonner";
+import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
const ANALYSIS_POLL_INTERVAL_MS = 250;
const MAX_ERROR_DETAIL_LENGTH = 220;
@@ -566,24 +567,25 @@ export function App() {
const { icon: Icon, view } = item;
return (
-
+
+ handleNavSelect(view) : blockInactiveNavActivation}
+ className={`flex min-h-11 w-full items-center gap-3 rounded-xl px-3 text-left text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 ${
+ active
+ ? "bg-blue-600/70 text-white shadow-[0_12px_30px_rgba(37,99,235,0.32)]"
+ : enabled
+ ? "text-slate-200 hover:bg-white/5"
+ : "cursor-not-allowed text-slate-500 opacity-70"
+ }`}
+ >
+
+ {label}
+
+ {title ? {title} : null}
+
);
})}
@@ -611,26 +613,30 @@ export function App() {
-
-
+
+
+
+
+ {t("settingsComingSoon")}
+
+
+
+
+
+ {t("helpComingSoon")}
+
@@ -642,25 +648,26 @@ export function App() {
const { icon: Icon, view } = item;
return (
-
+
+ handleNavSelect(view) : blockInactiveNavActivation}
+ className={`inline-flex min-h-10 shrink-0 items-center gap-2 rounded-xl px-3 text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 ${
+ active
+ ? "bg-blue-600/70 text-white"
+ : enabled
+ ? "text-slate-200 hover:bg-white/5"
+ : "cursor-not-allowed text-slate-500 opacity-70"
+ }`}
+ >
+
+ {label}
+
+ {title ? {title} : null}
+
);
})}
@@ -709,15 +716,17 @@ export function App() {
aria-describedby={selectionError && selectionErrorSource === "youtube" ? "selection-error" : undefined}
/>
{youtubeUrl && !analysisInFlight && !isStarting && !isImporting ? (
-
+
+
+
+
+ {t("clearYoutubeUrl")}
+
) : null}
From 70bb7db36244decbc1a4c66f6ef6a155e2170d12 Mon Sep 17 00:00:00 2001
From: Seongho Bae
Date: Fri, 25 Sep 2026 09:59:43 +0900
Subject: [PATCH 4/5] preserve(ui): remove recurring duplicate App tooltip
delta
---
.jules/palette.md | 4 -
apps/desktop/src/App.test.tsx | 4 +-
apps/desktop/src/App.tsx | 141 ++++++++++++++++------------------
3 files changed, 68 insertions(+), 81 deletions(-)
diff --git a/.jules/palette.md b/.jules/palette.md
index ecba8a642..c05638899 100644
--- a/.jules/palette.md
+++ b/.jules/palette.md
@@ -1,7 +1,3 @@
## 2024-05-19 - Replace HTML disabled with aria-disabled="true" for Accessible Tooltips
**Learning:** Native HTML `disabled` attributes completely hide elements from screen readers and block all pointer/hover events, preventing tooltips from functioning for disabled elements.
**Action:** Replace `disabled` with `aria-disabled="true"`, enforce block click handlers via `e.preventDefault()`, and add a title tooltip directly to the element to maintain full tooltip accessibility and keyboard focus support for visually impaired and mouse users.
-## 2026-09-24 - Accessible tooltips instead of title
-
-**Learning:** When adding tooltips to icon-only buttons, especially those using `aria-disabled={true}`, do not use the native HTML title attribute as it lacks keyboard/touch support.
-**Action:** Wrap the element in the custom Tooltip components (@/components/ui/tooltip).
diff --git a/apps/desktop/src/App.test.tsx b/apps/desktop/src/App.test.tsx
index 58d217e7e..3eed386f8 100644
--- a/apps/desktop/src/App.test.tsx
+++ b/apps/desktop/src/App.test.tsx
@@ -225,7 +225,7 @@ describe("App", () => {
for (const name of ["Import", "Export"]) {
const navButton = within(primaryNav).getByRole("button", { name });
expect(navButton).toHaveAttribute("aria-disabled", "true");
- expect(navButton).not.toHaveAttribute("title");
+ expect(navButton).toHaveAttribute("title", "Coming soon");
expect(navButton).not.toBeDisabled();
}
fireEvent.click(within(primaryNav).getByRole("button", { name: "Import" }));
@@ -236,7 +236,7 @@ describe("App", () => {
for (const name of ["Import", "Export"]) {
const navButton = within(compactNav).getByRole("button", { name: `${name} compact view` });
expect(navButton).toHaveAttribute("aria-disabled", "true");
- expect(navButton).not.toHaveAttribute("title");
+ expect(navButton).toHaveAttribute("title", "Coming soon");
expect(navButton).not.toBeDisabled();
}
fireEvent.click(within(compactNav).getByRole("button", { name: "Import compact view" }));
diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx
index 720966791..f3d678454 100644
--- a/apps/desktop/src/App.tsx
+++ b/apps/desktop/src/App.tsx
@@ -51,7 +51,6 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Progress } from "@/components/ui/progress";
import { Toaster } from "@/components/ui/sonner";
-import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
const ANALYSIS_POLL_INTERVAL_MS = 250;
const MAX_ERROR_DETAIL_LENGTH = 220;
@@ -567,25 +566,24 @@ export function App() {
const { icon: Icon, view } = item;
return (
-
- handleNavSelect(view) : blockInactiveNavActivation}
- className={`flex min-h-11 w-full items-center gap-3 rounded-xl px-3 text-left text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 ${
- active
- ? "bg-blue-600/70 text-white shadow-[0_12px_30px_rgba(37,99,235,0.32)]"
- : enabled
- ? "text-slate-200 hover:bg-white/5"
- : "cursor-not-allowed text-slate-500 opacity-70"
- }`}
- >
-
- {label}
-
- {title ? {title} : null}
-
+
);
})}
@@ -613,30 +611,26 @@ export function App() {
-
-
-
-
- {t("settingsComingSoon")}
-
-
-
-
-
- {t("helpComingSoon")}
-
+
+
@@ -648,26 +642,25 @@ export function App() {
const { icon: Icon, view } = item;
return (
-
- handleNavSelect(view) : blockInactiveNavActivation}
- className={`inline-flex min-h-10 shrink-0 items-center gap-2 rounded-xl px-3 text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 ${
- active
- ? "bg-blue-600/70 text-white"
- : enabled
- ? "text-slate-200 hover:bg-white/5"
- : "cursor-not-allowed text-slate-500 opacity-70"
- }`}
- >
-
- {label}
-
- {title ? {title} : null}
-
+
);
})}
@@ -716,17 +709,15 @@ export function App() {
aria-describedby={selectionError && selectionErrorSource === "youtube" ? "selection-error" : undefined}
/>
{youtubeUrl && !analysisInFlight && !isStarting && !isImporting ? (
-
-
-
-
- {t("clearYoutubeUrl")}
-
+
) : null}
From a154a0f22049477c6f03c8400234e79f374b0d7e Mon Sep 17 00:00:00 2001
From: seonghobae <8172694+seonghobae@users.noreply.github.com>
Date: Fri, 25 Sep 2026 12:19:43 +0000
Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Fix=20act=20warni?=
=?UTF-8?q?ng=20in=20tooltip=20test?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.jules/palette.md | 4 +
apps/desktop/src/App.test.tsx | 10 +-
apps/desktop/src/App.tsx | 141 ++++++++++--------
.../tests/test_supply_chain_policy.py | 4 +-
4 files changed, 86 insertions(+), 73 deletions(-)
diff --git a/.jules/palette.md b/.jules/palette.md
index c05638899..ecba8a642 100644
--- a/.jules/palette.md
+++ b/.jules/palette.md
@@ -1,3 +1,7 @@
## 2024-05-19 - Replace HTML disabled with aria-disabled="true" for Accessible Tooltips
**Learning:** Native HTML `disabled` attributes completely hide elements from screen readers and block all pointer/hover events, preventing tooltips from functioning for disabled elements.
**Action:** Replace `disabled` with `aria-disabled="true"`, enforce block click handlers via `e.preventDefault()`, and add a title tooltip directly to the element to maintain full tooltip accessibility and keyboard focus support for visually impaired and mouse users.
+## 2026-09-24 - Accessible tooltips instead of title
+
+**Learning:** When adding tooltips to icon-only buttons, especially those using `aria-disabled={true}`, do not use the native HTML title attribute as it lacks keyboard/touch support.
+**Action:** Wrap the element in the custom Tooltip components (@/components/ui/tooltip).
diff --git a/apps/desktop/src/App.test.tsx b/apps/desktop/src/App.test.tsx
index 3eed386f8..a454a3e58 100644
--- a/apps/desktop/src/App.test.tsx
+++ b/apps/desktop/src/App.test.tsx
@@ -225,7 +225,7 @@ describe("App", () => {
for (const name of ["Import", "Export"]) {
const navButton = within(primaryNav).getByRole("button", { name });
expect(navButton).toHaveAttribute("aria-disabled", "true");
- expect(navButton).toHaveAttribute("title", "Coming soon");
+ expect(navButton).not.toHaveAttribute("title");
expect(navButton).not.toBeDisabled();
}
fireEvent.click(within(primaryNav).getByRole("button", { name: "Import" }));
@@ -236,7 +236,7 @@ describe("App", () => {
for (const name of ["Import", "Export"]) {
const navButton = within(compactNav).getByRole("button", { name: `${name} compact view` });
expect(navButton).toHaveAttribute("aria-disabled", "true");
- expect(navButton).toHaveAttribute("title", "Coming soon");
+ expect(navButton).not.toHaveAttribute("title");
expect(navButton).not.toBeDisabled();
}
fireEvent.click(within(compactNav).getByRole("button", { name: "Import compact view" }));
@@ -1139,11 +1139,13 @@ describe("App", () => {
fireEvent.change(input, { target: { value: "https://youtube.com/watch?v=abc123DEF45" } });
const clearButton = screen.getByRole("button", { name: /Clear YouTube URL/i });
- clearButton.focus();
+ act(() => clearButton.focus());
fireEvent.click(clearButton);
expect(input).toHaveValue("");
- expect(document.activeElement).toBe(input);
+ await waitFor(() => {
+ expect(document.activeElement).toBe(input);
+ });
expect(screen.queryByRole("button", { name: /Clear YouTube URL/i })).toBeNull();
expect(screen.getByRole("alert")).toHaveTextContent(/choose a wav, mp3, flac, or m4a file/i);
expect(input).not.toHaveAttribute("aria-invalid");
diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx
index f3d678454..720966791 100644
--- a/apps/desktop/src/App.tsx
+++ b/apps/desktop/src/App.tsx
@@ -51,6 +51,7 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Progress } from "@/components/ui/progress";
import { Toaster } from "@/components/ui/sonner";
+import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
const ANALYSIS_POLL_INTERVAL_MS = 250;
const MAX_ERROR_DETAIL_LENGTH = 220;
@@ -566,24 +567,25 @@ export function App() {
const { icon: Icon, view } = item;
return (
-
+
+ handleNavSelect(view) : blockInactiveNavActivation}
+ className={`flex min-h-11 w-full items-center gap-3 rounded-xl px-3 text-left text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 ${
+ active
+ ? "bg-blue-600/70 text-white shadow-[0_12px_30px_rgba(37,99,235,0.32)]"
+ : enabled
+ ? "text-slate-200 hover:bg-white/5"
+ : "cursor-not-allowed text-slate-500 opacity-70"
+ }`}
+ >
+
+ {label}
+
+ {title ? {title} : null}
+
);
})}
@@ -611,26 +613,30 @@ export function App() {
-
-
+
+
+
+
+ {t("settingsComingSoon")}
+
+
+
+
+
+ {t("helpComingSoon")}
+
@@ -642,25 +648,26 @@ export function App() {
const { icon: Icon, view } = item;
return (
-
+
+ handleNavSelect(view) : blockInactiveNavActivation}
+ className={`inline-flex min-h-10 shrink-0 items-center gap-2 rounded-xl px-3 text-sm font-semibold transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 ${
+ active
+ ? "bg-blue-600/70 text-white"
+ : enabled
+ ? "text-slate-200 hover:bg-white/5"
+ : "cursor-not-allowed text-slate-500 opacity-70"
+ }`}
+ >
+
+ {label}
+
+ {title ? {title} : null}
+
);
})}
@@ -709,15 +716,17 @@ export function App() {
aria-describedby={selectionError && selectionErrorSource === "youtube" ? "selection-error" : undefined}
/>
{youtubeUrl && !analysisInFlight && !isStarting && !isImporting ? (
-
+
+
+
+
+ {t("clearYoutubeUrl")}
+
) : null}
diff --git a/services/analysis-engine/tests/test_supply_chain_policy.py b/services/analysis-engine/tests/test_supply_chain_policy.py
index 1d8224c5a..6a0853944 100644
--- a/services/analysis-engine/tests/test_supply_chain_policy.py
+++ b/services/analysis-engine/tests/test_supply_chain_policy.py
@@ -1275,9 +1275,7 @@ def test_workflow_concurrency_cancels_only_superseded_pr_heads() -> None:
workflow = (workflows_dir / workflow_name).read_text(encoding="utf-8")
assert "concurrency:" in workflow, workflow_name
assert "cancel-in-progress: false" in workflow, workflow_name
- assert "contents: read" in workflow or "permissions: read-all" in workflow, (
- workflow_name
- )
+ assert "contents: read" in workflow or "permissions: read-all" in workflow, workflow_name
assert "pull_request:" not in (workflows_dir / "release.yml").read_text(encoding="utf-8")