refactor(web): split base.css by section (pinned import order) and api.ts by domain #195

Closed
opened 2026-07-22 00:02:35 +02:00 by dominik.polakovics · 0 comments

The two mechanical splits from the line-cap policy (#193): web/src/base.css (3945 lines, ~39 touches/3mo) and web/src/api.ts (1563 lines, 36 touches/3mo). Both are low-design, verification-cheap splits — bundled into one issue deliberately. Decomposition design below, per the #193 split-quality bar.

Behavior-preserving. No visual change, no import-path change for existing callers.

base.css → web/src/styles/*.css with pinned import order

The cascade hazard is the whole game: rules moved to a different file change specificity-tie outcomes unless order is preserved. Therefore:

  • base.css stays as the entry point but becomes an ordered list of @import statements only (Vite inlines and preserves order). Nothing else lives in it.
  • Split strictly along the existing section banner comments, keeping every rule in its original relative order. Do not reorder, merge, or "clean up" rules in this PR — order-preserving moves only.
  • Proposed files (adjust to the actual banner list, one file per banner or coherent banner group): styles/tokens.css (the :root blocks + dark-scheme overrides — this file stays small forever), styles/type.css, styles/layout.css, styles/shell.css (side rail, drawer, mobile strip), styles/cards.css, styles/chips.css, styles/buttons.css, styles/forms.css, styles/banners.css, … through the remaining banners.
  • Every resulting file under 2000 (they'll be far under; keeping them per-section beats packing to the cap).
  • Media-query blocks (min-width: 1024px, prefers-reduced-motion) that override earlier sections must stay after the sections they override — if a banner group's rules are order-coupled to another group, put them in the same file rather than relying on import order between two new files.

api.ts → web/src/api/ domain modules, barrel re-export

  • api.ts becomes a pure barrel (export * from './api/...') so all ~36 importers are untouched.
  • Modules follow the file's existing milestone/section banners, roughly: api/core.ts (BASE, request, ApiError, errorMessage, setUnauthorizedHandler), api/auth.ts (M1), api/credentials.ts (M2), api/repos.ts (M2), api/providers.ts (M3 providers + provider auth), api/runs.ts (M3 instances & runs), plus whatever later sections exist past line 487 (issues/PRs/settings/push — split by the same banner rule).
  • Types move with their endpoints; shared cross-domain types go in the module that owns the endpoint returning them (or api/core.ts if truly shared). Each module under 1000.
  • web/src/api.test.ts follows the same split only if needed; it is currently under cap — leave it whole if that's simpler.

Sequencing & ratchet

  • Land after #193; in the same PR remove the base.css and api.ts entries from baseline.json (ratchet test enforces).
  • Independent of #194 (different files) — can land before or after it.

Acceptance

  • Full web suite green: vitest, eslint, prettier --check, vite build.
  • Visual smoke on the main surfaces (shell/rail, run chat, forms, banners) in light and dark, desktop and mobile widths — no diff expected.
  • All resulting files under their caps; the two baseline entries deleted.
The two mechanical splits from the line-cap policy (#193): `web/src/base.css` (3945 lines, ~39 touches/3mo) and `web/src/api.ts` (1563 lines, 36 touches/3mo). Both are low-design, verification-cheap splits — bundled into one issue deliberately. Decomposition design below, per the #193 split-quality bar. **Behavior-preserving.** No visual change, no import-path change for existing callers. ## base.css → `web/src/styles/*.css` with pinned import order The cascade hazard is the whole game: rules moved to a different file change specificity-tie outcomes unless order is preserved. Therefore: - `base.css` **stays** as the entry point but becomes an ordered list of `@import` statements only (Vite inlines and preserves order). Nothing else lives in it. - Split strictly along the existing section banner comments, keeping every rule in its original relative order. Do not reorder, merge, or "clean up" rules in this PR — order-preserving moves only. - Proposed files (adjust to the actual banner list, one file per banner or coherent banner group): `styles/tokens.css` (the `:root` blocks + dark-scheme overrides — this file stays small forever), `styles/type.css`, `styles/layout.css`, `styles/shell.css` (side rail, drawer, mobile strip), `styles/cards.css`, `styles/chips.css`, `styles/buttons.css`, `styles/forms.css`, `styles/banners.css`, … through the remaining banners. - Every resulting file under 2000 (they'll be far under; keeping them per-section beats packing to the cap). - Media-query blocks (`min-width: 1024px`, `prefers-reduced-motion`) that override earlier sections must stay **after** the sections they override — if a banner group's rules are order-coupled to another group, put them in the same file rather than relying on import order between two new files. ## api.ts → `web/src/api/` domain modules, barrel re-export - `api.ts` becomes a pure barrel (`export * from './api/...'`) so all ~36 importers are untouched. - Modules follow the file's existing milestone/section banners, roughly: `api/core.ts` (`BASE`, `request`, `ApiError`, `errorMessage`, `setUnauthorizedHandler`), `api/auth.ts` (M1), `api/credentials.ts` (M2), `api/repos.ts` (M2), `api/providers.ts` (M3 providers + provider auth), `api/runs.ts` (M3 instances & runs), plus whatever later sections exist past line 487 (issues/PRs/settings/push — split by the same banner rule). - Types move with their endpoints; shared cross-domain types go in the module that owns the endpoint returning them (or `api/core.ts` if truly shared). Each module under 1000. - `web/src/api.test.ts` follows the same split only if needed; it is currently under cap — leave it whole if that's simpler. ## Sequencing & ratchet - Land **after** #193; in the same PR remove the `base.css` and `api.ts` entries from `baseline.json` (ratchet test enforces). - Independent of #194 (different files) — can land before or after it. ## Acceptance - Full web suite green: `vitest`, `eslint`, `prettier --check`, `vite build`. - Visual smoke on the main surfaces (shell/rail, run chat, forms, banners) in light and dark, desktop and mobile widths — no diff expected. - All resulting files under their caps; the two baseline entries deleted.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/coding-lab#195
No description provided.