Skip to content

Commit ec98130

Browse files
FelixMalfaitclaude
andauthored
fix(admin-panel): inline skeleton loaders for table sections (#20014)
## Summary \`SettingsSkeletonLoader\` wraps its content in \`PageHeader\` + \`PageBody\`, which is right for **full-page replacement** (user detail, config variable detail, etc.) but renders as a large empty stub with one tiny floating bar when placed **inline inside a section that's already scaffolded**. That's what showed up in Recent Users, Top Workspaces, and the Chats tab in the admin panel — a jarring white page flash where a few row placeholders should be. This PR adds \`SettingsAdminSectionSkeletonLoader\` — a small, configurable-row-count skeleton that uses the project's standard \`SkeletonTheme\` pattern (\`theme.background.tertiary\` / \`theme.background.transparent.lighter\` + \`borderRadius: 4\`, matching \`PageContentSkeletonLoader\` and \`SettingsAdminTabSkeletonLoader\`) and renders row-height bars that match \`TableRow\` spacing. Swaps it into the three inline call sites. Full-page usages of \`SettingsSkeletonLoader\` are unchanged. ### Changed - **New**: \`packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminSectionSkeletonLoader.tsx\` - **Swapped** (3 inline loading states): \`SettingsAdminGeneral.tsx\` (Recent Users + Top Workspaces), \`SettingsAdminWorkspaceDetail.tsx\` (Chats tab) ## Test plan - [x] typecheck (\`npx nx typecheck twenty-front --skip-nx-cache\`) — clean - [x] oxlint — 0 warnings - [x] prettier — clean - [ ] Visual: navigate to admin panel, observe Recent Users / Top Workspaces / Chats tab loading — should see a tight stack of row-height placeholder bars instead of a big empty page stub 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b1838b3 commit ec98130

11 files changed

Lines changed: 53 additions & 101 deletions

File tree

packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountLoader.tsx

Lines changed: 0 additions & 16 deletions
This file was deleted.

packages/twenty-front/src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { GET_AI_PROVIDERS } from '@/settings/admin-panel/ai/graphql/queries/getA
2525
import { type GetAiProvidersResult } from '@/settings/admin-panel/ai/types/GetAiProvidersResult';
2626
import { parseProviderItems } from '@/settings/admin-panel/ai/utils/parseProviderItems';
2727
import { getModelIcon } from '@/settings/ai/utils/getModelIcon';
28-
import { SettingsAdminTabSkeletonLoader } from '@/settings/admin-panel/components/SettingsAdminTabSkeletonLoader';
28+
import { SettingsSectionSkeletonLoader } from '@/settings/components/SettingsSectionSkeletonLoader';
2929
import { SettingsEnterpriseFeatureGateCard } from '@/settings/components/SettingsEnterpriseFeatureGateCard';
3030
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
3131
import { useUsageValueFormatter } from '@/settings/usage/hooks/useUsageValueFormatter';
@@ -128,7 +128,7 @@ export const SettingsAdminAI = () => {
128128
);
129129

130130
if (isLoadingProviders || isLoadingModels) {
131-
return <SettingsAdminTabSkeletonLoader />;
131+
return <SettingsSectionSkeletonLoader />;
132132
}
133133

134134
const handleRecommendedToggle = async (

packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminGeneral.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { canManageFeatureFlagsState } from '@/client-config/states/canManageFeatureFlagsState';
22
import { useApolloAdminClient } from '@/settings/admin-panel/apollo/hooks/useApolloAdminClient';
3+
import { SettingsSectionSkeletonLoader } from '@/settings/components/SettingsSectionSkeletonLoader';
34
import { SettingsAdminVersionContainer } from '@/settings/admin-panel/components/SettingsAdminVersionContainer';
45
import { ADMIN_PANEL_RECENT_USERS } from '@/settings/admin-panel/graphql/queries/adminPanelRecentUsers';
56
import { ADMIN_PANEL_TOP_WORKSPACES } from '@/settings/admin-panel/graphql/queries/adminPanelTopWorkspaces';
6-
import { SettingsSkeletonLoader } from '@/settings/components/SettingsSkeletonLoader';
77
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
88
import { Table } from '@/ui/layout/table/components/Table';
99
import { TableBody } from '@/ui/layout/table/components/TableBody';
@@ -105,7 +105,7 @@ export const SettingsAdminGeneral = () => {
105105
fullWidth
106106
/>
107107
{isLoadingUsers ? (
108-
<SettingsSkeletonLoader />
108+
<SettingsSectionSkeletonLoader />
109109
) : recentUsers.length === 0 ? (
110110
<StyledEmptyState>
111111
{t`No users found matching your search criteria.`}
@@ -154,7 +154,7 @@ export const SettingsAdminGeneral = () => {
154154
fullWidth
155155
/>
156156
{isLoadingWorkspaces ? (
157-
<SettingsSkeletonLoader />
157+
<SettingsSectionSkeletonLoader />
158158
) : topWorkspaces.length === 0 ? (
159159
<StyledEmptyState>
160160
{t`No workspaces found matching your search criteria.`}

packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminTabSkeletonLoader.tsx

Lines changed: 0 additions & 18 deletions
This file was deleted.

packages/twenty-front/src/modules/settings/admin-panel/config-variables/components/SettingsAdminConfigVariables.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { SettingsAdminTabSkeletonLoader } from '@/settings/admin-panel/components/SettingsAdminTabSkeletonLoader';
1+
import { SettingsSectionSkeletonLoader } from '@/settings/components/SettingsSectionSkeletonLoader';
22
import { useApolloAdminClient } from '@/settings/admin-panel/apollo/hooks/useApolloAdminClient';
33
import { ConfigVariableFilterContainer } from '@/settings/admin-panel/config-variables/components/ConfigVariableFilterContainer';
44
import { ConfigVariableFilterDropdown } from '@/settings/admin-panel/config-variables/components/ConfigVariableFilterDropdown';
@@ -160,7 +160,7 @@ export const SettingsAdminConfigVariables = () => {
160160
}, [filteredVariables, allGroups]);
161161

162162
if (configVariablesLoading) {
163-
return <SettingsAdminTabSkeletonLoader />;
163+
return <SettingsSectionSkeletonLoader />;
164164
}
165165

166166
return (

packages/twenty-front/src/modules/settings/admin-panel/health-status/components/SettingsAdminHealthStatus.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useApolloAdminClient } from '@/settings/admin-panel/apollo/hooks/useApolloAdminClient';
2-
import { SettingsAdminTabSkeletonLoader } from '@/settings/admin-panel/components/SettingsAdminTabSkeletonLoader';
2+
import { SettingsSectionSkeletonLoader } from '@/settings/components/SettingsSectionSkeletonLoader';
33
import { SettingsAdminHealthStatusListCard } from '@/settings/admin-panel/health-status/components/SettingsAdminHealthStatusListCard';
44
import { SettingsAdminMaintenanceModeFetchEffect } from '@/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceModeFetchEffect';
55
import { SettingsAdminMaintenanceMode } from '@/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode';
@@ -22,7 +22,7 @@ export const SettingsAdminHealthStatus = () => {
2222
const services = data?.getSystemHealthStatus.services ?? [];
2323

2424
if (loadingHealthStatus) {
25-
return <SettingsAdminTabSkeletonLoader />;
25+
return <SettingsSectionSkeletonLoader />;
2626
}
2727

2828
return (
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { styled } from '@linaria/react';
2+
import { useContext } from 'react';
3+
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
4+
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
5+
6+
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
7+
8+
type SettingsSectionSkeletonLoaderProps = {
9+
rowCount?: number;
10+
};
11+
12+
const StyledRows = styled.div`
13+
display: flex;
14+
flex-direction: column;
15+
gap: ${themeCssVariables.spacing[2]};
16+
width: 100%;
17+
`;
18+
19+
export const SettingsSectionSkeletonLoader = ({
20+
rowCount = 4,
21+
}: SettingsSectionSkeletonLoaderProps) => {
22+
const { theme } = useContext(ThemeContext);
23+
24+
return (
25+
<StyledRows>
26+
<SkeletonTheme
27+
baseColor={theme.background.tertiary}
28+
highlightColor={theme.background.transparent.lighter}
29+
borderRadius={4}
30+
>
31+
<Skeleton
32+
count={rowCount}
33+
height={SKELETON_LOADER_HEIGHT_SIZES.standard.l}
34+
/>
35+
</SkeletonTheme>
36+
</StyledRows>
37+
);
38+
};

packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { SettingsPath } from 'twenty-shared/types';
2-
import { SettingsAccountLoader } from '@/settings/accounts/components/SettingsAccountLoader';
2+
import { SettingsSectionSkeletonLoader } from '@/settings/components/SettingsSectionSkeletonLoader';
33
import { SettingsAccountsBlocklistSection } from '@/settings/accounts/components/SettingsAccountsBlocklistSection';
44
import { SettingsAccountsConnectedAccountsListCard } from '@/settings/accounts/components/SettingsAccountsConnectedAccountsListCard';
55
import { SettingsAccountsSettingsSection } from '@/settings/accounts/components/SettingsAccountsSettingsSection';
@@ -29,7 +29,7 @@ export const SettingsAccounts = () => {
2929
>
3030
<SettingsPageContainer>
3131
{loading ? (
32-
<SettingsAccountLoader />
32+
<SettingsSectionSkeletonLoader />
3333
) : (
3434
<>
3535
<Section>

packages/twenty-front/src/pages/settings/admin-panel/SettingsAdminWorkspaceDetail.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
1010
import { canManageFeatureFlagsState } from '@/client-config/states/canManageFeatureFlagsState';
1111
import { AI_ADMIN_PATH } from '@/settings/admin-panel/ai/constants/AiAdminPath';
1212
import { useApolloAdminClient } from '@/settings/admin-panel/apollo/hooks/useApolloAdminClient';
13+
import { SettingsSectionSkeletonLoader } from '@/settings/components/SettingsSectionSkeletonLoader';
1314
import { SettingsAdminWorkspaceContent } from '@/settings/admin-panel/components/SettingsAdminWorkspaceContent';
1415
import { GET_ADMIN_WORKSPACE_CHAT_THREADS } from '@/settings/admin-panel/graphql/queries/getAdminWorkspaceChatThreads';
1516
import { WORKSPACE_LOOKUP_ADMIN_PANEL } from '@/settings/admin-panel/graphql/queries/workspaceLookupAdminPanel';
@@ -304,7 +305,7 @@ export const SettingsAdminWorkspaceDetail = () => {
304305
description={t`AI chat threads for this workspace`}
305306
/>
306307
{isLoadingThreads ? (
307-
<SettingsSkeletonLoader />
308+
<SettingsSectionSkeletonLoader />
308309
) : threads.length === 0 ? (
309310
<Card rounded>
310311
<TableRow gridTemplateColumns="1fr">

packages/twenty-front/src/pages/settings/applications/SettingsApplicationDetails.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import {
4040
UninstallApplicationDocument,
4141
} from '~/generated-metadata/graphql';
4242
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
43-
import { SettingsApplicationDetailSkeletonLoader } from '~/pages/settings/applications/components/SettingsApplicationDetailSkeletonLoader';
43+
import { SettingsSectionSkeletonLoader } from '@/settings/components/SettingsSectionSkeletonLoader';
4444
import { SettingsApplicationDetailTitle } from '~/pages/settings/applications/components/SettingsApplicationDetailTitle';
4545
import { CUSTOM_APPLICATION_ILLUSTRATIONS } from '~/pages/settings/applications/constants/CustomApplicationIllustrations';
4646
import { STANDARD_APPLICATION_ILLUSTRATIONS } from '~/pages/settings/applications/constants/StandardApplicationIllustrations';
@@ -241,7 +241,7 @@ export const SettingsApplicationDetails = () => {
241241

242242
const renderActiveTabContent = () => {
243243
if (!isDefined(application)) {
244-
return <SettingsApplicationDetailSkeletonLoader />;
244+
return <SettingsSectionSkeletonLoader />;
245245
}
246246

247247
switch (activeTabId) {

0 commit comments

Comments
 (0)