Skip to content

[UX] Mobile Home Screen Skeleton Loading#291

Open
Devasy wants to merge 1 commit intomainfrom
jules/ux-mobile-home-skeleton-1918836578316525257
Open

[UX] Mobile Home Screen Skeleton Loading#291
Devasy wants to merge 1 commit intomainfrom
jules/ux-mobile-home-skeleton-1918836578316525257

Conversation

@Devasy
Copy link
Owner

@Devasy Devasy commented Feb 24, 2026

Implemented a skeleton loading state for the mobile Home Screen to improve perceived performance and visual consistency. Replaced the generic ActivityIndicator with a GroupListSkeleton that mimics the layout of the group cards, including avatars and status text. Created a reusable base Skeleton component using Animated for pulsing effects and react-native-paper theming.


PR created automatically by Jules for task 1918836578316525257 started by @Devasy23

Summary by CodeRabbit

  • New Features

    • Introduced animated skeleton placeholder cards during group content loading that mirror the structure of the actual list, with pulsing animation and theme-aware styling.
  • Documentation

    • Added skeleton loading patterns and implementation guidelines to the mobile development knowledge base.

- Created reusable `Skeleton` component with pulsing animation in `mobile/components/ui/Skeleton.js`.
- Created `GroupListSkeleton` component in `mobile/components/skeletons/GroupListSkeleton.js` to mimic the home screen layout.
- Replaced `ActivityIndicator` in `mobile/screens/HomeScreen.js` with the new skeleton loader.
- Updated tracking files (`todo.md`, `changelog.md`, `knowledge.md`).

Co-authored-by: Devasy23 <110348311+Devasy23@users.noreply.github.com>
@Devasy Devasy requested a review from vrajpatelll as a code owner February 24, 2026 19:56
@google-labs-jules
Copy link
Contributor

👋 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 @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@netlify
Copy link

netlify bot commented Feb 24, 2026

Deploy Preview for split-but-wiser canceled.

Name Link
🔨 Latest commit 9f0791a
🔍 Latest deploy log https://app.netlify.com/projects/split-but-wiser/deploys/699e02563e8db80008351cb5

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

Walkthrough

Introduces a Mobile Skeleton Loading feature with a reusable Skeleton component featuring pulsing animation and theme support. Adds GroupListSkeleton to display loading group cards, replaces ActivityIndicator in HomeScreen with skeleton loader, and updates documentation to reflect the implementation.

Changes

Cohort / File(s) Summary
Skeleton Loading Components
mobile/components/ui/Skeleton.js, mobile/components/skeletons/GroupListSkeleton.js
Introduces new Skeleton component with animated pulsing opacity (0.3–1.0), theme-aware background color, and accessibility labeling. GroupListSkeleton renders five skeleton cards simulating group list layout.
Screen Integration
mobile/screens/HomeScreen.js
Replaces ActivityIndicator with GroupListSkeleton during loading state and removes related loader container styling.
Documentation & Tracking
.Jules/changelog.md, .Jules/knowledge.md, .Jules/todo.md
Documents new skeleton loading pattern for mobile and web, adds implementation details to knowledge base, and marks skeleton loading task as completed with file references and impact notes.

Possibly related PRs

  • PR #269: Adds accessibilityRole and accessibilityLabel updates for skeleton and loading states, complementing the accessibility attributes introduced in this PR's Skeleton component.

Suggested reviewers

  • vrajpatelll
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[UX] Mobile Home Screen Skeleton Loading' directly and clearly summarizes the main change: implementing skeleton loading for the mobile Home Screen, which is the primary objective of this PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Feb 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@9404621). Learn more about missing BASE report.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #291   +/-   ##
=======================================
  Coverage        ?   63.55%           
=======================================
  Files           ?       21           
  Lines           ?     2456           
  Branches        ?      254           
=======================================
  Hits            ?     1561           
  Misses          ?      831           
  Partials        ?       64           
Components Coverage Δ
Authentication System 71.35% <ø> (?)
Expense Management 70.15% <ø> (?)
Group Management 73.78% <ø> (?)
User Management 97.16% <ø> (?)
Backend Core 70.78% <ø> (?)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mobile/components/ui/Skeleton.js`:
- Around line 30-43: The Skeleton component's Animated.View currently sets
accessibilityRole="progressbar" and accessibilityLabel="Loading..." which causes
excessive screen reader announcements; remove both accessibilityRole and
accessibilityLabel from the Animated.View in mobile/components/ui/Skeleton.js
(the Animated.View instance rendering the skeleton with style including
opacity/width/height/borderRadius/backgroundColor) so individual skeletons are
treated as decorative and rely on the container's single "Loading groups"
announcement for accessibility.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9404621 and 9f0791a.

📒 Files selected for processing (6)
  • .Jules/changelog.md
  • .Jules/knowledge.md
  • .Jules/todo.md
  • mobile/components/skeletons/GroupListSkeleton.js
  • mobile/components/ui/Skeleton.js
  • mobile/screens/HomeScreen.js

Comment on lines +30 to +43
<Animated.View
style={[
{
opacity,
width,
height,
borderRadius,
backgroundColor: theme.colors.surfaceVariant,
},
style,
]}
accessibilityRole="progressbar"
accessibilityLabel="Loading..."
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find mobile -name "Skeleton.js" -type f

Repository: Devasy/splitwiser

Length of output: 93


🏁 Script executed:

cat -n mobile/components/ui/Skeleton.js

Repository: Devasy/splitwiser

Length of output: 1476


🏁 Script executed:

find mobile -name "*GroupList*" -o -name "*Skeleton*" | head -20

Repository: Devasy/splitwiser

Length of output: 142


🏁 Script executed:

cat -n mobile/components/skeletons/GroupListSkeleton.js

Repository: Devasy/splitwiser

Length of output: 1315


🌐 Web query:

React Native accessible={false} importantForAccessibility="no" accessibilityElementsHidden

💡 Result:

  • accessible={false}: only means the View itself is not treated as a single “accessibility element” (iOS: isAccessibilityElement, Android: focusable). It does not automatically remove the view (or its children) from the screen reader’s accessibility tree. [1]

  • importantForAccessibility="no" (Android): tells Android accessibility services the view itself is not important (won’t be reported), but it does not hide descendants. To hide a view and all children on Android, use importantForAccessibility="no-hide-descendants". [1][2]

  • accessibilityElementsHidden (iOS): when true, hides the view and any accessibility elements it contains from VoiceOver. This is essentially the iOS equivalent of Android’s importantForAccessibility="no-hide-descendants". [1][2]

Practical mapping (hide subtree from screen readers)

<View
  accessibilityElementsHidden={true}          // iOS: hide subtree
  importantForAccessibility="no-hide-descendants" // Android: hide subtree
>
  ...
</View>

Using accessible={false} and/or importantForAccessibility="no" is not sufficient if your goal is “screen reader should ignore this whole section.” [1][2]

Sources: React Native Accessibility docs [1]; React Native Testing Library notes on what actually makes elements inaccessible [2].


🌐 Web query:

React Native accessibility best practices skeleton loading screen reader announcement

💡 Result:

Best practices (React Native) for an accessible skeleton loading state + screen reader announcement

  1. Don’t expose the skeleton UI to screen readers

    • Treat skeleton blocks as decorative placeholders and hide them from accessibility (so they don’t become dozens of meaningless focus stops). Common guidance is to hide skeletons and instead expose one loading message/state on a parent region. [4], [7]
  2. Expose a single “loading” state on the real content container

    • Put the container that will eventually hold the loaded content into a “busy/loading” state:
      • accessibilityState={{ busy: true }} while loading, then busy: false when done. (RN supports busy in accessibilityState.) [1]
    • Optionally pair with a meaningful role/label such as:
      • accessibilityRole="progressbar" (or a status-like pattern) and accessibilityLabel="Loading results" so the purpose is clear. [1], [2]
  3. Announce loading changes via “live region” where possible (Android)

    • On Android, RN supports accessibilityLiveRegion="polite" / "assertive" to announce updates when text changes. Prefer polite for loading. [1]
    • Note: accessibilityLiveRegion is Android-focused and has had consistency gaps across platforms. [9]
  4. Use direct announcements sparingly

    • AccessibilityInfo.announceForAccessibility(...) exists, but some platform docs caution against relying on forced announcements and recommend semantic/live-region approaches where possible. [2]

Minimal pattern (container announces; skeleton hidden)

import {AccessibilityInfo, Platform, View, Text} from "react-native";

function Screen({loading}: {loading: boolean}) {
  // Optional: only when loading is long enough / user-triggered
  // if (loading) AccessibilityInfo.announceForAccessibility("Loading content");
  // else AccessibilityInfo.announceForAccessibility("Content loaded");

  return (
    <View
      accessible
      accessibilityState={{ busy: loading }}
      accessibilityLabel={loading ? "Loading content" : "Content"}
    >
      {/* Android: live region announcement when this text changes */}
      <Text accessibilityLiveRegion={Platform.OS === "android" ? "polite" : undefined}>
        {loading ? "Loading…" : ""}
      </Text>

      {loading ? (
        // Skeleton UI: hide from screen readers (decorative)
        <View importantForAccessibility="no-hide-descendants">
          {/* skeleton blocks here */}
        </View>
      ) : (
        <View>{/* real content here */}</View>
      )}
    </View>
  );
}

Key idea: one clear, non-spammy loading message/state on the container (busy + label / live update), while keeping skeleton visuals out of the accessibility tree. [1], [4], [7]


Remove individual accessibility announcements from decorative skeletons.

Each skeleton element exposes itself as a progressbar with "Loading..." label. With ~15 skeleton elements across the list (5 cards × 3 skeletons each), this creates excessive screen reader noise. The container already provides a single "Loading groups" announcement, which is sufficient.

Remove the accessibility role and label from individual skeletons since they are decorative placeholders:

🔧 Suggested adjustment
     <Animated.View
       style={[
         {
           opacity,
           width,
           height,
           borderRadius,
           backgroundColor: theme.colors.surfaceVariant,
         },
         style,
       ]}
-      accessibilityRole="progressbar"
-      accessibilityLabel="Loading..."
+      importantForAccessibility="no-hide-descendants"
+      accessibilityElementsHidden={true}
     />

Note: If simply removing the role/label is preferred, use both props above for proper cross-platform support (Android + iOS).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mobile/components/ui/Skeleton.js` around lines 30 - 43, The Skeleton
component's Animated.View currently sets accessibilityRole="progressbar" and
accessibilityLabel="Loading..." which causes excessive screen reader
announcements; remove both accessibilityRole and accessibilityLabel from the
Animated.View in mobile/components/ui/Skeleton.js (the Animated.View instance
rendering the skeleton with style including
opacity/width/height/borderRadius/backgroundColor) so individual skeletons are
treated as decorative and rely on the container's single "Loading groups"
announcement for accessibility.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant