Add shimmer loading skeleton for analysis dashboard#98
Conversation
|
@kushwahnihal25-rgb is attempting to deploy a commit to the karan3431's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Warning
|
| Layer / File(s) | Summary |
|---|---|
Shimmer animation and skeleton styling src/index.css |
CSS foundation closes the @media print block and adds @keyframes shimmer animation with .skeleton-shimmer class featuring a left-to-right gradient background and infinite animation. |
ScanSkeleton loading component src/components/shared/ScanSkeleton.tsx |
New default-exported React component renders an animated pulse layout with multiple GlassCard wrappers containing sized skeleton placeholder divs styled with the shimmer class. |
Offline ONNX scan result persistence src/pages/ScannerPage.tsx |
During offline inference, constructs a rich offlineScanResult object from ONNX output with derived grade, parsed confidence, classification, and nested fields, then persists to sessionStorage before proceeding with local display and navigation. |
Dashboard loading state with offline fallback src/pages/AnalysisDashboard.tsx |
AnalysisDashboard imports ScanSkeleton, checks sessionStorage for cached offlineScanResult with freshness_index to bypass API calls, and renders the skeleton component during loading instead of the previous StatusTerminal. |
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~22 minutes
Possibly related PRs
- jpdevhub/FreshScanAi#107: Both PRs modify the offline workflow in
src/pages/ScannerPage.tsx(building/persistingofflineScanResulttosessionStorage) andsrc/pages/AnalysisDashboard.tsx(readingofflineScanResultwhen unavailable), so they are directly related.
Suggested labels
Medium
Suggested reviewers
- jpdevhub
Poem
🐰 A shimmer so bright, left to right does it flow,
Skeleton frames dance with a graceful glow,
Offline results cached for when networks delay,
No more hard-coded waits—loading's got style today! ✨
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title 'Add shimmer loading skeleton for analysis dashboard' clearly and concisely describes the main change: implementing a shimmer skeleton loading component for the dashboard. |
| Linked Issues check | ✅ Passed | The PR implements all key requirements from issue #9: a reusable ScanSkeleton component with shimmer animation (keyframes and skeleton-shimmer class) and CSS gradient styling, integrated into AnalysisDashboard to replace loading states. |
| Out of Scope Changes check | ✅ Passed | Changes to ScannerPage.tsx for offline sessionStorage persistence and AnalysisDashboard.tsx fallback logic align with the reviewer's feedback to preserve recent offline-mode fixes and are necessary context for the skeleton implementation. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
⚔️ Resolve merge conflicts
- Resolve merge conflict in branch
clean-pr
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/shared/ScanSkeleton.tsx`:
- Around line 2-31: The ScanSkeleton component currently provides no accessible
loading semantics; update the top-level container returned by ScanSkeleton to
include role="status" and aria-live="polite" (or "assertive" if immediate
interruption is desired) and add a visually-hidden text node such as a <span
className="sr-only">Loading…</span> (or localized message) inside it so screen
readers announce the loading state; keep the existing visual structure
(GlassCard usage) but ensure the hidden text is inside the same root element so
assistive tech receives the status.
In `@src/index.css`:
- Line 418: The .skeleton-shimmer rule contains an extra empty line before the
background-size declaration which triggers the Stylelint
declaration-empty-line-before error; open the .skeleton-shimmer block, remove
the blank line immediately preceding the background-size: 200% 100%; line (or
adjust to match your project's declaration-empty-line-before style) so the
declaration follows the previous rule without an unexpected empty line.
- Around line 410-420: The shimmer animation on the .skeleton-shimmer selector
lacks a prefers-reduced-motion override; add a media query for
prefers-reduced-motion: reduce that disables or greatly reduces the animation
for .skeleton-shimmer (e.g., set animation to none or animation-duration to 0
and fix background-position), and ensure the `@keyframes` shimmer remains but is
not applied in that media query so motion-sensitive users do not get the
infinite shimmer.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2537c6bf-f10a-4b87-9306-3e436a5247f6
📒 Files selected for processing (3)
src/components/shared/ScanSkeleton.tsxsrc/index.csssrc/pages/AnalysisDashboard.tsx
| export default function ScanSkeleton() { | ||
| return ( | ||
| <div className="p-6 space-y-6 animate-pulse"> | ||
| <div className="flex flex-col md:flex-row gap-6"> | ||
| <GlassCard className="flex-1 p-8"> | ||
| <div className="h-4 w-32 skeleton-shimmer rounded mb-4"></div> | ||
| <div className="h-16 w-40 skeleton-shimmer rounded mb-4"></div> | ||
| <div className="h-2 w-full skeleton-shimmer rounded"></div> | ||
| </GlassCard> | ||
|
|
||
| <GlassCard className="md:w-72 p-6"> | ||
| <div className="h-4 w-24 skeleton-shimmer rounded mb-4"></div> | ||
| <div className="h-8 w-full skeleton-shimmer rounded mb-3"></div> | ||
| <div className="h-8 w-full skeleton-shimmer rounded"></div> | ||
| </GlassCard> | ||
| </div> | ||
|
|
||
| <GlassCard className="p-6"> | ||
| <div className="h-5 w-40 skeleton-shimmer rounded mb-4"></div> | ||
| <div className="space-y-3"> | ||
| <div className="h-16 skeleton-shimmer rounded"></div> | ||
| <div className="h-16 skeleton-shimmer rounded"></div> | ||
| <div className="h-16 skeleton-shimmer rounded"></div> | ||
| </div> | ||
| </GlassCard> | ||
|
|
||
| <GlassCard className="p-4"> | ||
| <div className="h-12 skeleton-shimmer rounded"></div> | ||
| </GlassCard> | ||
| </div> |
There was a problem hiding this comment.
Expose loading semantics for assistive tech.
This skeleton is now the loading UI, but it has no role="status"/aria-live/loading text, so screen reader users don’t get a meaningful loading announcement.
Suggested fix
export default function ScanSkeleton() {
return (
- <div className="p-6 space-y-6 animate-pulse">
+ <div
+ className="p-6 space-y-6 animate-pulse"
+ role="status"
+ aria-live="polite"
+ aria-busy="true"
+ >
+ <span className="sr-only">Loading analysis dashboard</span>
<div className="flex flex-col md:flex-row gap-6">📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export default function ScanSkeleton() { | |
| return ( | |
| <div className="p-6 space-y-6 animate-pulse"> | |
| <div className="flex flex-col md:flex-row gap-6"> | |
| <GlassCard className="flex-1 p-8"> | |
| <div className="h-4 w-32 skeleton-shimmer rounded mb-4"></div> | |
| <div className="h-16 w-40 skeleton-shimmer rounded mb-4"></div> | |
| <div className="h-2 w-full skeleton-shimmer rounded"></div> | |
| </GlassCard> | |
| <GlassCard className="md:w-72 p-6"> | |
| <div className="h-4 w-24 skeleton-shimmer rounded mb-4"></div> | |
| <div className="h-8 w-full skeleton-shimmer rounded mb-3"></div> | |
| <div className="h-8 w-full skeleton-shimmer rounded"></div> | |
| </GlassCard> | |
| </div> | |
| <GlassCard className="p-6"> | |
| <div className="h-5 w-40 skeleton-shimmer rounded mb-4"></div> | |
| <div className="space-y-3"> | |
| <div className="h-16 skeleton-shimmer rounded"></div> | |
| <div className="h-16 skeleton-shimmer rounded"></div> | |
| <div className="h-16 skeleton-shimmer rounded"></div> | |
| </div> | |
| </GlassCard> | |
| <GlassCard className="p-4"> | |
| <div className="h-12 skeleton-shimmer rounded"></div> | |
| </GlassCard> | |
| </div> | |
| export default function ScanSkeleton() { | |
| return ( | |
| <div | |
| className="p-6 space-y-6 animate-pulse" | |
| role="status" | |
| aria-live="polite" | |
| aria-busy="true" | |
| > | |
| <span className="sr-only">Loading analysis dashboard</span> | |
| <div className="flex flex-col md:flex-row gap-6"> | |
| <GlassCard className="flex-1 p-8"> | |
| <div className="h-4 w-32 skeleton-shimmer rounded mb-4"></div> | |
| <div className="h-16 w-40 skeleton-shimmer rounded mb-4"></div> | |
| <div className="h-2 w-full skeleton-shimmer rounded"></div> | |
| </GlassCard> | |
| <GlassCard className="md:w-72 p-6"> | |
| <div className="h-4 w-24 skeleton-shimmer rounded mb-4"></div> | |
| <div className="h-8 w-full skeleton-shimmer rounded mb-3"></div> | |
| <div className="h-8 w-full skeleton-shimmer rounded"></div> | |
| </GlassCard> | |
| </div> | |
| <GlassCard className="p-6"> | |
| <div className="h-5 w-40 skeleton-shimmer rounded mb-4"></div> | |
| <div className="space-y-3"> | |
| <div className="h-16 skeleton-shimmer rounded"></div> | |
| <div className="h-16 skeleton-shimmer rounded"></div> | |
| <div className="h-16 skeleton-shimmer rounded"></div> | |
| </div> | |
| </GlassCard> | |
| <GlassCard className="p-4"> | |
| <div className="h-12 skeleton-shimmer rounded"></div> | |
| </GlassCard> | |
| </div> | |
| ) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/shared/ScanSkeleton.tsx` around lines 2 - 31, The ScanSkeleton
component currently provides no accessible loading semantics; update the
top-level container returned by ScanSkeleton to include role="status" and
aria-live="polite" (or "assertive" if immediate interruption is desired) and add
a visually-hidden text node such as a <span className="sr-only">Loading…</span>
(or localized message) inside it so screen readers announce the loading state;
keep the existing visual structure (GlassCard usage) but ensure the hidden text
is inside the same root element so assistive tech receives the status.
| .skeleton-shimmer { | ||
| background: linear-gradient( | ||
| 90deg, | ||
| var(--color-surface-mid) 25%, | ||
| var(--color-surface-highest) 50%, | ||
| var(--color-surface-mid) 75% | ||
| ); | ||
|
|
||
| background-size: 200% 100%; | ||
| animation: shimmer 1.5s linear infinite; | ||
| } No newline at end of file |
There was a problem hiding this comment.
Add a reduced-motion fallback for shimmer animation.
Line 419 runs an infinite animation, but there’s no prefers-reduced-motion override. This can cause accessibility issues for motion-sensitive users and should be disabled/reduced in that mode.
Suggested fix
.skeleton-shimmer {
background: linear-gradient(
90deg,
var(--color-surface-mid) 25%,
var(--color-surface-highest) 50%,
var(--color-surface-mid) 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s linear infinite;
}
+
+@media (prefers-reduced-motion: reduce) {
+ .skeleton-shimmer {
+ animation: none;
+ background-position: 0 0;
+ }
+}🧰 Tools
🪛 Stylelint (17.12.0)
[error] 418-418: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/index.css` around lines 410 - 420, The shimmer animation on the
.skeleton-shimmer selector lacks a prefers-reduced-motion override; add a media
query for prefers-reduced-motion: reduce that disables or greatly reduces the
animation for .skeleton-shimmer (e.g., set animation to none or
animation-duration to 0 and fix background-position), and ensure the `@keyframes`
shimmer remains but is not applied in that media query so motion-sensitive users
do not get the infinite shimmer.
| var(--color-surface-mid) 75% | ||
| ); | ||
|
|
||
| background-size: 200% 100%; |
There was a problem hiding this comment.
Resolve the Stylelint rule violation in .skeleton-shimmer.
Line 418 is currently flagged by Stylelint (declaration-empty-line-before). Please remove the extra empty line before background-size (or align with your stylelint config) to keep lint green.
🧰 Tools
🪛 Stylelint (17.12.0)
[error] 418-418: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/index.css` at line 418, The .skeleton-shimmer rule contains an extra
empty line before the background-size declaration which triggers the Stylelint
declaration-empty-line-before error; open the .skeleton-shimmer block, remove
the blank line immediately preceding the background-size: 200% 100%; line (or
adjust to match your project's declaration-empty-line-before style) so the
declaration follows the previous rule without an unexpected empty line.
Source: Linters/SAST tools
|
Hi @jpdevhub , This is the clean PR requested in the review. Changes included:
All out-of-scope package.json and package-lock.json changes have been removed. Thank you for reviewing. |
|
Hi! The ScanSkeleton looks good, but your branch is severely out-of-date with main. Your PR currently deletes the recent offline-mode fixes we merged in api.ts, ScannerPage.tsx, and AnalysisDashboard.tsx (like the silent: true flag and the sessionStorage fallback). Please run git pull origin main, resolve the merge conflicts carefully to preserve our recent fixes, and push again. Let me know when it's updated! |
dad03ec to
9e0a2d0
Compare
|
Hi @jpdevhub , I've rebased the branch onto the latest main and force-pushed the updated PR. The recent offline-mode/sessionStorage related fixes should now be preserved. Could you please take another look when you have time? Thank you! |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Closes #9
Description
Implemented a shimmer loading skeleton for the Analysis Dashboard.
Changes
ScanSkeletoncomponent insrc/components/shared/AnalysisDashboard.tsxto use the shared skeleton componentsrc/index.cssNotes
package.jsonandpackage-lock.jsonwere removed.Checklist
npm run lintpasses with no errorsnpm run buildcompiles without TypeScript errorspython -m pytestpasses (including new tests I added).envfiles, API keys, secrets, model weights, or__pycache__in this diffmain, not mergedSummary by CodeRabbit
Summary of changes
New Features
Improvements
Style