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 * @file The compact lane tile used in the Workspace's horizontal lane strip.
* carries only what you need to pick a lane — which lane, is it alive, what * It carries only what you need to pick a lane — which lane, is it alive,
* stage, how far — because the full card, its controls and its working-copy * what stage, how far — because the full card, its controls and its
* facts live in the detail panel beside it. Keeping the tile small and full * working-copy facts live in the detail panel below it. Keeping the tile
* width is what lets many lanes stay scannable in one scrolling column. * 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> * @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/ */
@@ -42,7 +43,7 @@ export default function LaneStripCard({
aria-pressed={selected} aria-pressed={selected}
onClick={onSelect} onClick={onSelect}
title={lane.cwd} 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 selected
? "border-accent bg-accent/10" ? "border-accent bg-accent/10"
: "border-border bg-surface-2 hover:border-border-light hover:bg-surface-3" : "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> </button>
</div> </div>
{/* Lane list + detail live side by side so neither can cover the other: {/* Lane strip + detail stack vertically: the strip is a horizontally
the list is a scrolling column (holds any number of lanes), the scrolling row (holds any number of lanes), the detail/console area
detail/console area to its right never has to compete with it for below it gets the full width and never competes for it. */}
vertical space. */} <div className="flex min-h-0 flex-1 flex-col gap-4">
<div className="flex min-h-0 flex-1 gap-4"> <div data-testid="lane-strip" className="flex shrink-0 flex-row gap-2 overflow-x-auto pb-1">
<div
data-testid="lane-strip"
className="flex w-60 shrink-0 flex-col gap-2 overflow-y-auto pr-1"
>
{lanes.map((l) => ( {lanes.map((l) => (
<LaneStripCard <LaneStripCard
key={l.id} key={l.id}
@@ -5762,10 +5762,10 @@ exports[`screen snapshots > Run 1`] = `
</button> </button>
</div> </div>
<div <div
class="flex min-h-0 flex-1 gap-4" class="flex min-h-0 flex-1 flex-col gap-4"
> >
<div <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" data-testid="lane-strip"
> >
<p <p