Files
headquarter/openspec/specs/ui-polish-round-config-sections-home-projects.md
T

7.5 KiB

OpenSpec Spec: UI Polish Round — Config Sections, Home Paddings, Project Repos

Change

ui-polish-round-config-sections-home-projects

Parent Proposal

openspec/proposals/ui-polish-round-config-sections-home-projects.md

Status

spec


1. Scope

This spec covers three UI polish fixes:

  1. Unify config sections across Tool Workshop and Config Profiles.
  2. Restore paddings on the Home page cards.
  3. Improve project repository layout in the expandable project card.

2. Shared Config Section

2.1 New CSS classes

Add to apps/web/src/styles/global.css:

.config-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.config-section-title {
  margin: 0 0 var(--space-1);
  font-size: var(--font-size-base);
  font-weight: 600;
  line-height: var(--line-height-tight);
  color: var(--ink);
}

.config-section-subtitle {
  margin: calc(var(--space-1) * -1) 0 var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--muted);
  line-height: var(--line-height-normal);
}

.config-section > .config-section-title + .config-section-subtitle {
  margin-top: calc(var(--space-2) * -1);
}

2.2 Tool Workshop migration

In apps/web/src/components/features/tool/manifest-editor.tsx:

  • Replace every occurrence of:

    <div className="card-md stack stack-md">
      <h4 className="m-0">Title</h4>
      ...
    </div>
    

    with:

    <section className="config-section">
      <h4 className="config-section-title">Title</h4>
      ...
    </section>
    
  • Keep .card-md on the preview block if it is not a config section.

2.3 Config Profiles migration

In apps/web/src/components/features/config-profiles/ConfigProfileEditorPanel.tsx:

  • Replace every occurrence of:

    <div className="form-section">
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "0.75rem" }}>
        <h4 style={{ margin: 0 }}>Title</h4>
        ...
      </div>
      ...
    </div>
    

    with:

    <section className="config-section">
      <div className="config-section-header">
        <div>
          <h4 className="config-section-title">Title</h4>
          {subtitle && <p className="config-section-subtitle">{subtitle}</p>}
        </div>
        ...actions...
      </div>
      ...
    </section>
    
  • Add .config-section-header CSS:

    .config-section-header {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: var(--space-3);
      margin-bottom: var(--space-2);
    }
    
    .config-section-header .config-section-title {
      margin-bottom: 0;
    }
    

2.4 Backward compatibility

Keep .form-section defined as an alias so existing consumers outside Config Profiles are not broken.


3. Home Page Padding

3.1 Target classes

In apps/web/src/styles/global.css:

.home-hero {
  padding: var(--space-4);
}

.home-summary-card {
  padding: var(--space-4);
}

.home-section {
  padding: var(--space-4);
}

If .home-hero already has padding from a previous rule, override/ensure it uses --space-4.

3.2 Mobile adjustments

At max-width: 767px, reduce padding to --space-3:

@media (max-width: 767px) {
  .home-hero,
  .home-summary-card,
  .home-section {
    padding: var(--space-3);
  }
}

4. Project Repository Layout

4.1 Component markup

In apps/web/src/components/features/project/ProjectCard.tsx:

Change the expanded detail block from:

{expanded && (
  <div className="project-detail">
    {(project.repositories || []).length === 0 ? (
      <p className="muted">No repositories yet.</p>
    ) : (
      <div className="repo-list">...</div>
    )}
    {onAddRepository && (
      <div className="project-add-repo">...</div>
    )}
  </div>
)}

to:

{expanded && (
  <div className="project-detail">
    <section className="project-repos">
      <div className="project-repos-header">
        <div>
          <h4 className="config-section-title">Repositories</h4>
          <p className="config-section-subtitle">
            {project.repositories?.length ?? 0} repo
            {(project.repositories?.length ?? 0) !== 1 ? "s" : ""}
          </p>
        </div>
        {onAddRepository && (
          <button
            className="btn btn-sm btn-secondary"
            onClick={onAddRepository}
            type="button"
          >
            <Icon name="add" size="sm" /> Add Repository
          </button>
        )}
      </div>

      {(project.repositories || []).length === 0 ? (
        <p className="muted">No repositories yet.</p>
      ) : (
        <div className="repo-list">
          {(project.repositories || []).map((repo) => (
            <div key={repo.id} className="card card-md repo-block">
              ...
            </div>
          ))}
        </div>
      )}
    </section>
  </div>
)}

Remove the old .project-add-repo block.

4.2 CSS changes

In apps/web/src/styles/pages/projects.css:

.project-detail {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}

.project-repos {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.project-repos-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.project-repos-header .config-section-title {
  margin-bottom: 0;
}

.repo-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.repo-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--bg);
}

.repo-block,
.repo-block.card-md {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

/* Remove old .project-add-repo rules */
.project-add-repo {
  display: none;
}

4.3 Mobile

At max-width: 767px, stack .project-repos-header vertically:

@media (max-width: 767px) {
  .project-repos-header {
    flex-direction: column;
    gap: var(--space-2);
  }
}

5. Acceptance Criteria

  • .config-section, .config-section-title, .config-section-subtitle, .config-section-header exist in global.css.
  • manifest-editor.tsx uses .config-section for its grouped blocks.
  • ConfigProfileEditorPanel.tsx uses .config-section for its grouped blocks.
  • .form-section remains as a backward-compatible alias.
  • .home-hero, .home-summary-card, and .home-section have --space-4 padding (desktop) and --space-3 padding (mobile).
  • ProjectCard.tsx shows a "Repositories" header with repo count and an "Add Repository" button in the section header.
  • Repository blocks are left-aligned under the project header and fill the available width.
  • Old .project-add-repo standalone block is removed.
  • npm run typecheck passes.
  • npm run lint passes.

6. Verification Plan

  1. Run cd apps/web && npm run typecheck.
  2. Run cd apps/web && npm run lint.
  3. Open Tool Workshop → create/edit a tool type → verify section styling matches Config Profiles.
  4. Open Config Profiles → verify section headers and subtitles render correctly.
  5. Open Home → verify hero, summary cards, and section cards have comfortable padding.
  6. Open Projects → expand a project → verify repositories are left-aligned, have a "Repositories" header with count, and the "Add Repository" button is in the header.
  7. Test project card on mobile viewport.

7. Next Phase

After approval, create tasks and delegate to sdd-apply.