feat: redesign workspace card header and layout
- Swap workspace card header order: project name is now the primary eyebrow, workspace name is the bold title below it. - Restructure workspace card into clean top/body/actions sections with more whitespace and clearer hierarchy. - Replace cramped meta paragraphs with an inline meta row (repo, branch, instance count) and dedicated instance chip area. - Use icon-only ghost buttons for sync/delete to reduce visual noise; keep prominent Start Tool button. - Add top divider for actions, improve hover states, and make long names truncate gracefully. - Update mobile workspace list subtitle to project · workspace name. - Refresh workspaces.css with new card layout and responsive mobile rules. Quality gates: npm run typecheck clean, npm run lint clean, npm test -- --run 87 passed
This commit is contained in:
@@ -29,47 +29,68 @@ export function WorkspaceCard({
|
||||
|
||||
return (
|
||||
<article className={`card workspace-card ${loading ? "loading" : ""}`}>
|
||||
<Link
|
||||
to={`/workspaces/${workspace.id}`}
|
||||
className="workspace-header-link"
|
||||
>
|
||||
<div className="workspace-header">
|
||||
<h4>{workspace.name}</h4>
|
||||
<span className={`status-badge ${statusClass}`}>
|
||||
{workspace.status}
|
||||
<div className="workspace-card-top">
|
||||
<Link
|
||||
to={`/workspaces/${workspace.id}`}
|
||||
className="workspace-title-link"
|
||||
>
|
||||
<div className="workspace-title-stack">
|
||||
<span className="workspace-project-name">
|
||||
{workspace.project_name}
|
||||
</span>
|
||||
<h4 className="workspace-name">{workspace.name}</h4>
|
||||
</div>
|
||||
</Link>
|
||||
<span className={`status-badge ${statusClass}`}>
|
||||
{workspace.status}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="workspace-card-body">
|
||||
<div className="workspace-meta-row">
|
||||
<span className="workspace-repo">
|
||||
<Icon name="repositories" size="sm" />
|
||||
{workspace.repo_name}
|
||||
</span>
|
||||
<span className="workspace-branch">
|
||||
<Icon name="branch" size="sm" />
|
||||
{workspace.branch}
|
||||
</span>
|
||||
{workspace.instance_count > 0 && (
|
||||
<span className="workspace-instance-count">
|
||||
{workspace.instance_count} tool
|
||||
{workspace.instance_count > 1 ? "s" : ""}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
<div className="workspace-meta">
|
||||
<p className="workspace-project">
|
||||
{workspace.project_name} / {workspace.repo_name}
|
||||
</p>
|
||||
<p className="workspace-branch">
|
||||
<Icon name="branch" size="sm" /> {workspace.branch}
|
||||
</p>
|
||||
<WorkspaceInstanceChips workspaceId={workspace.id} />
|
||||
</div>
|
||||
|
||||
<div className="workspace-actions">
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={() => onStartTool(workspace)}
|
||||
disabled={loading}
|
||||
title="Start a tool in this workspace"
|
||||
>
|
||||
<Icon name="play" size="sm" /> Start Tool
|
||||
<Icon name="play" size="sm" />
|
||||
Start Tool
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
className="ghost-button"
|
||||
onClick={() => onSync(workspace)}
|
||||
disabled={loading}
|
||||
title="Sync workspace"
|
||||
>
|
||||
<Icon name="refresh" size="sm" /> Sync
|
||||
<Icon name="refresh" size="sm" />
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-danger"
|
||||
className="ghost-button danger-text"
|
||||
onClick={() => onDelete(workspace)}
|
||||
disabled={loading}
|
||||
title="Delete workspace"
|
||||
>
|
||||
<Icon name="delete" size="sm" /> Delete
|
||||
<Icon name="delete" size="sm" />
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
Reference in New Issue
Block a user