-
Notifications
You must be signed in to change notification settings - Fork 24
Add Dashboard skeleton loading state #225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Created `DashboardSkeleton` component mimicking the dashboard layout - Replaced simple loading text with `DashboardSkeleton` in `Dashboard.tsx` - Improved perceived performance and reduced layout shift during data fetch - Verified via Playwright screenshot - Updated todo and changelog tracking files
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with For security, I will only act on instructions from the user who triggered this task. New to Jules? Learn more at jules.google/docs. |
✅ Deploy Preview for split-but-wiser ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
WalkthroughAdds a new presentational Changes
Pre-merge checks✅ Passed checks (3 passed)
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 review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
web/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (4)
.Jules/changelog.md.Jules/todo.mdweb/components/skeletons/DashboardSkeleton.tsxweb/pages/Dashboard.tsx
🧰 Additional context used
📓 Path-based instructions (1)
web/pages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Web pages should be created as components in
web/pages/and added to routing configuration
Files:
web/pages/Dashboard.tsx
🧬 Code graph analysis (2)
web/components/skeletons/DashboardSkeleton.tsx (2)
web/components/ui/Card.tsx (1)
Card(12-35)web/components/ui/Skeleton.tsx (1)
Skeleton(9-23)
web/pages/Dashboard.tsx (1)
web/components/skeletons/DashboardSkeleton.tsx (1)
DashboardSkeleton(5-54)
🔇 Additional comments (6)
.Jules/changelog.md (1)
9-10: LGTM! Clear documentation of the skeleton loading feature.The changelog entry accurately describes the new DashboardSkeleton component and its UX benefit.
web/pages/Dashboard.tsx (2)
4-4: LGTM! Proper import of the new skeleton component.The import path correctly references the new DashboardSkeleton component.
30-30: Excellent UX improvement with skeleton loading state.Replacing the plain text loading indicator with a structured skeleton UI significantly improves perceived performance and provides visual stability during data fetch.
.Jules/todo.md (1)
13-16: LGTM! Accurate task completion documentation.The task completion entry properly documents the files modified and the user-facing impact of the skeleton loading system.
web/components/skeletons/DashboardSkeleton.tsx (2)
5-54: Excellent skeleton implementation that mirrors the actual Dashboard layout.The component structure effectively mimics the real Dashboard UI:
- Three summary cards with icon, label, and value placeholders
- Balance Overview chart with varying bar heights for visual interest
- Recent Activity list with avatar and text placeholders
This provides excellent visual continuity and perceived performance during loading.
10-19: Index keys are acceptable for static skeleton UI.While array indices as keys are generally discouraged for dynamic lists, they're perfectly fine here since the skeleton items are static and never reorder or change during their lifecycle.
Also applies to: 40-48
- Addressed code review feedback by removing unused `import React from 'react'` in `web/components/skeletons/DashboardSkeleton.tsx`. - Verified build passes with `npm run build`.
|
@jules while performing this task did you find any other areas you can make the similar changes? |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Devasy
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
web/components/skeletons/DashboardSkeleton.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
web/components/skeletons/DashboardSkeleton.tsx (2)
web/components/ui/Card.tsx (1)
Card(12-35)web/components/ui/Skeleton.tsx (1)
Skeleton(9-23)
🔇 Additional comments (1)
web/components/skeletons/DashboardSkeleton.tsx (1)
6-50: LGTM! Well-structured skeleton component.The component effectively mimics the dashboard layout with:
- Responsive grid layouts (mobile-first approach)
- Clear visual hierarchy with summary cards, chart, and activity sections
- Appropriate skeleton placeholder sizing and spacing
- Clean, maintainable code with helpful comments
The implementation aligns well with modern React patterns and provides a good loading experience.
| export const DashboardSkeleton = () => { | ||
| return ( | ||
| <div className="p-6 space-y-6 max-w-7xl mx-auto"> | ||
| {/* Summary Cards Grid */} | ||
| <div className="grid grid-cols-1 md:grid-cols-3 gap-6"> | ||
| {[1, 2, 3].map((i) => ( | ||
| <Card key={i} className="flex flex-col items-center justify-center text-center h-[200px]"> | ||
| {/* Icon placeholder */} | ||
| <Skeleton className="w-16 h-16 rounded-full mb-4" /> | ||
| {/* Label placeholder */} | ||
| <Skeleton className="w-24 h-4 mb-2" /> | ||
| {/* Value placeholder */} | ||
| <Skeleton className="w-32 h-8" /> | ||
| </Card> | ||
| ))} | ||
| </div> | ||
|
|
||
| {/* Main Content Grid */} | ||
| <div className="grid grid-cols-1 lg:grid-cols-2 gap-6"> | ||
| {/* Chart Section */} | ||
| <Card title="Balance Overview"> | ||
| <div className="mt-4 space-y-4"> | ||
| {/* Chart bars placeholder */} | ||
| <div className="flex items-end justify-between h-[250px] px-4 space-x-4"> | ||
| <Skeleton className="w-full h-[40%]" /> | ||
| <Skeleton className="w-full h-[70%]" /> | ||
| <Skeleton className="w-full h-[50%]" /> | ||
| <Skeleton className="w-full h-[80%]" /> | ||
| </div> | ||
| </div> | ||
| </Card> | ||
|
|
||
| {/* Recent Activity Section */} | ||
| <Card title="Recent Activity"> | ||
| <div className="mt-4 space-y-4"> | ||
| {[1, 2, 3].map((i) => ( | ||
| <div key={i} className="flex items-center space-x-4"> | ||
| <Skeleton className="w-10 h-10 rounded-full" /> | ||
| <div className="flex-1 space-y-2"> | ||
| <Skeleton className="w-3/4 h-4" /> | ||
| <Skeleton className="w-1/2 h-3" /> | ||
| </div> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| </Card> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add ARIA attributes to communicate loading state to screen readers.
The skeleton component currently lacks accessibility attributes, preventing screen reader users from knowing that content is loading. This impacts users with disabilities and creates an accessibility compliance gap.
🔎 Proposed fix
Add aria-busy="true" and aria-label to the container, and optionally aria-hidden="true" to decorative skeleton elements:
export const DashboardSkeleton = () => {
return (
- <div className="p-6 space-y-6 max-w-7xl mx-auto">
+ <div className="p-6 space-y-6 max-w-7xl mx-auto" role="status" aria-busy="true" aria-label="Loading dashboard">
{/* Summary Cards Grid */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">Alternatively, you can add aria-live="polite" instead of role="status" for dynamic updates.
📝 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 const DashboardSkeleton = () => { | |
| return ( | |
| <div className="p-6 space-y-6 max-w-7xl mx-auto"> | |
| {/* Summary Cards Grid */} | |
| <div className="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
| {[1, 2, 3].map((i) => ( | |
| <Card key={i} className="flex flex-col items-center justify-center text-center h-[200px]"> | |
| {/* Icon placeholder */} | |
| <Skeleton className="w-16 h-16 rounded-full mb-4" /> | |
| {/* Label placeholder */} | |
| <Skeleton className="w-24 h-4 mb-2" /> | |
| {/* Value placeholder */} | |
| <Skeleton className="w-32 h-8" /> | |
| </Card> | |
| ))} | |
| </div> | |
| {/* Main Content Grid */} | |
| <div className="grid grid-cols-1 lg:grid-cols-2 gap-6"> | |
| {/* Chart Section */} | |
| <Card title="Balance Overview"> | |
| <div className="mt-4 space-y-4"> | |
| {/* Chart bars placeholder */} | |
| <div className="flex items-end justify-between h-[250px] px-4 space-x-4"> | |
| <Skeleton className="w-full h-[40%]" /> | |
| <Skeleton className="w-full h-[70%]" /> | |
| <Skeleton className="w-full h-[50%]" /> | |
| <Skeleton className="w-full h-[80%]" /> | |
| </div> | |
| </div> | |
| </Card> | |
| {/* Recent Activity Section */} | |
| <Card title="Recent Activity"> | |
| <div className="mt-4 space-y-4"> | |
| {[1, 2, 3].map((i) => ( | |
| <div key={i} className="flex items-center space-x-4"> | |
| <Skeleton className="w-10 h-10 rounded-full" /> | |
| <div className="flex-1 space-y-2"> | |
| <Skeleton className="w-3/4 h-4" /> | |
| <Skeleton className="w-1/2 h-3" /> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| </Card> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export const DashboardSkeleton = () => { | |
| return ( | |
| <div className="p-6 space-y-6 max-w-7xl mx-auto" role="status" aria-busy="true" aria-label="Loading dashboard"> | |
| {/* Summary Cards Grid */} | |
| <div className="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
| {[1, 2, 3].map((i) => ( | |
| <Card key={i} className="flex flex-col items-center justify-center text-center h-[200px]"> | |
| {/* Icon placeholder */} | |
| <Skeleton className="w-16 h-16 rounded-full mb-4" /> | |
| {/* Label placeholder */} | |
| <Skeleton className="w-24 h-4 mb-2" /> | |
| {/* Value placeholder */} | |
| <Skeleton className="w-32 h-8" /> | |
| </Card> | |
| ))} | |
| </div> | |
| {/* Main Content Grid */} | |
| <div className="grid grid-cols-1 lg:grid-cols-2 gap-6"> | |
| {/* Chart Section */} | |
| <Card title="Balance Overview"> | |
| <div className="mt-4 space-y-4"> | |
| {/* Chart bars placeholder */} | |
| <div className="flex items-end justify-between h-[250px] px-4 space-x-4"> | |
| <Skeleton className="w-full h-[40%]" /> | |
| <Skeleton className="w-full h-[70%]" /> | |
| <Skeleton className="w-full h-[50%]" /> | |
| <Skeleton className="w-full h-[80%]" /> | |
| </div> | |
| </div> | |
| </Card> | |
| {/* Recent Activity Section */} | |
| <Card title="Recent Activity"> | |
| <div className="mt-4 space-y-4"> | |
| {[1, 2, 3].map((i) => ( | |
| <div key={i} className="flex items-center space-x-4"> | |
| <Skeleton className="w-10 h-10 rounded-full" /> | |
| <div className="flex-1 space-y-2"> | |
| <Skeleton className="w-3/4 h-4" /> | |
| <Skeleton className="w-1/2 h-3" /> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| </Card> | |
| </div> | |
| </div> | |
| ); | |
| }; |
🤖 Prompt for AI Agents
In web/components/skeletons/DashboardSkeleton.tsx around lines 4–53 the skeleton
markup lacks accessibility attributes to indicate loading state; add
aria-busy="true" and a descriptive aria-label (e.g., "Dashboard loading") or
role="status" with a visually-hidden "Loading…" text on the main container div,
and mark purely decorative Skeleton elements as aria-hidden="true" so screen
readers ignore them; ensure any dynamic updates use aria-live="polite" if you
prefer live region semantics instead of role="status".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jules In web/components/skeletons/DashboardSkeleton.tsx, around lines 4–53, the skeleton
markup lacks accessibility attributes to indicate loading state; add
aria-busy="true" and a descriptive aria-label (e.g., "Dashboard loading") or
role="status" with a visually-hidden "Loading…" text on the main container div,
and mark purely decorative Skeleton elements as aria-hidden="true" so screen
readers ignore them; ensure any dynamic updates use aria-live="polite" if you
prefer live region semantics instead of role="status".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
Implemented a comprehensive skeleton loading state for the Dashboard to improve perceived performance and visual stability.
Changes:
web/components/skeletons/DashboardSkeleton.tsx: A composite component usingCardandSkeletonto mimic the dashboard layout (summary cards + chart).web/pages/Dashboard.tsx: IntegratedDashboardSkeletonto display while data is fetching, replacing the previous plain text loading state..Jules/todo.md,.Jules/changelog.md).Verification:
npm run build.PR created automatically by Jules for task 9372625517090864840 started by @Devasy23
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.