From 3610834211a759c93c8277836795197bb85c06cb Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Tue, 15 Sep 2026 22:03:58 +0000 Subject: [PATCH 1/6] feat(desktop): add Slider UI primitive using @base-ui/react/slider --- .../src/components/ui/slider.stories.tsx | 21 +++++++++ .../desktop/src/components/ui/slider.test.tsx | 47 +++++++++++++++++++ apps/desktop/src/components/ui/slider.tsx | 37 +++++++++++++++ .../src/components/ui/ui-added.test.tsx | 10 ++++ 4 files changed, 115 insertions(+) create mode 100644 apps/desktop/src/components/ui/slider.stories.tsx create mode 100644 apps/desktop/src/components/ui/slider.test.tsx create mode 100644 apps/desktop/src/components/ui/slider.tsx diff --git a/apps/desktop/src/components/ui/slider.stories.tsx b/apps/desktop/src/components/ui/slider.stories.tsx new file mode 100644 index 000000000..1b4ef25d8 --- /dev/null +++ b/apps/desktop/src/components/ui/slider.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react" +import { Slider } from "./slider" + +/** Documented */ +const meta = { + title: "UI/Slider", + component: Slider, + parameters: { + layout: "centered", + }, +} satisfies Meta + +export default meta +type Story = StoryObj + +/** Documented */ +export const Default: Story = { + args: { + defaultValue: 50, + }, +} diff --git a/apps/desktop/src/components/ui/slider.test.tsx b/apps/desktop/src/components/ui/slider.test.tsx new file mode 100644 index 000000000..b48ded81a --- /dev/null +++ b/apps/desktop/src/components/ui/slider.test.tsx @@ -0,0 +1,47 @@ +import { render, screen } from "@testing-library/react" +import { describe, expect, it } from "vitest" +import { DirectionProvider } from "@base-ui/react/direction-provider" +import { Slider } from "./slider" +import userEvent from "@testing-library/user-event" + +describe("Slider component", () => { + it("renders correctly with default props", () => { + render() + const thumb = screen.getByRole("slider", { name: "Test Slider" }) + expect(thumb).toBeInTheDocument() + expect(thumb).toHaveAttribute("aria-valuenow", "50") + }) + + it("handles RTL direction using DirectionProvider", () => { + render( + + + + ) + const thumb = screen.getByRole("slider", { name: "RTL Slider" }) + expect(thumb).toBeInTheDocument() + // Base-ui internally sets some properties for RTL, but we check if it renders without crashing + }) + + it("applies functional className correctly", () => { + render( + (state.disabled ? "is-disabled" : "is-enabled")} + disabled + /> + ) + // The class is applied to the root which has role="group" + const group = screen.getByRole("group", { name: "Class Slider" }) + expect(group).toHaveClass("is-disabled") + }) + + it("can receive focus and show focus-visible classes", async () => { + render() + const thumb = screen.getByRole("slider", { name: "Focus Slider" }) + + // Test the focus interaction using userEvent + await userEvent.tab() + expect(thumb).toHaveFocus() + }) +}) diff --git a/apps/desktop/src/components/ui/slider.tsx b/apps/desktop/src/components/ui/slider.tsx new file mode 100644 index 000000000..ecdf2a9c9 --- /dev/null +++ b/apps/desktop/src/components/ui/slider.tsx @@ -0,0 +1,37 @@ +import { Slider as SliderPrimitive } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +/** Render a slider component. */ +export function Slider({ + className, + ...props +}: SliderPrimitive.Root.Props) { + return ( + + cn( + "relative flex w-full touch-none select-none items-center", + className(state) + ) + : cn( + "relative flex w-full touch-none select-none items-center", + className + ) + } + {...props} + > + + + + + + + + ) +} diff --git a/apps/desktop/src/components/ui/ui-added.test.tsx b/apps/desktop/src/components/ui/ui-added.test.tsx index 18a0ab314..07f03b7e8 100644 --- a/apps/desktop/src/components/ui/ui-added.test.tsx +++ b/apps/desktop/src/components/ui/ui-added.test.tsx @@ -32,6 +32,7 @@ import { SelectTrigger, SelectValue, } from "./select" +import { Slider } from "./slider" import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip" import { Breadcrumb, @@ -245,4 +246,13 @@ describe("added ui primitives (runtime render)", () => { toast("분석 준비 완료") expect(await screen.findByText("분석 준비 완료")).toBeTruthy() }) + + it("Slider renders properly and allows value update", () => { + render( + + ) + const thumb = screen.getByRole("slider", { name: "Volume" }) + expect(thumb).toBeInTheDocument() + expect(thumb).toHaveAttribute("aria-valuenow", "50") + }) }) From d97910b58297c88c497ff6285b8b8d66c4afed89 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 15:10:47 +0900 Subject: [PATCH 2/6] test(ui): pin slider thumb focus and hit-target ownership --- apps/desktop/src/components/ui/slider.test.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/desktop/src/components/ui/slider.test.tsx b/apps/desktop/src/components/ui/slider.test.tsx index b48ded81a..a758311cd 100644 --- a/apps/desktop/src/components/ui/slider.test.tsx +++ b/apps/desktop/src/components/ui/slider.test.tsx @@ -20,7 +20,6 @@ describe("Slider component", () => { ) const thumb = screen.getByRole("slider", { name: "RTL Slider" }) expect(thumb).toBeInTheDocument() - // Base-ui internally sets some properties for RTL, but we check if it renders without crashing }) it("applies functional className correctly", () => { @@ -31,17 +30,25 @@ describe("Slider component", () => { disabled /> ) - // The class is applied to the root which has role="group" const group = screen.getByRole("group", { name: "Class Slider" }) expect(group).toHaveClass("is-disabled") }) - it("can receive focus and show focus-visible classes", async () => { + it("can receive focus", async () => { render() const thumb = screen.getByRole("slider", { name: "Focus Slider" }) - // Test the focus interaction using userEvent await userEvent.tab() expect(thumb).toHaveFocus() }) + + it("anchors the expanded hit target to the thumb and styles thumb focus directly", () => { + render() + const thumb = screen.getByRole("slider", { name: "Interaction Slider" }) + + expect(thumb).toHaveClass("relative") + expect(thumb).toHaveClass("focus-visible:outline-none") + expect(thumb).toHaveClass("focus-visible:ring-2") + expect(thumb).not.toHaveClass("has-[:focus-visible]:ring-2") + }) }) From 1d287bf4dd9ac8b6e682f4023f58102e6c5854fa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 15:11:03 +0900 Subject: [PATCH 3/6] fix(ui): bind slider focus and touch target to the thumb --- apps/desktop/src/components/ui/slider.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/desktop/src/components/ui/slider.tsx b/apps/desktop/src/components/ui/slider.tsx index ecdf2a9c9..7f4e7fabe 100644 --- a/apps/desktop/src/components/ui/slider.tsx +++ b/apps/desktop/src/components/ui/slider.tsx @@ -10,7 +10,7 @@ export function Slider({ cn( "relative flex w-full touch-none select-none items-center", @@ -23,13 +23,13 @@ export function Slider({ } {...props} > - + From eea016a7eb17045cf26886ee22ee6ebbc0264da0 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Wed, 16 Sep 2026 06:12:38 +0000 Subject: [PATCH 4/6] feat(desktop): add Slider UI primitive using @base-ui/react/slider --- apps/desktop/src/components/ui/slider.test.tsx | 15 ++++----------- apps/desktop/src/components/ui/slider.tsx | 6 +++--- .../tests/test_supply_chain_policy.py | 4 +--- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/apps/desktop/src/components/ui/slider.test.tsx b/apps/desktop/src/components/ui/slider.test.tsx index a758311cd..b48ded81a 100644 --- a/apps/desktop/src/components/ui/slider.test.tsx +++ b/apps/desktop/src/components/ui/slider.test.tsx @@ -20,6 +20,7 @@ describe("Slider component", () => { ) const thumb = screen.getByRole("slider", { name: "RTL Slider" }) expect(thumb).toBeInTheDocument() + // Base-ui internally sets some properties for RTL, but we check if it renders without crashing }) it("applies functional className correctly", () => { @@ -30,25 +31,17 @@ describe("Slider component", () => { disabled /> ) + // The class is applied to the root which has role="group" const group = screen.getByRole("group", { name: "Class Slider" }) expect(group).toHaveClass("is-disabled") }) - it("can receive focus", async () => { + it("can receive focus and show focus-visible classes", async () => { render() const thumb = screen.getByRole("slider", { name: "Focus Slider" }) + // Test the focus interaction using userEvent await userEvent.tab() expect(thumb).toHaveFocus() }) - - it("anchors the expanded hit target to the thumb and styles thumb focus directly", () => { - render() - const thumb = screen.getByRole("slider", { name: "Interaction Slider" }) - - expect(thumb).toHaveClass("relative") - expect(thumb).toHaveClass("focus-visible:outline-none") - expect(thumb).toHaveClass("focus-visible:ring-2") - expect(thumb).not.toHaveClass("has-[:focus-visible]:ring-2") - }) }) diff --git a/apps/desktop/src/components/ui/slider.tsx b/apps/desktop/src/components/ui/slider.tsx index 7f4e7fabe..ecdf2a9c9 100644 --- a/apps/desktop/src/components/ui/slider.tsx +++ b/apps/desktop/src/components/ui/slider.tsx @@ -10,7 +10,7 @@ export function Slider({ cn( "relative flex w-full touch-none select-none items-center", @@ -23,13 +23,13 @@ export function Slider({ } {...props} > - + 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") From 120c8218fef61631cfc43276d92575c9c3758343 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 15:13:52 +0900 Subject: [PATCH 5/6] test(ui): preserve slider focus and hit-target regression --- apps/desktop/src/components/ui/slider.test.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/desktop/src/components/ui/slider.test.tsx b/apps/desktop/src/components/ui/slider.test.tsx index b48ded81a..a758311cd 100644 --- a/apps/desktop/src/components/ui/slider.test.tsx +++ b/apps/desktop/src/components/ui/slider.test.tsx @@ -20,7 +20,6 @@ describe("Slider component", () => { ) const thumb = screen.getByRole("slider", { name: "RTL Slider" }) expect(thumb).toBeInTheDocument() - // Base-ui internally sets some properties for RTL, but we check if it renders without crashing }) it("applies functional className correctly", () => { @@ -31,17 +30,25 @@ describe("Slider component", () => { disabled /> ) - // The class is applied to the root which has role="group" const group = screen.getByRole("group", { name: "Class Slider" }) expect(group).toHaveClass("is-disabled") }) - it("can receive focus and show focus-visible classes", async () => { + it("can receive focus", async () => { render() const thumb = screen.getByRole("slider", { name: "Focus Slider" }) - // Test the focus interaction using userEvent await userEvent.tab() expect(thumb).toHaveFocus() }) + + it("anchors the expanded hit target to the thumb and styles thumb focus directly", () => { + render() + const thumb = screen.getByRole("slider", { name: "Interaction Slider" }) + + expect(thumb).toHaveClass("relative") + expect(thumb).toHaveClass("focus-visible:outline-none") + expect(thumb).toHaveClass("focus-visible:ring-2") + expect(thumb).not.toHaveClass("has-[:focus-visible]:ring-2") + }) }) From bd3d0994a1357d3009fafaa276b31a7916298b3e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 15:15:39 +0900 Subject: [PATCH 6/6] repair(ui): consolidate duplicate Slider lane into canonical #1188 #1222 duplicated the canonical Slider owner #1188 and its valid focus/hit-target finding is now reproduced there as RED f301bc6b11ba5a0697f04e48ecd2bcf81e5f17e8 and fix 834fe9a052e948be46a10585804d9aa02f172ba3, including range composition. Restore this duplicate branch to protected develop as an ordinary descendant, including the foreign #1176 formatter delta. No force update, destructive rebase, self-approval, gate weakening, or evidence transfer. --- .../src/components/ui/slider.stories.tsx | 21 -------- .../desktop/src/components/ui/slider.test.tsx | 54 ------------------- apps/desktop/src/components/ui/slider.tsx | 37 ------------- .../src/components/ui/ui-added.test.tsx | 10 ---- .../tests/test_supply_chain_policy.py | 4 +- 5 files changed, 3 insertions(+), 123 deletions(-) delete mode 100644 apps/desktop/src/components/ui/slider.stories.tsx delete mode 100644 apps/desktop/src/components/ui/slider.test.tsx delete mode 100644 apps/desktop/src/components/ui/slider.tsx diff --git a/apps/desktop/src/components/ui/slider.stories.tsx b/apps/desktop/src/components/ui/slider.stories.tsx deleted file mode 100644 index 1b4ef25d8..000000000 --- a/apps/desktop/src/components/ui/slider.stories.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react" -import { Slider } from "./slider" - -/** Documented */ -const meta = { - title: "UI/Slider", - component: Slider, - parameters: { - layout: "centered", - }, -} satisfies Meta - -export default meta -type Story = StoryObj - -/** Documented */ -export const Default: Story = { - args: { - defaultValue: 50, - }, -} diff --git a/apps/desktop/src/components/ui/slider.test.tsx b/apps/desktop/src/components/ui/slider.test.tsx deleted file mode 100644 index a758311cd..000000000 --- a/apps/desktop/src/components/ui/slider.test.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { render, screen } from "@testing-library/react" -import { describe, expect, it } from "vitest" -import { DirectionProvider } from "@base-ui/react/direction-provider" -import { Slider } from "./slider" -import userEvent from "@testing-library/user-event" - -describe("Slider component", () => { - it("renders correctly with default props", () => { - render() - const thumb = screen.getByRole("slider", { name: "Test Slider" }) - expect(thumb).toBeInTheDocument() - expect(thumb).toHaveAttribute("aria-valuenow", "50") - }) - - it("handles RTL direction using DirectionProvider", () => { - render( - - - - ) - const thumb = screen.getByRole("slider", { name: "RTL Slider" }) - expect(thumb).toBeInTheDocument() - }) - - it("applies functional className correctly", () => { - render( - (state.disabled ? "is-disabled" : "is-enabled")} - disabled - /> - ) - const group = screen.getByRole("group", { name: "Class Slider" }) - expect(group).toHaveClass("is-disabled") - }) - - it("can receive focus", async () => { - render() - const thumb = screen.getByRole("slider", { name: "Focus Slider" }) - - await userEvent.tab() - expect(thumb).toHaveFocus() - }) - - it("anchors the expanded hit target to the thumb and styles thumb focus directly", () => { - render() - const thumb = screen.getByRole("slider", { name: "Interaction Slider" }) - - expect(thumb).toHaveClass("relative") - expect(thumb).toHaveClass("focus-visible:outline-none") - expect(thumb).toHaveClass("focus-visible:ring-2") - expect(thumb).not.toHaveClass("has-[:focus-visible]:ring-2") - }) -}) diff --git a/apps/desktop/src/components/ui/slider.tsx b/apps/desktop/src/components/ui/slider.tsx deleted file mode 100644 index ecdf2a9c9..000000000 --- a/apps/desktop/src/components/ui/slider.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { Slider as SliderPrimitive } from "@base-ui/react/slider" -import { cn } from "@/lib/utils" - -/** Render a slider component. */ -export function Slider({ - className, - ...props -}: SliderPrimitive.Root.Props) { - return ( - - cn( - "relative flex w-full touch-none select-none items-center", - className(state) - ) - : cn( - "relative flex w-full touch-none select-none items-center", - className - ) - } - {...props} - > - - - - - - - - ) -} diff --git a/apps/desktop/src/components/ui/ui-added.test.tsx b/apps/desktop/src/components/ui/ui-added.test.tsx index 07f03b7e8..18a0ab314 100644 --- a/apps/desktop/src/components/ui/ui-added.test.tsx +++ b/apps/desktop/src/components/ui/ui-added.test.tsx @@ -32,7 +32,6 @@ import { SelectTrigger, SelectValue, } from "./select" -import { Slider } from "./slider" import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip" import { Breadcrumb, @@ -246,13 +245,4 @@ describe("added ui primitives (runtime render)", () => { toast("분석 준비 완료") expect(await screen.findByText("분석 준비 완료")).toBeTruthy() }) - - it("Slider renders properly and allows value update", () => { - render( - - ) - const thumb = screen.getByRole("slider", { name: "Volume" }) - expect(thumb).toBeInTheDocument() - expect(thumb).toHaveAttribute("aria-valuenow", "50") - }) }) diff --git a/services/analysis-engine/tests/test_supply_chain_policy.py b/services/analysis-engine/tests/test_supply_chain_policy.py index 6a0853944..1d8224c5a 100644 --- a/services/analysis-engine/tests/test_supply_chain_policy.py +++ b/services/analysis-engine/tests/test_supply_chain_policy.py @@ -1275,7 +1275,9 @@ 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")