feat(web/ui): unify config sections, restore home padding, improve project repos
- Add shared .config-section component class and migrate Tool Workshop and Config Profiles editors to use it. - Restore --space-4 padding on home hero, summary cards, and sections with --space-3 on mobile. - Restructure expandable project card: add 'Repositories' header with repo count and move 'Add Repository' button into the section header. - Left-align repository blocks so they fill from the project detail edge.
This commit is contained in:
@@ -173,9 +173,12 @@ export const ConfigProfileEditorPanel = ({
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-section">
|
||||
<div className="row justify-between items-center mb-3">
|
||||
<h4 className="m-0">Includes</h4>
|
||||
<section className="config-section">
|
||||
<div className="config-section-header">
|
||||
<div>
|
||||
<h4 className="config-section-title">Includes</h4>
|
||||
<p className="config-section-subtitle">Compose configurations from other profiles</p>
|
||||
</div>
|
||||
<span className="muted text-sm">{includedProfileIds.length} included</span>
|
||||
</div>
|
||||
{includedProfileIds.length === 0 ? (
|
||||
@@ -216,10 +219,10 @@ export const ConfigProfileEditorPanel = ({
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="form-section">
|
||||
<h4 className="m-0 mb-3">Environment Variables</h4>
|
||||
<section className="config-section">
|
||||
<h4 className="config-section-title">Environment Variables</h4>
|
||||
{Object.entries(formData.env_vars || {}).map(([key, value], idx) => (
|
||||
<div key={idx} className="form-row row-sm mb-2">
|
||||
<input type="text" value={key} onChange={(e) => onUpdateEnvVar(key, e.target.value, value)} placeholder="VAR_NAME" className="form-input" />
|
||||
@@ -228,16 +231,20 @@ export const ConfigProfileEditorPanel = ({
|
||||
</div>
|
||||
))}
|
||||
<button type="button" className="secondary-button" onClick={onAddEnvVar}><Icon name="add" size="sm" /> Add Variable</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="form-section">
|
||||
<h4 className="m-0 mb-3">Runtime Hints</h4>
|
||||
<section className="config-section">
|
||||
<h4 className="config-section-title">Runtime Hints</h4>
|
||||
<textarea value={JSON.stringify(formData.runtime_hints || {}, null, 2)} onChange={(e) => { try { const parsed = JSON.parse(e.target.value); onFormChange("runtime_hints", parsed); } catch { /* ignore */ } }} placeholder='{"start_command": "npm start"}' rows={4} className="form-input font-mono text-sm" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="form-section">
|
||||
<h4 className="m-0 mb-2">Files</h4>
|
||||
<p className="muted text-sm m-0 mb-3">Relative paths written to the instance directory. Use Mounts below for absolute container paths.</p>
|
||||
<section className="config-section">
|
||||
<div className="config-section-header">
|
||||
<div>
|
||||
<h4 className="config-section-title">Files</h4>
|
||||
<p className="config-section-subtitle">Relative paths written to the instance directory</p>
|
||||
</div>
|
||||
</div>
|
||||
{Object.entries(formData.files || {}).map(([path, content], idx) => (
|
||||
<div key={idx} className="card-sm mb-2">
|
||||
<div className="form-row row-sm mb-2">
|
||||
@@ -248,11 +255,15 @@ export const ConfigProfileEditorPanel = ({
|
||||
</div>
|
||||
))}
|
||||
<button type="button" className="secondary-button" onClick={onAddFile}><Icon name="add" size="sm" /> Add File</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="form-section">
|
||||
<h4 className="m-0 mb-2">Mounts</h4>
|
||||
<p className="muted text-sm m-0 mb-3">Bind directories into the container at absolute paths. Files are relative to the mount target.</p>
|
||||
<section className="config-section">
|
||||
<div className="config-section-header">
|
||||
<div>
|
||||
<h4 className="config-section-title">Mounts</h4>
|
||||
<p className="config-section-subtitle">Bind directories into the container at absolute paths</p>
|
||||
</div>
|
||||
</div>
|
||||
{(formData.mounts || []).map((mount, index) => (
|
||||
<div key={index} className="card-sm mb-3">
|
||||
<div className="form-row row-sm mb-3">
|
||||
@@ -276,11 +287,12 @@ export const ConfigProfileEditorPanel = ({
|
||||
</div>
|
||||
))}
|
||||
<button type="button" className="secondary-button" onClick={onAddMount}><Icon name="add" size="sm" /> Add Mount</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="form-section">
|
||||
<section className="config-section">
|
||||
<h4 className="config-section-title">Git Mounts</h4>
|
||||
<GitMountEditor mounts={formData.git_mounts || []} onChange={(git_mounts) => onFormChange("git_mounts", git_mounts)} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="dialog-actions sticky-footer">
|
||||
<button type="submit" disabled={saveStatus === "saving"} className="btn btn-primary">
|
||||
|
||||
Reference in New Issue
Block a user