Add front component skeleton loader (#23261)

Front components (dashboard widget, side panel, settings preview) showed
blank space during their entire load. They now show a shimmering
full-area skeleton continuously, from the lazy chunk load through
metadata fetch, token/SDK wait, and worker boot, until the real UI
mounts.

The skeleton is threaded down as an optional `loadingFallback` prop so
the shared `twenty-front-component-renderer` package stays
dependency-free (react-loading-skeleton stays in twenty-front). The
command-menu headless component opts out by not passing a fallback, so
it stays blank as before.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/23261?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Raphaël Bosi
2026-07-24 14:09:16 +02:00
committed by GitHub
parent 3a8f086d15
commit 3ee8fc0973
6 changed files with 62 additions and 8 deletions
@@ -3,6 +3,7 @@ import { Suspense, lazy } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { FrontComponentSkeletonLoader } from '@/front-components/components/FrontComponentSkeletonLoader';
import { usePageLayoutContentContext } from '@/page-layout/contexts/PageLayoutContentContext';
import { useIsPageLayoutInEditMode } from '@/page-layout/hooks/useIsPageLayoutInEditMode';
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
@@ -57,10 +58,11 @@ export const FrontComponentWidgetRenderer = ({
isCanvasLayout={layoutMode === PageLayoutTabLayoutMode.CANVAS}
isInEditMode={isPageLayoutInEditMode}
>
<Suspense fallback={null}>
<Suspense fallback={<FrontComponentSkeletonLoader />}>
<FrontComponentRenderer
frontComponentId={frontComponentId}
selectedRecordIds={selectedRecordIds}
loadingFallback={<FrontComponentSkeletonLoader />}
/>
</Suspense>
</StyledContainer>