fluid-loading: dot matrix loaders everywhere#48
Conversation
Replace spinners and skeleton placeholders with the shared dot matrix component during navigation, auth, bootstrap, and async actions.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR introduces a unified
Confidence Score: 4/5Safe to merge — changes are purely visual and additive; no data paths, auth logic, or API contracts are touched. The loading-state system is well-structured and the reduced-motion, SSR, and browser-guard cases are all handled. The only items worth a second look are a src/lib/components/ui/dotmatrix/dotmatrix-base.svelte (variable shadowing) and src/lib/components/route-navigation-loader.svelte (aria-hidden suppressing live regions) Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Page Load] --> B[app.html boot-loader visible]
B --> C{SvelteKit hydrates?}
C -- yes --> D[root +layout $effect adds app-ready]
D --> E[boot-loader CSS transition: opacity 0 / visibility hidden]
F[User clicks link] --> G{navigating.to set?}
G -- no --> H[No loader]
G -- yes --> I{isAppPath from AND to?}
I -- both app --> J[RouteNavigationLoader scope=app\ncontent overlay over sidebar]
I -- at least one non-app --> K[RouteNavigationLoader scope=root\nfull-page overlay]
J --> L[Navigation complete - loader unmounts]
K --> L
M[Action button click] --> N{loading state true?}
N -- yes --> O[DotMatrixLoader variant=inline inside button]
N -- no --> P[Icon rendered]
Reviews (1): Last reviewed commit: "Use dot matrix loader for all loading st..." | Re-trigger Greptile |
| <div | ||
| class="absolute inset-0 z-10 flex items-center justify-center bg-background/78 backdrop-blur-[1px]" | ||
| aria-hidden="true" | ||
| > | ||
| <DotMatrixLoader variant="content" /> | ||
| </div> | ||
| {:else} | ||
| <div class="fixed inset-0 z-50 bg-background" aria-hidden="true"> | ||
| <DotMatrixLoader variant="page" /> | ||
| </div> |
There was a problem hiding this comment.
Navigation loader live region silenced by
aria-hidden
Both overlay wrappers carry aria-hidden="true", which hides the inner DotMatrixBase's role="status" / aria-live="polite" from assistive technology. Screen readers will not announce the loading state on navigation. SvelteKit does announce page changes via the route announcer, but that fires after navigation completes — there is no in-progress "Loading…" callout for AT users. Consider moving aria-hidden to the decorative dot grid only, and letting the role="status" container remain accessible, or adding a visually-hidden live region outside the aria-hidden wrapper.
| const dotStyle: DotStyle = { | ||
| width: dotSize, | ||
| height: dotSize, | ||
| '--dmx-distance': distance, | ||
| '--dmx-row': row, | ||
| '--dmx-col': col, | ||
| '--dmx-x': `${deltaX}px`, | ||
| '--dmx-y': `${deltaY}px`, | ||
| '--dmx-angle': angle, | ||
| '--dmx-radius': radiusNormalizedValue, | ||
| '--dmx-manhattan': manhattan, | ||
| ...stylePatch, | ||
| ...(!isActive | ||
| ? { | ||
| opacity: 0, | ||
| visibility: 'hidden', | ||
| pointerEvents: 'none', | ||
| animation: 'none' | ||
| } | ||
| : {}) | ||
| }; | ||
|
|
||
| return { | ||
| index, | ||
| class: cn( | ||
| 'dmx-dot', | ||
| !isActive && 'dmx-inactive', | ||
| isBloomDot && 'dmx-bloom-dot', | ||
| dotClassName, | ||
| animationState.className | ||
| ), | ||
| style: dotStyle |
There was a problem hiding this comment.
dotStyle variable shadows the imported function
The local const dotStyle: DotStyle = { … } declared inside the $derived.by() loop shares its name with the dotStyle function imported from ./dotmatrix-core.js. The scopes are different so the runtime result is correct — dot.style holds the object, and the template calls the imported function — but the collision makes the code hard to follow and will trigger no-shadow lint warnings. Renaming the local variable to something like dotCellStyle would remove the ambiguity.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Stack Context
Improves perceived performance and visual consistency by using the dot matrix animation everywhere the app would otherwise show a blank screen, skeleton, or generic spinner.
Why?
Loading states were inconsistent — pulse skeletons, CSS spinners, and empty content during navigation. The dot matrix component gives a single branded loader for route transitions, auth, bootstrap, and in-flight actions.
What
DotMatrixLoaderwith page, content, panel, and inline variantsnavigatingstate (root + app shell)app.htmluntil the app hydratesTest plan