Add and use reusable loading state to resource lists
What does this MR do and why?
We use skeleton loaders as placeholders on lists on three lists. At least I found it in three:
- Issues List
- Explore - Ai Catalog List
- Dashboard List
I wanted to create a reusable component which we can easily use everywhere. I decided to put it the directory app/assets/javascripts/vue_shared/components/resource_lists/ which is the new reusable component for resource lists, coming from this epic &13781 (closed)
It is configurable in a way that we can set the number of lines for the left and right loading skeletons, and how many items we want to render in one list. It is not possible to configure the widths of the skeleton bars, because we currently don't need this.
Screenshots or screen recordings
| Without loading for reference | Before | After |
|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
| - | ![]() |
![]() |
Responsive behavior:
Screen_Recording_2025-07-30_at_11.01.59
How to set up and validate locally
Storybook
- Start Storybook with
yarn storybook:start - Visit http://localhost:9002/?path=/docs/vue-shared-components-resource-lists-loading-state-list--docs
- Visit http://localhost:9002/?path=/docs/vue-shared-components-resource-lists-loading-state-list-item--docs
Loading states mock
Apply this mock to set the `v-if`'s to true for endless spinners
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
index 797d1642e716..a35a5b1337c9 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
@@ -384,7 +384,7 @@ export default {
</issuable-bulk-edit-sidebar>
<slot name="list-body"></slot>
<loading-state-list
- v-if="issuablesLoading"
+ v-if="true"
:left-lines-count="3"
:list-length="skeletonItemCount"
/>
diff --git a/ee/app/assets/javascripts/ai/catalog/components/ai_catalog_list.vue b/ee/app/assets/javascripts/ai/catalog/components/ai_catalog_list.vue
index 7a95cd586fd3..6aa094f475ab 100644
--- a/ee/app/assets/javascripts/ai/catalog/components/ai_catalog_list.vue
+++ b/ee/app/assets/javascripts/ai/catalog/components/ai_catalog_list.vue
@@ -57,7 +57,7 @@ export default {
<template>
<div data-testid="ai-catalog-list">
- <loading-state-list v-if="isLoading" />
+ <loading-state-list v-if="true" />
<template v-else-if="items.length > 0">
<ul class="gl-list-style-none gl-m-0 gl-p-0">
diff --git a/ee/app/assets/javascripts/analytics/analytics_dashboards/components/dashboards_list.vue b/ee/app/assets/javascripts/analytics/analytics_dashboards/components/dashboards_list.vue
index d4e8c602c946..a43e9e9b8a21 100644
--- a/ee/app/assets/javascripts/analytics/analytics_dashboards/components/dashboards_list.vue
+++ b/ee/app/assets/javascripts/analytics/analytics_dashboards/components/dashboards_list.vue
@@ -321,7 +321,7 @@ export default {
@error="onError"
/>
- <loading-state-list v-if="isLoading" />
+ <loading-state-list v-if="true" :right-lines-count="1" />
<template v-else>
<dashboard-list-item
@@ -333,8 +333,8 @@ export default {
@clone="onCloneDashboard"
/>
</template>
- <li v-if="loadingNewDashboard" class="!gl-px-5">
- <loading-state-list-item />
+ <li v-if="true" class="!gl-px-5">
+ <loading-state-list-item :right-lines-count="1" />
</li>
</ul>
</div>
app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
ee/app/assets/javascripts/ai/catalog/components/ai_catalog_list.vue
- Enable the feature flag:
echo "Feature.enable(:global_ai_catalog)" | rails c - Visit http://gdk.test:3000/explore/ai-catalog/agents
ee/app/assets/javascripts/analytics/analytics_dashboards/components/dashboards_list.vue
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Related to #554018 (closed)










