);
diff --git a/ui/src/components/projects/BuilderTabStrip.test.tsx b/ui/src/components/projects/BuilderTabStrip.test.tsx
index ea6c9dbf..691e5ea0 100644
--- a/ui/src/components/projects/BuilderTabStrip.test.tsx
+++ b/ui/src/components/projects/BuilderTabStrip.test.tsx
@@ -187,4 +187,28 @@ describe("BuilderTabStrip", () => {
expect(nav?.className).toContain("gap-6");
expect(nav?.className).toContain("pl-6");
});
+
+ it("supports horizontal scroll with scroll-snap on mobile (Phase 15)", () => {
+ // The mobile treatment is expressed as Tailwind classes on the strip
+ // itself; we verify the classes are present rather than measuring
+ // scrollWidth (jsdom does not lay out flex children).
+ renderStrip({
+ projectRef: "abc",
+ activeTab: "overview",
+ hasMultipleAgents: true,
+ });
+ const nav = container.querySelector('[data-testid="builder-tab-strip"]');
+ // Horizontal scroll enabled on mobile, reset on md+.
+ expect(nav?.className).toContain("overflow-x-auto");
+ expect(nav?.className).toContain("md:overflow-visible");
+ // Scroll snap per tab on mobile.
+ expect(nav?.className).toContain("snap-x");
+ expect(nav?.className).toContain("snap-mandatory");
+ // Tabs do not shrink so they stay fixed width while the container scrolls.
+ const firstTab = container.querySelector(
+ "[data-testid='builder-tab-overview']",
+ );
+ expect(firstTab?.className).toContain("shrink-0");
+ expect(firstTab?.className).toContain("snap-start");
+ });
});
diff --git a/ui/src/components/projects/BuilderTabStrip.tsx b/ui/src/components/projects/BuilderTabStrip.tsx
index 0be5a015..deb99fd6 100644
--- a/ui/src/components/projects/BuilderTabStrip.tsx
+++ b/ui/src/components/projects/BuilderTabStrip.tsx
@@ -121,6 +121,9 @@ function BuilderTabLink({
// Base type: uppercase 14px Inter 600 tracking-[0.1em]
"relative inline-flex h-10 items-center text-[14px] font-semibold uppercase tracking-[0.1em]",
"no-underline transition-colors",
+ // Mobile (Phase 15): do not shrink tabs and snap each tab to the
+ // scroll container's left edge for a satisfying swipe feel.
+ "shrink-0 snap-start",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background",
// Active: volt text + 2px volt bottom border
active
@@ -144,7 +147,22 @@ export function BuilderTabStrip({
);
}