feat(web/ui): refactor component inline styles into utility classes

Pass 2 of the web UI spacing/typography/visual-rhythm rework.

- Add layout, spacing, typography, visual, card, and component utilities
- Add form-section, form-row, form-help, text-error, alert-success
- Unify .form-group and .form-field; add .status-badge family
- Alias legacy button classes to .btn primitives
- Refactor ToolTypeListSidebar and ConfigProfileListSidebar to use .sidebar
  and var(--sidebar-width) instead of hardcoded 280px
- Refactor ToolTypeEditorPanel, ConfigProfileEditorPanel,
  git-mount-editor, and manifest-editor to use utility classes

Quality gates: npm run typecheck, npm run lint, npm run build pass.
Inline style blocks in target components reduced from 198 to 11.
This commit is contained in:
Developer
2026-06-16 14:47:37 +00:00
parent 38d116dcf7
commit 5d5b39bec1
8 changed files with 957 additions and 571 deletions
@@ -70,26 +70,15 @@ export const GitMountEditor = ({
return (
<div className="git-mount-editor">
<h4 style={{ margin: "0 0 0.75rem 0" }}>Git Mounts</h4>
<p
className="muted"
style={{ margin: "0 0 0.75rem 0", fontSize: "0.875rem" }}
>
<h4 className="m-0 mb-2">Git Mounts</h4>
<p className="muted text-sm mb-3 m-0">
Clone a repository once and mount multiple directories from it.
</p>
{normalizedMounts.length > 0 && (
<div
className="git-mount-list"
style={{
display: "flex",
flexDirection: "column",
gap: "0.75rem",
marginBottom: "1rem",
}}
>
<div className="git-mount-list mb-4">
{normalizedMounts.map((mount, index) => (
<div key={index} className="card" style={{ padding: "1rem" }}>
<div key={index} className="card-md">
{editingIndex === index ? (
<GitMountForm
mount={mount}
@@ -98,59 +87,28 @@ export const GitMountEditor = ({
/>
) : (
<div>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "flex-start",
marginBottom: "0.5rem",
}}
>
<div style={{ flex: 1, minWidth: 0 }}>
<div
style={{
fontWeight: 600,
fontSize: "0.9375rem",
marginBottom: "0.25rem",
}}
>
<div className="row justify-between items-start mb-2">
<div className="min-w-0 flex-1">
<div className="font-semibold text-base mb-1">
{mount.remote_url}
{mount.branch && (
<span
style={{
color: "var(--muted)",
fontWeight: 400,
marginLeft: "0.5rem",
}}
>
<span className="muted font-normal ml-2">
@{mount.branch}
</span>
)}
</div>
<div
style={{
display: "flex",
flexDirection: "column",
gap: "0.25rem",
}}
>
<div className="stack stack-sm">
{mount.mappings?.map((m, mi) => (
<div
key={mi}
style={{
fontSize: "0.875rem",
color: "var(--muted)",
fontFamily: "monospace",
}}
className="text-sm muted font-mono"
>
{m.source_path || "."} {m.target_path}
</div>
))}
</div>
</div>
<div
style={{ display: "flex", gap: "0.25rem", flexShrink: 0 }}
>
<div className="row row-sm flex-none">
<button
type="button"
className="ghost-button small"
@@ -177,7 +135,7 @@ export const GitMountEditor = ({
)}
{isAdding ? (
<div className="card" style={{ padding: "1rem" }}>
<div className="card-md">
<GitMountForm
mount={{
remote_url: "",
@@ -359,16 +317,11 @@ const GitMountForm = ({
};
return (
<div style={{ display: "flex", flexDirection: "column", gap: "0.75rem" }}>
<div
className="form-row"
style={{ gap: "0.5rem", alignItems: "flex-start" }}
>
<div style={{ flex: 2 }}>
<label style={{ fontSize: "0.875rem", fontWeight: 500 }}>
Repository URL
</label>
<div style={{ display: "flex", gap: "0.5rem" }}>
<div className="stack stack-md">
<div className="form-row row-sm items-start">
<div className="form-group flex-2">
<label className="text-sm font-medium">Repository URL</label>
<div className="row row-sm">
<input
type="text"
value={remoteUrl}
@@ -385,7 +338,6 @@ const GitMountForm = ({
}}
placeholder="https://github.com/user/repo.git"
className={`form-input ${errors.remote_url ? "error" : ""}`}
style={{ flex: 1 }}
/>
<button
type="button"
@@ -401,7 +353,7 @@ const GitMountForm = ({
</button>
</div>
{errors.remote_url && (
<span className="error-text">{errors.remote_url}</span>
<span className="text-error">{errors.remote_url}</span>
)}
{validation.status === "valid" && (
<span className="validation-status valid">
@@ -409,7 +361,7 @@ const GitMountForm = ({
{
(validation as Extract<ValidationState, { status: "valid" }>)
.branches.length
}{" "}
}{" "}
branches)
</span>
)}
@@ -434,10 +386,8 @@ const GitMountForm = ({
</span>
)}
</div>
<div style={{ flex: 1 }}>
<label style={{ fontSize: "0.875rem", fontWeight: 500 }}>
Branch
</label>
<div className="form-group flex-1">
<label className="text-sm font-medium">Branch</label>
{validation.status === "valid" ? (
<select
value={branch}
@@ -466,18 +416,14 @@ const GitMountForm = ({
</div>
<div
className="stack stack-sm"
style={{
opacity: isUrlValidated ? 1 : 0.5,
pointerEvents: isUrlValidated ? "auto" : "none",
}}
>
<label style={{ fontSize: "0.875rem", fontWeight: 500 }}>
Mappings
</label>
<p
className="muted"
style={{ margin: "0 0 0.5rem 0", fontSize: "0.8125rem" }}
>
<label className="text-sm font-medium">Mappings</label>
<p className="muted text-sm m-0">
Source paths within the repo and where to mount them in the container.
{!isUrlValidated && (
<span style={{ color: "var(--warning)" }}>
@@ -486,14 +432,11 @@ const GitMountForm = ({
</span>
)}
</p>
<div
style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}
>
<div className="stack stack-sm">
{mappings.map((mapping, index) => (
<div
key={index}
className="form-row"
style={{ gap: "0.5rem", alignItems: "flex-start" }}
className="form-row row-sm items-start"
>
<input
type="text"
@@ -503,17 +446,8 @@ const GitMountForm = ({
}
placeholder="packages/api"
className={`form-input ${errors[`mapping_${index}_source`] ? "error" : ""}`}
style={{ flex: 1 }}
/>
<span
style={{
padding: "0.5rem 0",
color: "var(--muted)",
fontSize: "0.875rem",
}}
>
</span>
<span className="text-sm muted py-2"></span>
<input
type="text"
value={mapping.target_path}
@@ -522,7 +456,6 @@ const GitMountForm = ({
}
placeholder="/app/api"
className={`form-input ${errors[`mapping_${index}_target`] ? "error" : ""}`}
style={{ flex: 1 }}
/>
{mappings.length > 1 && (
<button
@@ -535,12 +468,12 @@ const GitMountForm = ({
</button>
)}
{errors[`mapping_${index}_source`] && (
<span className="error-text">
<span className="text-error">
{errors[`mapping_${index}_source`]}
</span>
)}
{errors[`mapping_${index}_target`] && (
<span className="error-text">
<span className="text-error">
{errors[`mapping_${index}_target`]}
</span>
)}
@@ -551,17 +484,13 @@ const GitMountForm = ({
type="button"
className="secondary-button small"
onClick={addMapping}
style={{ marginTop: "0.5rem" }}
>
<Icon name="add" size="sm" />
Add Mapping
</button>
</div>
<div
className="form-actions"
style={{ display: "flex", gap: "0.5rem", marginTop: "0.5rem" }}
>
<div className="form-actions row-sm mt-2">
<button type="button" className="primary-button" onClick={handleSubmit}>
Save
</button>