Make execution workspace detail page responsive for mobile

- Reduce card padding on small screens (p-4 → p-4 sm:p-5)
- Reduce spacing between sections on mobile (space-y-4 sm:space-y-6)
- Scale heading text (text-xl sm:text-2xl)
- Truncate long description on mobile, show full on sm+
- Reduce textarea min-heights on mobile (sm: prefix for larger sizes)
- Stack linked issue cards vertically on mobile, horizontal scroll on sm+
- Remove min-width constraint on linked issue cards on mobile

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
dotta 2026-04-05 07:35:33 -05:00
parent 68499eb2f4
commit 612bab1eb6

View file

@ -378,7 +378,7 @@ export function ExecutionWorkspaceDetail() {
return (
<>
<div className="mx-auto max-w-5xl space-y-6">
<div className="mx-auto max-w-5xl space-y-4 sm:space-y-6">
<div className="flex flex-wrap items-center gap-3">
<Button variant="ghost" size="sm" asChild>
<Link to={project ? `/projects/${projectRef}/workspaces` : "/projects"}>
@ -393,19 +393,20 @@ export function ExecutionWorkspaceDetail() {
</StatusPill>
</div>
<div className="grid gap-6 lg:grid-cols-[minmax(0,1.4fr)_minmax(18rem,0.95fr)]">
<div className="space-y-6">
<div className="rounded-2xl border border-border bg-card p-5">
<div className="grid gap-4 sm:gap-6 lg:grid-cols-[minmax(0,1.4fr)_minmax(18rem,0.95fr)]">
<div className="space-y-4 sm:space-y-6">
<div className="rounded-2xl border border-border bg-card p-4 sm:p-5">
<div className="flex flex-col gap-4 sm:flex-row sm:flex-wrap sm:items-start sm:justify-between">
<div className="space-y-2">
<div className="text-xs font-medium uppercase tracking-[0.16em] text-muted-foreground">
Execution workspace
</div>
<h1 className="text-2xl font-semibold">{workspace.name}</h1>
<h1 className="text-xl font-semibold sm:text-2xl">{workspace.name}</h1>
<p className="max-w-2xl text-sm text-muted-foreground">
Configure the concrete runtime workspace that Paperclip reuses for this issue flow. These settings stay
Configure the concrete runtime workspace that Paperclip reuses for this issue flow.
<span className="hidden sm:inline"> These settings stay
attached to the execution workspace so future runs can keep local paths, repo refs, provisioning, teardown,
and runtime-service behavior in sync with the actual workspace being reused.
and runtime-service behavior in sync with the actual workspace being reused.</span>
</p>
</div>
<div className="flex w-full shrink-0 items-center gap-2 sm:w-auto">
@ -482,7 +483,7 @@ export function ExecutionWorkspaceDetail() {
<div className="mt-4 grid gap-4 md:grid-cols-2">
<Field label="Provision command" hint="Runs when Paperclip prepares this execution workspace">
<textarea
className="min-h-28 w-full rounded-lg border border-border bg-background px-3 py-2 font-mono text-sm outline-none"
className="min-h-20 w-full rounded-lg border border-border bg-background px-3 py-2 font-mono text-sm outline-none sm:min-h-28"
value={form.provisionCommand}
onChange={(event) => setForm((current) => current ? { ...current, provisionCommand: event.target.value } : current)}
placeholder="bash ./scripts/provision-worktree.sh"
@ -490,7 +491,7 @@ export function ExecutionWorkspaceDetail() {
</Field>
<Field label="Teardown command" hint="Runs when the execution workspace is archived or cleaned up">
<textarea
className="min-h-28 w-full rounded-lg border border-border bg-background px-3 py-2 font-mono text-sm outline-none"
className="min-h-20 w-full rounded-lg border border-border bg-background px-3 py-2 font-mono text-sm outline-none sm:min-h-28"
value={form.teardownCommand}
onChange={(event) => setForm((current) => current ? { ...current, teardownCommand: event.target.value } : current)}
placeholder="bash ./scripts/teardown-worktree.sh"
@ -501,7 +502,7 @@ export function ExecutionWorkspaceDetail() {
<div className="mt-4 grid gap-4">
<Field label="Cleanup command" hint="Workspace-specific cleanup before teardown">
<textarea
className="min-h-24 w-full rounded-lg border border-border bg-background px-3 py-2 font-mono text-sm outline-none"
className="min-h-16 w-full rounded-lg border border-border bg-background px-3 py-2 font-mono text-sm outline-none sm:min-h-24"
value={form.cleanupCommand}
onChange={(event) => setForm((current) => current ? { ...current, cleanupCommand: event.target.value } : current)}
placeholder="pkill -f vite || true"
@ -553,7 +554,7 @@ export function ExecutionWorkspaceDetail() {
<label htmlFor="inherit-runtime-config">Inherit project workspace runtime config</label>
</div>
<textarea
className="min-h-48 w-full rounded-lg border border-border bg-background px-3 py-2 font-mono text-sm outline-none disabled:cursor-not-allowed disabled:opacity-60"
className="min-h-32 w-full rounded-lg border border-border bg-background px-3 py-2 font-mono text-sm outline-none disabled:cursor-not-allowed disabled:opacity-60 sm:min-h-48"
value={form.workspaceRuntime}
onChange={(event) => setForm((current) => current ? { ...current, workspaceRuntime: event.target.value } : current)}
disabled={form.inheritRuntime}
@ -586,8 +587,8 @@ export function ExecutionWorkspaceDetail() {
</div>
</div>
<div className="space-y-6">
<div className="rounded-2xl border border-border bg-card p-5">
<div className="space-y-4 sm:space-y-6">
<div className="rounded-2xl border border-border bg-card p-4 sm:p-5">
<div className="space-y-1">
<div className="text-xs font-medium uppercase tracking-[0.16em] text-muted-foreground">Linked objects</div>
<h2 className="text-lg font-semibold">Workspace context</h2>
@ -632,7 +633,7 @@ export function ExecutionWorkspaceDetail() {
</DetailRow>
</div>
<div className="rounded-2xl border border-border bg-card p-5">
<div className="rounded-2xl border border-border bg-card p-4 sm:p-5">
<div className="space-y-1">
<div className="text-xs font-medium uppercase tracking-[0.16em] text-muted-foreground">Paths and refs</div>
<h2 className="text-lg font-semibold">Concrete location</h2>
@ -676,7 +677,7 @@ export function ExecutionWorkspaceDetail() {
</DetailRow>
</div>
<div className="rounded-2xl border border-border bg-card p-5">
<div className="rounded-2xl border border-border bg-card p-4 sm:p-5">
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
<div className="space-y-1">
<div className="text-xs font-medium uppercase tracking-[0.16em] text-muted-foreground">Runtime services</div>
@ -755,7 +756,7 @@ export function ExecutionWorkspaceDetail() {
)}
</div>
<div className="rounded-2xl border border-border bg-card p-5">
<div className="rounded-2xl border border-border bg-card p-4 sm:p-5">
<div className="space-y-1">
<div className="text-xs font-medium uppercase tracking-[0.16em] text-muted-foreground">Recent operations</div>
<h2 className="text-lg font-semibold">Runtime and cleanup logs</h2>
@ -798,7 +799,7 @@ export function ExecutionWorkspaceDetail() {
</div>
</div>
<div className="rounded-2xl border border-border bg-card p-5">
<div className="rounded-2xl border border-border bg-card p-4 sm:p-5">
<div className="flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
<div className="space-y-1">
<div className="text-xs font-medium uppercase tracking-[0.16em] text-muted-foreground">Linked issues</div>
@ -819,12 +820,12 @@ export function ExecutionWorkspaceDetail() {
: "Failed to load linked issues."}
</p>
) : linkedIssues.length > 0 ? (
<div className="-mx-1 flex gap-3 overflow-x-auto px-1 pb-1">
<div className="-mx-1 flex flex-col gap-3 px-1 pb-1 sm:flex-row sm:overflow-x-auto">
{linkedIssues.map((issue) => (
<Link
key={issue.id}
to={issueUrl(issue)}
className="min-w-72 rounded-xl border border-border/80 bg-background px-4 py-3 transition-colors hover:bg-accent/20"
className="rounded-xl border border-border/80 bg-background px-4 py-3 transition-colors hover:bg-accent/20 sm:min-w-72"
>
<div className="flex items-start justify-between gap-3">
<div className="min-w-0 space-y-1">