diff --git a/apps/web/src/components/features/workspace/workspace-card.tsx b/apps/web/src/components/features/workspace/workspace-card.tsx index 627eb5f..bc53ede 100644 --- a/apps/web/src/components/features/workspace/workspace-card.tsx +++ b/apps/web/src/components/features/workspace/workspace-card.tsx @@ -29,47 +29,68 @@ export function WorkspaceCard({ return (
- -
-

{workspace.name}

- - {workspace.status} +
+ +
+ + {workspace.project_name} + +

{workspace.name}

+
+ + + {workspace.status} + +
+ +
+
+ + + {workspace.repo_name} + + + {workspace.branch} + + {workspace.instance_count > 0 && ( + + {workspace.instance_count} tool + {workspace.instance_count > 1 ? "s" : ""} + + )}
- -
-

- {workspace.project_name} / {workspace.repo_name} -

-

- {workspace.branch} -

+
diff --git a/apps/web/src/pages/WorkspacesPage.tsx b/apps/web/src/pages/WorkspacesPage.tsx index fcec79e..c6a5fa1 100644 --- a/apps/web/src/pages/WorkspacesPage.tsx +++ b/apps/web/src/pages/WorkspacesPage.tsx @@ -104,7 +104,7 @@ export function WorkspacesPage() { items={workspaces.map((ws) => ({ id: ws.id, title: ws.name, - subtitle: `${ws.project_name} · ${ws.repo_name} · ${ws.branch}`, + subtitle: `${ws.project_name} · ${ws.name}`, status: ws.status, }))} onItemClick={(id) => { diff --git a/apps/web/src/styles/pages/workspaces.css b/apps/web/src/styles/pages/workspaces.css index 663149d..64b97ca 100644 --- a/apps/web/src/styles/pages/workspaces.css +++ b/apps/web/src/styles/pages/workspaces.css @@ -7,22 +7,28 @@ .workspaces-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: var(--space-4); margin-top: var(--space-4); } /* Workspace card */ .workspace-card { - padding: var(--space-4); + display: flex; + flex-direction: column; + gap: var(--space-4); + padding: var(--space-5); border: 1px solid var(--border); border-radius: 12px; background: var(--panel); - transition: box-shadow 0.15s ease; + transition: + box-shadow 0.15s ease, + border-color 0.15s ease; } .workspace-card:hover { - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08); + border-color: color-mix(in srgb, var(--border) 80%, var(--brand)); } .workspace-card.loading { @@ -30,46 +36,149 @@ pointer-events: none; } -.workspace-header-link { +/* Top row: title + status */ +.workspace-card-top { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: var(--space-3); +} + +.workspace-title-link { display: block; text-decoration: none; color: inherit; -} - -.workspace-header { - display: flex; - align-items: center; - gap: var(--space-2); - margin-bottom: var(--space-2); -} - -.workspace-header h4 { - margin: 0; - font-size: 1.1rem; flex: 1; + min-width: 0; } -.workspace-meta { - margin-bottom: var(--space-3); +.workspace-title-link:hover .workspace-name { + color: var(--brand); } -.workspace-meta p { - margin: 0.15rem 0; - font-size: 0.875rem; +.workspace-title-stack { + display: flex; + flex-direction: column; + gap: var(--space-1); + min-width: 0; +} + +.workspace-project-name { + font-size: var(--font-size-sm); + font-weight: 500; + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.04em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.workspace-name { + margin: 0; + font-size: var(--font-size-lg); + font-weight: 700; + color: var(--ink); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* Body: meta row + instance chips */ +.workspace-card-body { + display: flex; + flex-direction: column; + gap: var(--space-3); +} + +.workspace-meta-row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: var(--space-3); + font-size: var(--font-size-sm); color: var(--muted); } +.workspace-meta-row > span { + display: inline-flex; + align-items: center; + gap: var(--space-1); +} + +.workspace-repo { + color: var(--muted); +} + +.workspace-branch { + color: var(--muted); +} + +.workspace-instance-count { + padding: var(--space-1) var(--space-2); + background: var(--bg); + border-radius: 999px; + font-size: var(--font-size-xs); + font-weight: 500; + color: var(--success); +} + +/* Instance chips */ +.instance-chips { + display: flex; + flex-wrap: wrap; + gap: var(--space-2); +} + +.instance-chip { + display: inline-flex; + align-items: center; + gap: var(--space-1); + font-size: var(--font-size-xs); + padding: var(--space-1) var(--space-2); + background: var(--bg); + border: 1px solid var(--border); + border-radius: 999px; + color: var(--ink); + max-width: 100%; +} + +.instance-chip.running { + background: var(--success-light); + border-color: color-mix(in srgb, var(--success) 25%, transparent); + color: var(--success); +} + +.instance-chip a { + color: inherit; + text-decoration: none; + margin-left: var(--space-1); +} + +.instance-chip a:hover { + text-decoration: underline; +} + +/* Actions */ .workspace-actions { display: flex; + align-items: center; gap: var(--space-2); - flex-wrap: wrap; + margin-top: auto; + padding-top: var(--space-3); + border-top: 1px solid var(--border); +} + +.workspace-actions .btn-primary { + margin-right: auto; } /* Status badges */ .status-badge { - font-size: 0.75rem; + flex-shrink: 0; + font-size: var(--font-size-xs); font-weight: 600; - padding: 0.15rem 0.5rem; + padding: var(--space-1) var(--space-2); border-radius: 999px; text-transform: capitalize; } @@ -103,7 +212,7 @@ /* Mobile */ @media (max-width: 767px) { .workspaces-page { - padding: var(--space-2); + padding: var(--space-3); } .workspaces-grid { @@ -112,14 +221,15 @@ } .workspace-card { - padding: var(--space-3); + padding: var(--space-4); + gap: var(--space-3); } .workspace-actions { - flex-direction: column; + flex-wrap: wrap; } - .workspace-actions .btn { + .workspace-actions .btn-primary { width: 100%; justify-content: center; }