From 5366ce1058c7056909a76a1b4ed031e24dd67e6f Mon Sep 17 00:00:00 2001 From: RealZST Date: Sun, 18 Oct 2026 20:46:27 +0800 Subject: [PATCH 1/6] fix(onboarding): wrap the agent row into two rows on narrow windows With 17 agents the welcome row is 908px wide, wider than the desktop window's 900px minimum, so both ends were cut off. The row now keeps a single line while the viewport leaves 40px on each side and otherwise splits into two even rows (9 + 8), computed from AGENT_ORDER so new agents need no further change. Icons stay 44px. Co-Authored-By: Claude Fable 5.1 --- src/components/onboarding/onboarding.tsx | 36 ++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/components/onboarding/onboarding.tsx b/src/components/onboarding/onboarding.tsx index 42caa84e..f8e5c284 100644 --- a/src/components/onboarding/onboarding.tsx +++ b/src/components/onboarding/onboarding.tsx @@ -296,6 +296,27 @@ const SCATTER_POSITIONS: Record< pi: { x: -80, y: 160, r: -18 }, }; +const MASCOT_SIZE = 44; +const MASCOT_GAP = 10; +const MASCOT_ROW_GAP = 14; +// Breathing room the single-row layout must keep on each side of the viewport. +const ROW_SIDE_MARGIN = 40; + +function mascotRowWidth(count: number): number { + return count * MASCOT_SIZE + (count - 1) * MASCOT_GAP; +} + +// The agent row stays on one line while the viewport is wide enough for it +// plus the side margins; narrower than that it splits into two even rows +// (ceil(n/2) + floor(n/2)) so the second row never holds a couple of orphans. +// `clamp()` does the switch without a resize listener: the middle term is +// hugely positive above the threshold (clamped to the full width) and hugely +// negative below it (clamped to the half width). +const FULL_ROW_WIDTH = mascotRowWidth(AGENT_ORDER.length); +const HALF_ROW_WIDTH = mascotRowWidth(Math.ceil(AGENT_ORDER.length / 2)); +const SINGLE_ROW_MIN_VIEWPORT = FULL_ROW_WIDTH + 2 * ROW_SIDE_MARGIN; +const AGENT_ROW_WIDTH = `clamp(${HALF_ROW_WIDTH}px, (100vw - ${SINGLE_ROW_MIN_VIEWPORT}px) * 9999, ${FULL_ROW_WIDTH}px)`; + function HandAnnotation({ type, delay = 2400, @@ -348,8 +369,17 @@ function StepWelcome() { return (
-
-
+ {/* The step column is narrower than the full row; `justify-center` on + the wrapper lets the fixed-width row overflow it evenly on both sides. */} +
+
{AGENT_ORDER.map((name, i) => { const s = SCATTER_POSITIONS[name]; return ( @@ -366,7 +396,7 @@ function StepWelcome() { : "none", }} > - +
); })} From f10a4f838bafd2165a8deeaf048482166ba5d675 Mon Sep 17 00:00:00 2001 From: RealZST Date: Sun, 18 Oct 2026 20:46:27 +0800 Subject: [PATCH 2/6] fix(ui): wrap page headers and the filter bar on narrow windows The Extensions filter bar, the Extensions header and the Marketplace header sit above their scroll containers, so whatever did not fit was clipped off the right edge with no way to reach it (unlike the lists below, which scroll). They now wrap: the dropdowns and search box move to their own right-aligned line, and the header buttons keep their labels on one line instead of breaking mid-text before overflowing. Co-Authored-By: Claude Fable 5.1 --- .../extensions/extension-filters.tsx | 153 +++++++++--------- src/pages/extensions.tsx | 12 +- src/pages/marketplace.tsx | 12 +- 3 files changed, 92 insertions(+), 85 deletions(-) diff --git a/src/components/extensions/extension-filters.tsx b/src/components/extensions/extension-filters.tsx index 10afb7cb..b9842d5f 100644 --- a/src/components/extensions/extension-filters.tsx +++ b/src/components/extensions/extension-filters.tsx @@ -155,8 +155,10 @@ export function ExtensionFilters() { return (
- {/* Filters: kind pills + result count + dropdowns + search */} -
+ {/* Filters: kind pills + result count + dropdowns + search. Wraps on + narrow windows: the bar sits above the scroll container, so anything + past the right edge would otherwise be clipped with no way to reach it. */} +
{kinds.map((kind) => ( + )} +
diff --git a/src/pages/extensions.tsx b/src/pages/extensions.tsx index bcab48b3..ea7e0cc6 100644 --- a/src/pages/extensions.tsx +++ b/src/pages/extensions.tsx @@ -181,14 +181,14 @@ export default function ExtensionsPage() {
{/* Fixed header */}
-
-
+
+

{t("page.title")}

-
+