Skip to content

Conversation

@gocanto
Copy link
Contributor

@gocanto gocanto commented Oct 3, 2025

Summary

  • add a skeleton partial for the articles list to preserve layout while content loads
  • update the articles list component to manage loading state and render skeleton entries that match the loaded height
  • extend partial tests to cover the skeleton behaviour and ensure the previous item count drives the skeleton size

Summary by CodeRabbit

  • New Features

    • Animated skeleton placeholders for article lists and post pages; skeleton components added with responsive layouts and an isAnimated prop (defaults on).
    • Skeleton count adapts to prior results; "No articles found." message and ARIA busy state during loading.
    • Debounced category-triggered fetch with cancellation on unmount.
  • Bug Fixes

    • Prevented stale responses with request deduplication and rollback to prior items on error/cancel to reduce flicker.
  • Tests

    • Added tests for skeleton display, transitions, refresh behavior, and error handling.

@coderabbitai
Copy link

coderabbitai bot commented Oct 3, 2025

Caution

Review failed

The pull request is closed.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds skeleton UI components and integrates them into list and post pages: new ArticleItemSkeletonPartial and PostPageSkeletonPartial components; ArticlesListPartial now renders skeletons with isLoading, skeletonCount, debounced fetch, lastRequestId guarding, rollback on error, and cancellation on unmount; PostPage shows a skeleton while loading. Tests updated to cover loading, refresh, and error flows.

Changes

Cohort / File(s) Summary
Article item skeleton
src/partials/ArticleItemSkeletonPartial.vue
New Vue 3 SFC rendering an article-item skeleton. Accepts isAnimated?: boolean (default true), computes animationClass, and registers the component name via defineOptions.
Post page skeleton
src/partials/PostPageSkeletonPartial.vue
New Vue 3 SFC providing a post-page skeleton layout with animated placeholders; registered via defineOptions.
Articles list loading & fetch flow
src/partials/ArticlesListPartial.vue
Reworked to support skeleton loading: adds isLoading, DEFAULT_SKELETON_COUNT, skeletonCount, skeletonCountFor helper, lastRequestId request-deduplication, debounced fetch with cancellation (onBeforeUnmount), and rollback to previous items on error; integrates ArticleItemSkeletonPartial and ARIA busy state.
Post page loading flow
src/pages/PostPage.vue
Adds isLoading state, renders PostPageSkeletonPartial while loading, shows post on success, and an explicit error message when fetch fails; isLoading cleared in finally.
ArticlesList tests
tests/partials/ArticlesListPartial.test.ts
Expanded tests: reactive apiStore mock, multiple posts, debounce stubbed to no-op, verifies skeletons show during load and items after load, and tests refresh behavior preserving previous counts and resolving refresh promise.
PostPage tests
tests/pages/PostPage.test.ts
Adds assertions that post-page-skeleton is present during initial load, removed after success, and hidden with an error message on failure.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant List as ArticlesListPartial
  participant API as Store/API
  participant Skeleton as ArticleItemSkeletonPartial

  U->>List: Trigger fetch (mount / search / refresh)
  activate List
  List->>List: lastRequestId = newId\nisLoading = true\nskeletonCount = skeletonCountFor(prevItems)
  List->>Skeleton: Render N skeletons (skeletonCount)
  List->>API: getCategories() (if needed)
  List->>API: getPosts(reqId)
  note right of List: Deduplicate via lastRequestId\nIgnore stale responses
  API-->>List: posts / error
  alt latest response
    List->>List: Update items or restore previous on error\nisLoading = false
    List->>List: Render ArticleItemPartial list
  else stale response
    List-->>List: Ignore result
  end
  deactivate List
Loading
sequenceDiagram
  autonumber
  actor U as User
  participant Page as PostPage
  participant API as Store/API
  participant Skeleton as PostPageSkeletonPartial

  U->>Page: Navigate to post
  activate Page
  Page->>Page: isLoading = true
  Page->>Skeleton: Render skeleton
  Page->>API: fetchPost(id)
  API-->>Page: post / error
  alt success
    Page->>Page: render post\nisLoading = false
  else error
    Page->>Page: show "We couldn't load this post."\nisLoading = false
  end
  deactivate Page
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

I nibble code in twilight hush,
Soft pulses bloom where loaders flush,
I guard requests from stale old bites,
Till posts hop in on moonlit nights.
A rabbit cheer — the meadow loads! 🐇✨

Pre-merge checks and finishing touches

✅ 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 clearly and concisely describes the primary change of adding a skeleton loader for articles, matching the main updates to the article list and loading states in the changeset.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32c0de1 and 2f7da7a.

📒 Files selected for processing (2)
  • src/partials/ArticlesListPartial.vue (2 hunks)
  • tests/partials/ArticlesListPartial.test.ts (3 hunks)

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.

@gocanto gocanto marked this pull request as draft October 3, 2025 04:04
@gemini-code-assist
Copy link

Summary of Changes

Hello @gocanto, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the user experience of the article list by introducing a skeleton loader. When articles are being fetched, users will now see a visually consistent placeholder, preventing layout shifts and providing immediate feedback, making the application feel more responsive and polished.

Highlights

  • New Skeleton Component: A new Vue component, ArticleItemSkeletonPartial.vue, has been added to display a placeholder for an article item while content is loading.
  • Loading State Management: The ArticlesListPartial.vue component now includes logic to manage a loading state (isLoading) and dynamically render skeleton entries. The number of skeletons displayed is determined by the count of previously loaded items or a default value.
  • Enhanced Data Fetching Logic: The fetchPosts method in ArticlesListPartial.vue has been updated to handle loading states, clear existing items, and prevent race conditions during concurrent data requests using a requestId mechanism.
  • Extended Test Coverage: New tests have been added to ArticlesListPartial.test.ts to verify the correct rendering of skeleton loaders during data fetching and to ensure the skeleton count adapts based on the previous list size.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gocanto gocanto removed the codex label Oct 3, 2025
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a skeleton loader for the articles list, which is a great enhancement for user experience. The implementation is solid, using a new ArticleItemSkeletonPartial component and updating ArticlesListPartial to manage the loading state. The logic to handle race conditions during data fetching is well-implemented. The tests have also been updated to cover the new loading behavior, which is excellent. I have one suggestion to refactor the fetchPosts function for better maintainability by reducing some code duplication.

@gocanto gocanto added testing and removed testing labels Oct 3, 2025
@gocanto gocanto added the testing label Oct 3, 2025
@gocanto gocanto changed the title Add skeleton loader for article list feat: Add skeleton loader for articles Oct 3, 2025
@gocanto gocanto marked this pull request as ready for review October 3, 2025 06:37
Copy link

@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: 2

♻️ Duplicate comments (2)
src/partials/ArticlesListPartial.vue (2)

65-92: LGTM!

The fetchPosts implementation correctly handles:

  • Request deduplication via lastRequestId to prevent race conditions
  • Skeleton count preservation based on previous results
  • Error recovery by restoring previous items
  • Proper cleanup in the finally block

The current structure with pre-fetch skeleton setup (line 69) and post-fetch update (line 88) is correct and necessary for the loading UX flow.


65-92: Previous review suggestion about consolidating skeletonCount update.

A prior reviewer suggested moving the skeletonCount update to the finally block to reduce duplication. This is a valid refactor that would consolidate the skeleton count logic.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 253380d and 32c0de1.

📒 Files selected for processing (5)
  • src/pages/PostPage.vue (6 hunks)
  • src/partials/ArticlesListPartial.vue (3 hunks)
  • src/partials/PostPageSkeletonPartial.vue (1 hunks)
  • tests/pages/PostPage.test.ts (2 hunks)
  • tests/partials/ArticlesListPartial.test.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
tests/pages/PostPage.test.ts (1)
src/stores/api/store.ts (1)
  • getPost (123-131)
tests/partials/ArticlesListPartial.test.ts (1)
src/stores/api/store.ts (2)
  • getPosts (114-122)
  • getCategories (105-113)
🪛 GitHub Actions: Unit Tests
tests/partials/ArticlesListPartial.test.ts

[error] 187-187: AssertionError: expected [] to have a length of 3 but got +0

🪛 GitHub Check: vitest
tests/partials/ArticlesListPartial.test.ts

[failure] 187-187: tests/partials/ArticlesListPartial.test.ts > ArticlesListPartial > uses the previous result count while refreshing the list
AssertionError: expected [] to have a length of 3 but got +0

  • Expected
  • Received
  • 3
  • 0

❯ tests/partials/ArticlesListPartial.test.ts:187:21

🔇 Additional comments (14)
src/partials/PostPageSkeletonPartial.vue (2)

1-41: LGTM!

The skeleton component is well-structured with appropriate accessibility attributes (aria-hidden="true") and animation classes. The implementation correctly provides a loading placeholder that matches the post page layout.


1-41: LGTM! Well-structured skeleton component.

The component correctly implements a loading placeholder with proper accessibility (aria-hidden="true") and testability (data-testid). The skeleton structure mirrors the actual post layout, providing good visual continuity during loading.

src/partials/ArticlesListPartial.vue (4)

24-29: LGTM!

The conditional rendering correctly shows skeleton loaders during the loading state and displays items when available. The use of aria-busy="true" on the loading container improves accessibility.


95-112: LGTM!

The debounced fetch pattern is well-implemented:

  • Correct lodash debounce configuration with leading: true, trailing: true
  • Proper lifecycle cleanup via onBeforeUnmount to cancel pending debounced calls
  • Prevents memory leaks and unnecessary API calls

61-92: Approve: Race condition prevention with lastRequestId.

The request deduplication pattern using lastRequestId correctly prevents stale responses from updating state. The logic to restore previousItems on error and guard state updates with requestId === lastRequestId is sound.


95-112: Approve: Proper debounce configuration and cleanup.

The debounced fetch with leading: true, trailing: true provides immediate feedback while preventing excess requests. The onBeforeUnmount hook correctly cancels pending debounced calls.

tests/pages/PostPage.test.ts (4)

73-76: LGTM!

The test correctly verifies the skeleton's presence during the initial loading state and its removal after the data is loaded. This aligns with the expected behavior of the loading flow in PostPage.vue.


138-139: LGTM!

The test correctly validates the error state behavior: skeleton is hidden and the fallback error message "We couldn't load this post." is displayed when loading fails.


60-78: Approve: Skeleton loading assertions.

The test correctly verifies that the skeleton is present during initial load (line 73) and disappears after successful fetch (line 76), ensuring the loading UX works as intended.


120-140: Approve: Error handling with skeleton cleanup.

The test properly asserts that the skeleton is removed (line 138) and the error message is displayed (line 139) when the fetch fails, confirming graceful error handling.

src/pages/PostPage.vue (4)

30-32: LGTM!

The conditional rendering correctly manages the loading, success, and error states:

  • Skeleton is shown during loading
  • Post content is rendered when available
  • Fallback error message appears when loading fails

Also applies to: 103-103


145-145: LGTM!

The loading state is correctly managed: initialized to true and set to false in the finally block after the fetch attempt, ensuring the skeleton is hidden regardless of success or failure.

Also applies to: 212-214


30-32: Approve: Clear loading and error states.

The conditional rendering flow is well-structured:

  • Skeleton shown during loading (line 30)
  • Article content shown when post exists (line 32)
  • Error message shown when load fails (line 103)

This provides good user feedback for all states.

Also applies to: 103-103


145-145: Approve: Proper loading state management.

The isLoading ref is correctly initialized to true (line 145) and set to false in the finally block (line 213), ensuring the loading state is cleared regardless of success or error.

Also applies to: 205-214

@gocanto gocanto marked this pull request as draft October 3, 2025 06:54
@gocanto gocanto marked this pull request as ready for review October 3, 2025 07:32
@gocanto gocanto merged commit ecb889b into main Oct 3, 2025
2 of 5 checks passed
@gocanto gocanto deleted the gocanto/add-article-list-skeleton-loader-2025-10-03 branch October 3, 2025 07:33
@coderabbitai coderabbitai bot mentioned this pull request Nov 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants