Modern loaders: replace spinners with thinking-orbs - #868
Merged
Conversation
Contributor
Greptile SummaryThis PR unifies the renderer’s loading indicators around a theme-aware thinking-orbs wrapper. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (1): Last reviewed commit: "Loading" | Re-trigger Greptile |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Swaps every loading indicator in the app — the old
react-loader-spinnerGrid, the CSS.loading-spinnercircle, and the animatedloadingo.gifavatar — for the dotted thinking-orbs canvas animations, wired through one theme-aware wrapper.Why
The app had three unrelated loading treatments (a lucide spinner, a CSS border-spin circle, and a 610 KB looping gif) with no shared theming. thinking-orbs gives us a single, cohesive set of state-specific animations (
working,searching,solving,composing, …) that render on a plain 2D canvas — no WebGL, cheap on low-end devices, and identical across Chrome/Safari/Firefox.What changed
New:
OrbLoaderwrappersrc/renderer/src/components/OrbLoader.tsx— a thin wrapper aroundThinkingOrbthat does three things the raw component can't:automode only recognisesdata-theme="dark|light", but Hermes writes theme ids ("dracula","nord", …) to that attribute. The wrapper reads the resolved theme fromThemeProviderand pins the orb's ink from each theme's declaredappearance(dark/light), so the ink is correct across all 12 themes — not just when the OS setting happens to agree.size.ThinkingOrbships exactly two design presets (20, 64) and throws on any other size.OrbLoaderaccepts any number: it snaps the design to the nearest preset (split at 42) and drives the visual footprint from the number viastyle. Arbitrary pixel sizes (e.g. a 30 px avatar) are safe and never crash.invert. Flips the ink relative to the app theme, for orbs that sit on an inverted surface (see the chat avatar below).Loaders replaced
solvingorb.workingorb.searchingorb, replacing the CSS.loading-spinner.ActiveSessionsBar) →composingorb, replacing the lucideLoader2spinner-on-a-colour-circle.HermesAvatar) →composingorb, replacingloadingo.gif. The gif's loop-boundary stop logic is gone — a canvas orb never freezes mid-frame, so the avatar swaps straight to the agent'sProfileAvatarthe instant the turn goes idle.Chat avatar: inverted disc for legibility
The monochrome orb ink washed out against the near-black page, so the loading avatar (
.chat-avatar-orb) is backed by an inverted circle —--text-primary, which is light on dark themes and dark on light themes — and passesinverttoOrbLoaderso the ink flips to match. Result: a dark orb on a white disc under a dark theme, a light orb on a dark disc under a light theme. The canvas is inset slightly so the dots sit inside the circle instead of clipping.Dependency + cleanup
package.json:react-loader-spinner→thinking-orbs@^0.1.1..loading-spinnerCSS rule.test/setup.ts: replaced the 34-entryreact-loader-spinnermock with a one-linethinking-orbsmock (its canvas + IntersectionObserver rendering has no jsdom equivalent).Notes / follow-ups
loadingo.gif(610 KB) is now unused but still committed — can be deleted in a follow-up to trim the bundle.--text-primaryis a grayish tone) the avatar disc isn't pure white. If a crisp pure white/black disc is wanted regardless of theme, switch the background from--text-primaryto appearance-keyed#fff/#111.Verification
npm run typecheck:web— clean.npm test— 171 files, 1819 tests pass.electron-vite build— production bundle builds.lat check— all wiki links and code refs pass;lat.md/updated (loading-indicators.mdadded;chat-commands,sidebar-navigation,window-chrome, index updated).Docs
See
lat.md/loading-indicators.mdfor the full design notes: theOrbLoaderwrapper, per-state usage conventions, numeric-size snapping, theinvertinverted-disc avatar, and the test mock.