diff --git a/src/components/LandingCommunitySection.tsx b/src/components/LandingCommunitySection.tsx index 7fbd364c2..0e32e526a 100644 --- a/src/components/LandingCommunitySection.tsx +++ b/src/components/LandingCommunitySection.tsx @@ -2,6 +2,7 @@ import { Hydrate } from '@tanstack/react-start' import { visible } from '@tanstack/react-start/hydration' import type { LibraryId } from '~/libraries' import { MaintainersSection } from './MaintainersSection' +import { Skeleton, SkeletonGroup } from '~/components/ds/ui' interface LandingCommunitySectionProps { libraryId: LibraryId @@ -10,17 +11,17 @@ interface LandingCommunitySectionProps { function SectionSkeleton({ title }: { title: string }) { return (
-
-
+ +
{Array.from({ length: 4 }).map((_, index) => ( -
))}
-
+
) } diff --git a/src/components/PartnersGrid.tsx b/src/components/PartnersGrid.tsx index 6bb7e8097..f6d318401 100644 --- a/src/components/PartnersGrid.tsx +++ b/src/components/PartnersGrid.tsx @@ -5,6 +5,7 @@ import { PartnerImage, partnerTierBandColor, partnerTierLabels, + partnerTiers, type PartnerTier, } from '~/utils/partners' import { @@ -13,6 +14,7 @@ import { type PartnerPlacementContext, } from '~/utils/partner-placement' import { usePartnerPlacementContext } from '~/utils/usePartnerPlacementContext' +import { Skeleton } from '~/components/ds/ui' import { trackEvent, useTrackedImpression, @@ -155,6 +157,66 @@ function PartnerGridItem({ ) } +/** + * Loading shape for `PartnersGrid`. It walks the same tier config as the real + * grid, so the band heights and cell sizes line up instead of collapsing to a + * uniform placeholder. + */ +export function PartnersGridSkeleton({ + partnersList, + status = 'active', + withSponsorsBand = true, +}: { + partnersList?: PartnersGridProps['partnersList'] + status?: PartnersGridProps['status'] + withSponsorsBand?: boolean +}) { + const items = (partnersList ?? allPartners).filter( + (partner) => partner.status === status, + ) + + return ( +
+ {partnerTiers.map((tier) => { + const count = items.filter((partner) => partner.tier === tier).length + if (count === 0) { + return null + } + const sizing = tierLayout[tier] + return ( + + +
+ {Array.from({ length: count }).map((_, index) => ( +
+ +
+ ))} +
+
+ ) + })} + {withSponsorsBand ? ( + <> + +
+ + + +
+ + ) : null} +
+ ) +} + export function PartnersGrid({ analyticsPlacement = 'grid', partnersList, diff --git a/src/components/PartnersSponsorsSection.tsx b/src/components/PartnersSponsorsSection.tsx index 34dbae7ce..f9881d580 100644 --- a/src/components/PartnersSponsorsSection.tsx +++ b/src/components/PartnersSponsorsSection.tsx @@ -2,9 +2,13 @@ import { Link } from '@tanstack/react-router' import { Hydrate } from '@tanstack/react-start' import { visible } from '@tanstack/react-start/hydration' import { ArrowRightIcon } from '@phosphor-icons/react/ArrowRight' -import { Button } from '~/components/ds/ui' +import { Button, Skeleton, SkeletonGroup } from '~/components/ds/ui' import { OssSponsorsWithQuery } from '~/components/OssSponsorsSection' -import { PartnersGrid, TierBand } from '~/components/PartnersGrid' +import { + PartnersGrid, + PartnersGridSkeleton, + TierBand, +} from '~/components/PartnersGrid' import type { PartnerPlacement } from '~/utils/analytics' type PartnersSponsorsContentProps = { @@ -74,34 +78,13 @@ export function PartnersSponsorsContent({ function PartnersSponsorsSkeleton() { return ( -