Skip to content

Commit e3635ba

Browse files
authored
Merge pull request #19 from deco-sites/jonasjesus/deco-5273-loading-fallbacks-cls
fix(sections): CLS-safe LoadingFallbacks for Carousel and CategoryBanner (DECO-5273)
2 parents fab44ae + 354ed7a commit e3635ba

3 files changed

Lines changed: 53 additions & 45 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,10 @@
11
export { default, loader } from "../../components/ui/CategoryBanner";
2+
3+
// Reserve the banner's real height to avoid CLS while the URL-matched banner
4+
// resolves: the image is 360x120 on mobile and 1440x200 on desktop.
5+
export const LoadingFallback = () => (
6+
<div
7+
className="w-full h-[120px] sm:h-[200px] bg-base-200"
8+
style={{ contentVisibility: "auto", containIntrinsicSize: "200px" }}
9+
/>
10+
);

src/sections/Images/Carousel.tsx

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -206,20 +206,16 @@ export default Carousel;
206206
export const cache = "listing";
207207

208208
export function LoadingFallback() {
209+
// Reserve the carousel's real footprint to avoid CLS: the banner is a
210+
// full-width hero at min-h-[660px] on mobile and ~600px (1440x600 image) on
211+
// desktop. The previous fallback was a product-grid skeleton — wrong shape
212+
// and far shorter than the banner, causing a large layout shift on load.
209213
return (
210-
<div className="w-full py-8">
211-
<div className="container mx-auto px-4">
212-
<div className="h-6 w-48 bg-base-200 animate-pulse rounded mb-4" />
213-
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
214-
{Array.from({ length: 4 }).map((_, i) => (
215-
<div key={i} className="flex flex-col gap-2">
216-
<div className="aspect-square bg-base-200 animate-pulse rounded" />
217-
<div className="h-4 bg-base-200 animate-pulse rounded w-3/4" />
218-
<div className="h-4 bg-base-200 animate-pulse rounded w-1/2" />
219-
</div>
220-
))}
221-
</div>
222-
</div>
214+
<div
215+
className="w-screen min-h-[660px] sm:min-h-[600px] bg-base-200 flex items-center justify-center"
216+
style={{ contentVisibility: "auto", containIntrinsicSize: "660px" }}
217+
>
218+
<span className="loading loading-spinner" />
223219
</div>
224220
);
225221
}

src/server/cms/sections.gen.ts

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,23 @@
1313
import * as _sync0 from "../../sections/Footer/Footer";
1414
import * as _sync1 from "../../sections/Theme/Theme";
1515
import * as _sync2 from "../../sections/Header/Header";
16-
import { LoadingFallback as _fb0 } from "../../sections/Category/CategoryGrid";
17-
import { LoadingFallback as _fb1 } from "../../sections/Images/Banner";
18-
import { LoadingFallback as _fb2 } from "../../sections/Images/ShoppableBanner";
19-
import { LoadingFallback as _fb3 } from "../../sections/Images/ImageGallery";
20-
import { LoadingFallback as _fb4 } from "../../sections/Images/Carousel";
21-
import { LoadingFallback as _fb5 } from "../../sections/Product/Wishlist";
22-
import { LoadingFallback as _fb6 } from "../../sections/Product/ProductShelf";
23-
import { LoadingFallback as _fb7 } from "../../sections/Product/ShelfWithImage";
24-
import { LoadingFallback as _fb8 } from "../../sections/Product/ProductShelfTabbed";
25-
import { LoadingFallback as _fb9 } from "../../sections/Product/ProductDetails";
26-
import { LoadingFallback as _fb10 } from "../../sections/Miscellaneous/CampaignTimer";
27-
import { LoadingFallback as _fb11 } from "../../sections/Miscellaneous/CookieConsent";
28-
import { LoadingFallback as _fb12 } from "../../sections/Social/WhatsApp";
29-
import { LoadingFallback as _fb13 } from "../../sections/Social/InstagramPosts";
30-
import { LoadingFallback as _fb14 } from "../../sections/Links/LinkTree";
31-
import { LoadingFallback as _fb15 } from "../../sections/Newsletter/Newsletter";
16+
import { LoadingFallback as _fb0 } from "../../sections/Category/CategoryBanner";
17+
import { LoadingFallback as _fb1 } from "../../sections/Category/CategoryGrid";
18+
import { LoadingFallback as _fb2 } from "../../sections/Images/Banner";
19+
import { LoadingFallback as _fb3 } from "../../sections/Images/ShoppableBanner";
20+
import { LoadingFallback as _fb4 } from "../../sections/Images/ImageGallery";
21+
import { LoadingFallback as _fb5 } from "../../sections/Images/Carousel";
22+
import { LoadingFallback as _fb6 } from "../../sections/Product/Wishlist";
23+
import { LoadingFallback as _fb7 } from "../../sections/Product/ProductShelf";
24+
import { LoadingFallback as _fb8 } from "../../sections/Product/ShelfWithImage";
25+
import { LoadingFallback as _fb9 } from "../../sections/Product/ProductShelfTabbed";
26+
import { LoadingFallback as _fb10 } from "../../sections/Product/ProductDetails";
27+
import { LoadingFallback as _fb11 } from "../../sections/Miscellaneous/CampaignTimer";
28+
import { LoadingFallback as _fb12 } from "../../sections/Miscellaneous/CookieConsent";
29+
import { LoadingFallback as _fb13 } from "../../sections/Social/WhatsApp";
30+
import { LoadingFallback as _fb14 } from "../../sections/Social/InstagramPosts";
31+
import { LoadingFallback as _fb15 } from "../../sections/Links/LinkTree";
32+
import { LoadingFallback as _fb16 } from "../../sections/Newsletter/Newsletter";
3233

3334
export interface SectionMetaEntry {
3435
eager?: boolean;
@@ -42,6 +43,7 @@ export interface SectionMetaEntry {
4243

4344
export const sectionMeta: Record<string, SectionMetaEntry> = {
4445
"site/sections/Footer/Footer.tsx": { eager: true, sync: true, layout: true, hasLoadingFallback: true },
46+
"site/sections/Category/CategoryBanner.tsx": { hasLoadingFallback: true },
4547
"site/sections/Category/CategoryGrid.tsx": { hasLoadingFallback: true },
4648
"site/sections/Images/Banner.tsx": { hasLoadingFallback: true },
4749
"site/sections/Images/ShoppableBanner.tsx": { hasLoadingFallback: true },
@@ -71,22 +73,23 @@ export const syncComponents: Record<string, any> = {
7173

7274
export const loadingFallbacks: Record<string, React.ComponentType<any>> = {
7375
"site/sections/Footer/Footer.tsx": _sync0.LoadingFallback,
74-
"site/sections/Category/CategoryGrid.tsx": _fb0,
75-
"site/sections/Images/Banner.tsx": _fb1,
76-
"site/sections/Images/ShoppableBanner.tsx": _fb2,
77-
"site/sections/Images/ImageGallery.tsx": _fb3,
78-
"site/sections/Images/Carousel.tsx": _fb4,
79-
"site/sections/Product/Wishlist.tsx": _fb5,
80-
"site/sections/Product/ProductShelf.tsx": _fb6,
81-
"site/sections/Product/ShelfWithImage.tsx": _fb7,
82-
"site/sections/Product/ProductShelfTabbed.tsx": _fb8,
83-
"site/sections/Product/ProductDetails.tsx": _fb9,
84-
"site/sections/Miscellaneous/CampaignTimer.tsx": _fb10,
85-
"site/sections/Miscellaneous/CookieConsent.tsx": _fb11,
86-
"site/sections/Social/WhatsApp.tsx": _fb12,
87-
"site/sections/Social/InstagramPosts.tsx": _fb13,
76+
"site/sections/Category/CategoryBanner.tsx": _fb0,
77+
"site/sections/Category/CategoryGrid.tsx": _fb1,
78+
"site/sections/Images/Banner.tsx": _fb2,
79+
"site/sections/Images/ShoppableBanner.tsx": _fb3,
80+
"site/sections/Images/ImageGallery.tsx": _fb4,
81+
"site/sections/Images/Carousel.tsx": _fb5,
82+
"site/sections/Product/Wishlist.tsx": _fb6,
83+
"site/sections/Product/ProductShelf.tsx": _fb7,
84+
"site/sections/Product/ShelfWithImage.tsx": _fb8,
85+
"site/sections/Product/ProductShelfTabbed.tsx": _fb9,
86+
"site/sections/Product/ProductDetails.tsx": _fb10,
87+
"site/sections/Miscellaneous/CampaignTimer.tsx": _fb11,
88+
"site/sections/Miscellaneous/CookieConsent.tsx": _fb12,
89+
"site/sections/Social/WhatsApp.tsx": _fb13,
90+
"site/sections/Social/InstagramPosts.tsx": _fb14,
8891
"site/sections/Theme/Theme.tsx": _sync1.LoadingFallback,
89-
"site/sections/Links/LinkTree.tsx": _fb14,
90-
"site/sections/Newsletter/Newsletter.tsx": _fb15,
92+
"site/sections/Links/LinkTree.tsx": _fb15,
93+
"site/sections/Newsletter/Newsletter.tsx": _fb16,
9194
"site/sections/Header/Header.tsx": _sync2.LoadingFallback,
9295
};

0 commit comments

Comments
 (0)