Skip to content

fix(dashboard): one stated rule for small-size spinners - #4085

Open
adiarora06 wants to merge 1 commit into
kirodotdev:mainfrom
adiarora06:fix/small-spinner-glyph-rule
Open

fix(dashboard): one stated rule for small-size spinners#4085
adiarora06 wants to merge 1 commit into
kirodotdev:mainfrom
adiarora06:fix/small-spinner-glyph-rule

Conversation

@adiarora06

@adiarora06 adiarora06 commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Problem / Motivation

Small loading indicators use Loader2/LoaderCircle inconsistently, and the arc glyph becomes difficult to read at 10–14px. The repository had no stated rule or regression guard.

Why it matters

These indicators appear throughout dense dashboard controls. Inconsistent glyph selection makes equivalent states look different, while undersized arc spinners read as broken rings instead of motion.

What changed (motivation → approach → change)

Adopt one size-based rule: below 15px use lucide Loader; at 15px and above use LoaderCircle. The change documents that rule, applies it across explicit-size call sites, covers spinner components stored in icon maps, and adds a source-level guard. CSS/1em-sized spinners remain outside the static rule because their rendered size is contextual.

Tests

  • spinnerGlyphRule.test.ts: four assertions cover sub-15px sites, 15px-and-up sites, icon maps, and the documentation pin.
  • Updated glyph-class assertions in affected component tests.
  • Full frontend run previously completed with 20,959 tests passing; one known unrelated parallel-load flake passed in isolation.
  • TypeScript typecheck passed; ESLint reported zero errors.

Manual verification

Reviewed the affected spinner sizes and confirmed the rule preserves LoaderCircle at normal sizes while using the spoke glyph only where the arc loses legibility.

Screenshots / video

N/A — this is a repository-wide consistency sweep of existing loading states; no layout or interaction changed.

Related Issues

Closes #3925

Checklist

  • At most two commits (one is the norm), with a Conventional Commits title (feat|fix|docs|refactor|perf|test|chore|ci|build|revert: ...)
  • Existing tests pass and new tests added for new functionality
  • Self-review completed; code follows project style guidelines
  • Documentation updated
  • No secrets, credentials, or internal references in the diff

Contribution License Agreement

N/A — repository placeholder; no CLA text has been supplied.

@adiarora06
adiarora06 requested a review from a team August 17, 2026 07:04
@adiarora06
adiarora06 requested a review from a team as a code owner August 17, 2026 07:04
@github-actions github-actions Bot added fork Pull request from a fork (external contributor) readiness: action required A blocking check or review needs attention labels Aug 17, 2026
@iamwhatever

Copy link
Copy Markdown
Collaborator

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## Why it matters
  • ## What changed
  • ## Tests

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

@github-actions github-actions Bot added readiness: checking Automated validation is still running and removed readiness: action required A blocking check or review needs attention labels Aug 17, 2026
@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

UX Review (Fable 5, fork) — ✅ PASS

UX-level review of fa79d54d7a469f07ce641bcb8aa5840c269939ce via the fork AI-review pipeline — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

UX-Verdict: PASS

A pure spinner-glyph consistency sweep — size-keyed, documented, and test-enforced; no copy, flow, or state a user interacts with changes.

[UX-REVIEWED] fa79d54

@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

GPT 5.6 Review (fork) — ✅ no blocking findings

Reviewed fa79d54d7a469f07ce641bcb8aa5840c269939ce via the fork AI-review pipeline; updated in place on each push.

Review details

FINDING -- website/src/test/spinnerGlyphRule.test.ts:13 -- SMALL_ARC ignores size after other props, letting existing sub-15px arc spinners bypass the promised guard -> Fix: match numeric size anywhere in the opening tag.
[GPT-REVIEWED] fa79d54

@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

First Principles Review (Fable 5, fork) — 🟡 CONCERNS

Premise-level review of fa79d54d7a469f07ce641bcb8aa5840c269939ce via the fork AI-review pipeline — why this exists and whether the shipped surface is the smallest honest version. Updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

I have everything the contract requires: intent, full inventory, counted siblings/consumers against the base tree, and verified the guard-test convention already exists in-repo. Emitting the review.

First-Principles-Verdict: CONCERNS

The rule and sweep earn their place, but eight lucide-inline sites are flipped by a size attr their own CSS overrides — the doc's own scope sentence says to leave those alone.

What this change ships

Intent: make small loading spinners legible and uniform by adopting one size-keyed glyph rule — a FIX (closes #3925).

  1. Sub-15px spinners across the dashboard and apps spin as eight spokes instead of an arc (~45 sites) — justified
  2. Three 16–20px chat spinners flip the other way, spoke → arc — justified (the consistency half, declared via the 15px-and-up test)
  3. Five status/phase icon maps now name the spoke glyph — justified, declared
  4. page-layout.md gains a Spinners section stating the rule — justified (spec-updated-in-same-commit invariant)
  5. New source-scan test enforces the rule both ways, in maps, and pins the doc — justified (matches the existing convention: issueRadarStickyHeader.test.tsx already scans source)
  6. Eight CSS-sized (lucide-inline) spinners flipped by declared size — undeclared, contradicts the doc's own scope
  7. Two AssistantMessage tests rewritten wholesale where only two class names changed — rides along
  8. Eleven import blocks collapsed from multi-line to one line — rides along

Watch

  • The doc says a CSS-sized spinner "has no size to check statically and is out of the rule's scope; leave those on LoaderCircle." Yet 8 swept sites (grep lucide-inline.*animate-spin with size=: CommandBarOverlay, ErrorCard, ReportProblemModal, BrowserPanel ×2, DevFleetPage ×3) carry .lucide-inline { width: 1em } (index.css:2068), which overrides the size attribute — so the sweep and the guard test classify these by a number that does not control rendering. Either delete the inert size attr at those sites or leave them on LoaderCircle per the doc.

Subtractions

  • Revert the two rewritten tests in website/src/test/AssistantMessage.test.tsx to the minimal lucide-loader-circlelucide-loader class swap; the restructure (renames, moved clicks, new comments) is churn the fix doesn't need.
  • Revert the 11 multi-line import blocks collapsed to single lines (e.g. AddReposModal.tsx, BrowserPanel.tsx, mochi ChatPanel.tsx) — formatting churn that buries the real change in blame.
  • Drop the inert size={N} attribute from the 8 lucide-inline spinner sites above, so the guard test's classification matches what actually renders.

[FIRST-PRINCIPLES-REVIEWED] fa79d54

@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Design Review (Fable 5, fork) — ✅ PASS

Design-level review of fa79d54d7a469f07ce641bcb8aa5840c269939ce via the fork AI-review pipeline — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

Design-Verdict: PASS

A real, issue-backed inconsistency, fixed with a stated rule plus a two-directional guard — consistent with this repo's existing source-pin test idiom.

Watch

  • The rule keys on the declared size, but several converted sites (e.g. CommandBarOverlay.tsx, DevFleetPage.tsx) also carry lucide-inline, whose width: 1em overrides that attribute — the doc declares CSS-sized spinners out of scope, yet the guard classifies these by a number that doesn't govern their rendering. Harmless today (1em ≈ the declared px at those sites), but it blurs the rule's own scoping; consider stripping the vestigial size or noting the interaction in the doc.

Suggestions

  • A shared <Spinner size={n}> that picks the glyph internally would encode the rule once, absorb future call sites without discipline, and shrink the regex guard to "no raw Loader/LoaderCircle outside Spinner" — a follow-up worth considering since this PR already touched every site.
  • The guard test has no exemption mechanism; if a legitimate divergence ever appears (design refresh, one-off context), the only outs are compliance or editing the test — a short "how to exempt" line in the doc would pre-empt that fight.

[DESIGN-REVIEWED] fa79d54

@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Opus 4.8 Review (fork) — ✅ no blocking findings

Reviewed fa79d54d7a469f07ce641bcb8aa5840c269939ce via the fork AI-review pipeline; updated in place on each push.

Review details

No findings.

[OPUS-REVIEWED] fa79d54

@github-actions github-actions Bot added merge conflict Branch has merge conflicts with its base — author must resolve before merge readiness: passed Eligible automated validation passed for the current revision and removed readiness: checking Automated validation is still running labels Aug 17, 2026
@adiarora06
adiarora06 force-pushed the fix/small-spinner-glyph-rule branch from ac8489a to 7a7cb3c Compare August 18, 2026 18:55
@iamwhatever

Copy link
Copy Markdown
Collaborator

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## Why it matters
  • ## What changed
  • ## Tests

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

2 similar comments
@bolichen97

Copy link
Copy Markdown
Collaborator

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## Why it matters
  • ## What changed
  • ## Tests

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

@iamwhatever

Copy link
Copy Markdown
Collaborator

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## Why it matters
  • ## What changed
  • ## Tests

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention merge conflict Branch has merge conflicts with its base — author must resolve before merge readiness: checking Automated validation is still running and removed readiness: passed Eligible automated validation passed for the current revision merge conflict Branch has merge conflicts with its base — author must resolve before merge readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running labels Aug 18, 2026
@adiarora06
adiarora06 force-pushed the fix/small-spinner-glyph-rule branch from 7a7cb3c to 284dc91 Compare August 24, 2026 01:33
@iamwhatever

Copy link
Copy Markdown
Collaborator

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## Why it matters
  • ## What changed
  • ## Tests

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

@github-actions github-actions Bot removed the merge conflict Branch has merge conflicts with its base — author must resolve before merge label Aug 24, 2026
@dwu96

dwu96 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## Why it matters
  • ## What changed
  • ## Tests

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

auto-merge was automatically disabled August 27, 2026 20:25

Head branch was pushed to by a user without write access

@adiarora06
adiarora06 force-pushed the fix/small-spinner-glyph-rule branch from 284dc91 to fa79d54 Compare August 27, 2026 20:25
@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: passed Eligible automated validation passed for the current revision merge conflict Branch has merge conflicts with its base — author must resolve before merge and removed readiness: action required A blocking check or review needs attention merge conflict Branch has merge conflicts with its base — author must resolve before merge readiness: checking Automated validation is still running labels Aug 27, 2026
@bolichen97
bolichen97 enabled auto-merge August 30, 2026 00:08
)

`LoaderCircle` (exported as both `Loader2` and `LoaderCircle`) draws a single
2px-stroke arc spanning ~270 degrees of a circle. At 10-14px that stroke is
thick relative to the radius and the gap is roughly a sixth of the glyph, so it
reads as a broken ring rather than as motion. kirodotdev#3905 swapped the one row it
touched to lucide `Loader`, whose eight discrete spokes stay legible at that
size, and its review made the sharp point: the stated cause is a property of
the ICON at small sizes, not of that row, so it indicts every small spinner in
the app.

The rule, adopted from the issue's option 1 and written down in
`website/docs/page-layout.md`:

  Below 15px use `Loader`. At 15px and above use `LoaderCircle`.

Applied to every spinner with a DECLARED size below 15px (68 sites across 46
files), and in the other direction too: three `<Loader size={16|20}>` in
ChatPage move to `LoaderCircle`, because a rule enforced one way only would let
the spoke glyph spread upward and leave two spinners at one size again.

`src/test/spinnerGlyphRule.test.ts` enforces both directions and pins the
threshold to the doc, so the next call site has something to check against
rather than re-litigating the choice.

Two scope boundaries, both stated rather than left implicit:

- A spinner sized by CSS is out of scope. `lucide-inline` is `width: 1em`, so
  it follows the surrounding font size and has no size to check statically;
  those stay on `LoaderCircle` rather than being guessed at.
- The `Loader2` alias is left alone where it is not a small-size site. Retiring
  it in favour of the one canonical `LoaderCircle` name is worth doing, but it
  is a rename across ~40 unrelated sites and belongs in its own change.

The third assertion exists because the size-keyed sweep MISSED a class: a
spinner passed as a VALUE (`{ Icon: Loader2 }` in a phase/status map) has its
size at the `<Icon size={13} />` render site instead, so four such maps went
unconverted -- two of them breaking at runtime rather than in review. That case
is now checked rather than remembered.

- `spinnerGlyphRule`: 4 passed; all four fail on main.
- Full `vitest run`: 20959 passed, 1328 of 1329 files. The one failure is
  `CronFolderHeader.cov80.test.tsx`, the known parallel-load flake.
- `tsc --noEmit` clean; eslint 0 errors.
auto-merge was automatically disabled August 30, 2026 17:30

Head branch was pushed to by a user without write access

@adiarora06
adiarora06 force-pushed the fix/small-spinner-glyph-rule branch from fa79d54 to afa168f Compare August 30, 2026 17:30
@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running merge conflict Branch has merge conflicts with its base — author must resolve before merge and removed readiness: passed Eligible automated validation passed for the current revision readiness: action required A blocking check or review needs attention merge conflict Branch has merge conflicts with its base — author must resolve before merge readiness: checking Automated validation is still running labels Aug 30, 2026
@bolichen97

Copy link
Copy Markdown
Collaborator

Open PR relationship audit

This is a consolidated, point-in-time code-level audit note. It compares complete merge-base diffs and current/merged code; it does not treat a shared topic as duplication or partial coverage as completion.

Relationship findings

  • This PR is OVERLAPPING with PR #5274. The goals differ or the implementations can complement each other; this is not a duplicate claim. Recommended action for PR #4085: REBASE. Independently valuable and not duplicative, but ordering matters: whichever lands second must re-run the glyph sweep over the other's new call sites, so the two authors should agree on the order. Files: website/src/apps/code-review-sage/components/ReportView.tsx.
  • This PR is OVERLAPPING with PR #7977. The goals differ or the implementations can complement each other; this is not a duplicate claim. Recommended action for PR #4085: REBASE. The rebase is not mechanical here: it needs a decision on PR #7977's pinned recipe string, and that decision belongs in this PR rather than being discovered by red CI. Files: website/src/pages/chat/TranscriptScrollShell.tsx.
  • This PR is OVERLAPPING with PR #8040. The goals differ or the implementations can complement each other; this is not a duplicate claim. Recommended action for PR #4085: REBASE. Different goals in the same files with overlapping test hunks; the second to land needs a real merge and a glyph pass over the other's new spinners. Files: website/src/test/AssistantMessage.test.tsx.
  • This PR is OVERLAPPING with PR #8041. The goals differ or the implementations can complement each other; this is not a duplicate claim. Recommended action for PR #4085: REBASE. Base drift has already introduced a new violation outside the PR's file set; the guard cannot go green until the sweep is re-applied to current main. Files: website/src/components/SketchDialog.tsx.
  • PR #7628 is OVERLAPPING relative to this PR. The goals differ or the implementations can complement each other; this is not a duplicate claim. Recommended action for PR #7628: KEEP. Textual adjacency only. A cosmetic glyph-standardization sweep and a new usage state are independent and both landable. Files: website/src/App.tsx.

No PR, Issue, label, branch, or review state was changed by the relationship-note portion of this audit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drive-to-green PR claimed by drive-to-green pipeline fork Pull request from a fork (external contributor) merge conflict Branch has merge conflicts with its base — author must resolve before merge readiness: action required A blocking check or review needs attention

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decide one rule for small-size spinners: Loader vs LoaderCircle across 21 sites

5 participants