feat(run): lay out the Workspace lane strip as a horizontal row above the detail panel

The lane strip was a fixed-width vertical column beside the detail panel.
Flipped it to a horizontally scrolling row on top so the detail/console
area gets the full page width below it.
This commit is contained in:
2026-08-19 10:22:35 +07:00
parent 8aa22cd255
commit 2fe465e36f
3 changed files with 14 additions and 17 deletions
@@ -1,9 +1,10 @@
/**
* @file The compact lane tile used in the Workspace's vertical lane list. It
* carries only what you need to pick a lane — which lane, is it alive, what
* stage, how far — because the full card, its controls and its working-copy
* facts live in the detail panel beside it. Keeping the tile small and full
* width is what lets many lanes stay scannable in one scrolling column.
* @file The compact lane tile used in the Workspace's horizontal lane strip.
* It carries only what you need to pick a lane — which lane, is it alive,
* what stage, how far — because the full card, its controls and its
* working-copy facts live in the detail panel below it. Keeping the tile
* small and fixed-width is what lets many lanes stay scannable in one
* scrolling row.
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/
@@ -42,7 +43,7 @@ export default function LaneStripCard({
aria-pressed={selected}
onClick={onSelect}
title={lane.cwd}
className={`w-full shrink-0 rounded-lg border p-3 text-left shadow-sm transition-colors ${
className={`w-56 shrink-0 rounded-lg border p-3 text-left shadow-sm transition-colors ${
selected
? "border-accent bg-accent/10"
: "border-border bg-surface-2 hover:border-border-light hover:bg-surface-3"
+5 -9
View File
@@ -521,15 +521,11 @@ export function Workspace() {
</button>
</div>
{/* Lane list + detail live side by side so neither can cover the other:
the list is a scrolling column (holds any number of lanes), the
detail/console area to its right never has to compete with it for
vertical space. */}
<div className="flex min-h-0 flex-1 gap-4">
<div
data-testid="lane-strip"
className="flex w-60 shrink-0 flex-col gap-2 overflow-y-auto pr-1"
>
{/* Lane strip + detail stack vertically: the strip is a horizontally
scrolling row (holds any number of lanes), the detail/console area
below it gets the full width and never competes for it. */}
<div className="flex min-h-0 flex-1 flex-col gap-4">
<div data-testid="lane-strip" className="flex shrink-0 flex-row gap-2 overflow-x-auto pb-1">
{lanes.map((l) => (
<LaneStripCard
key={l.id}
@@ -5762,10 +5762,10 @@ exports[`screen snapshots > Run 1`] = `
</button>
</div>
<div
class="flex min-h-0 flex-1 gap-4"
class="flex min-h-0 flex-1 flex-col gap-4"
>
<div
class="flex w-60 shrink-0 flex-col gap-2 overflow-y-auto pr-1"
class="flex shrink-0 flex-row gap-2 overflow-x-auto pb-1"
data-testid="lane-strip"
>
<p