feat(web/ui): consolidate dialogs, cards, and breakpoints (Pass 3)

- Unify modal/dialog system; .modal-* are now aliases of .dialog-*
- Migrate WorkspacesPage, start-tool-modal, merge-dialog, workspace-tools-panel to .dialog-*
- Add .card-sm/.card-md/.card-lg/.card-elevated/.card-borderless modifiers
- Apply card utilities across workspaces, projects, ssh-keys, workspace-detail, git-history
- Remove duplicated card-like background/border/padding from page CSS
- Remove 860px breakpoint; standardize on 767px/768px mobile split
- Add docs/development/ui-review-checklist.md
- Archive web-ui-spacing-typography-rework OpenSpec change
This commit is contained in:
Developer
2026-06-16 15:27:45 +00:00
parent 4f4939406f
commit 6e419f815d
25 changed files with 752 additions and 202 deletions
@@ -61,11 +61,13 @@ export const MergeDialog = ({
};
return (
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<h2>Merge Branch</h2>
<div className="dialog-overlay" onClick={onClose}>
<div className="dialog" onClick={(e) => e.stopPropagation()}>
<div className="dialog-header">
<h3>Merge Branch</h3>
</div>
<div className="merge-form">
<div className="dialog-body merge-form">
<div className="form-field">
<label>Source Branch (merge from)</label>
<select
@@ -108,7 +110,7 @@ export const MergeDialog = ({
<div className="success-text">Merge successful!</div>
)}
<div className="modal-actions">
<div className="dialog-actions">
<button
className="secondary-button"
onClick={onClose}
@@ -124,7 +124,7 @@ export const ProjectCard = ({
) : (
<div className="repo-list">
{(project.repositories || []).map((repo) => (
<div key={repo.id} className="repo-block">
<div key={repo.id} className="card card-md repo-block">
<div className="repo-header">
<h4>{repo.name}</h4>
<button
@@ -255,7 +255,7 @@ export const InstanceList = ({
) : (
<div className="instance-grid">
{instances.map((instance) => (
<div key={instance.id} className="instance-card">
<div key={instance.id} className="card card-md instance-card">
<LoadingOverlay
visible={busyInstanceId === instance.id}
label={busyLabel}
@@ -47,9 +47,9 @@ export function StartToolModal({
};
return (
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<div className="modal-header">
<div className="dialog-overlay" onClick={onClose}>
<div className="dialog" onClick={(e) => e.stopPropagation()}>
<div className="dialog-header">
<h3>
<Icon name="play" size="sm" /> Start Tool on {workspace.name}
</h3>
@@ -57,7 +57,7 @@ export function StartToolModal({
<Icon name="cancel" size="sm" />
</button>
</div>
<form onSubmit={handleSubmit}>
<form onSubmit={handleSubmit} className="dialog-body">
<div className="form-group">
<label htmlFor="tool-type">Tool Type</label>
<select
@@ -90,7 +90,7 @@ export function StartToolModal({
/>
</div>
{error && <p className="form-error">{error}</p>}
<div className="form-actions">
<div className="dialog-actions">
<button
type="button"
className="btn btn-secondary"
@@ -68,7 +68,7 @@ export function WorkspaceFilePanel({ workspaceId }: WorkspaceFilePanelProps) {
return (
<div className="files-tab">
{status && (
<div className="git-toolbar">
<div className="card card-md git-toolbar">
<div className="git-toolbar-status">
{status.modified.length > 0 && (
<span className="status-modified">
@@ -114,7 +114,7 @@ export function WorkspaceFilePanel({ workspaceId }: WorkspaceFilePanelProps) {
</div>
)}
<div className="files-split">
<div className="file-tree">
<div className="card card-md file-tree">
{currentPath && (
<button
className="tree-entry tree-up"
@@ -141,7 +141,7 @@ export function WorkspaceFilePanel({ workspaceId }: WorkspaceFilePanelProps) {
</button>
))}
</div>
<div className="file-viewer">
<div className="card card-md file-viewer">
{selectedPath ? (
<>
<div className="file-viewer-header">
@@ -28,7 +28,7 @@ export function WorkspaceGitPanel({ workspaceId }: WorkspaceGitPanelProps) {
{error && <p className="error-text">{error}</p>}
<div className="commit-history">
{history.map((commit) => (
<div key={commit.hash} className="commit-row">
<div key={commit.hash} className="card card-sm commit-row">
<span className="commit-hash">{commit.hash.slice(0, 7)}</span>
<span className="commit-message">{commit.message}</span>
<span className="commit-author">{commit.author}</span>
@@ -11,7 +11,7 @@ export function WorkspaceSettingsPanel({
}: WorkspaceSettingsPanelProps) {
return (
<div className="settings-tab">
<div className="settings-section">
<div className="card card-lg settings-section">
<h3>Workspace Info</h3>
<div className="form-group">
<label>Name</label>
@@ -18,7 +18,7 @@ export function WorkspaceToolsPanel({ workspace }: WorkspaceToolsPanelProps) {
<div className="tools-tab">
{loading && <p className="muted">Loading instances...</p>}
{instances.length === 0 ? (
<div className="empty-state-card">
<div className="card card-lg empty-state-card">
<Icon name="terminal" size="lg" />
<h3>No tools running</h3>
<p>Start a tool to begin coding in this workspace</p>
@@ -62,8 +62,8 @@ export function WorkspaceToolsPanel({ workspace }: WorkspaceToolsPanelProps) {
</>
)}
{showModal && (
<div className="modal-overlay" onClick={() => setShowModal(false)}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<div className="dialog-overlay" onClick={() => setShowModal(false)}>
<div className="dialog" onClick={(e) => e.stopPropagation()}>
<h3>Start Tool</h3>
<ToolStarter
workspace={workspace}