Skip to content

Commit f9a7c45

Browse files
authored
fix(settings): align skeleton loading states with actual page layouts (#3967)
* fix(settings): align skeleton loading states with actual page layouts * lint * fix(settings): address PR feedback — deduplicate skeleton, fix import order, remove inline comments
1 parent d0baf5b commit f9a7c45

File tree

13 files changed

+255
-65
lines changed

13 files changed

+255
-65
lines changed

apps/sim/app/workspace/[workspaceId]/settings/[section]/settings.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import { CredentialsSkeleton } from '@/app/workspace/[workspaceId]/settings/comp
1616
import { CustomToolsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/custom-tools/custom-tool-skeleton'
1717
import { GeneralSkeleton } from '@/app/workspace/[workspaceId]/settings/components/general/general-skeleton'
1818
import { InboxSkeleton } from '@/app/workspace/[workspaceId]/settings/components/inbox/inbox-skeleton'
19+
import { IntegrationsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/integrations/integrations-skeleton'
1920
import { McpSkeleton } from '@/app/workspace/[workspaceId]/settings/components/mcp/mcp-skeleton'
21+
import { RecentlyDeletedSkeleton } from '@/app/workspace/[workspaceId]/settings/components/recently-deleted/recently-deleted-skeleton'
2022
import { SkillsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/skills/skill-skeleton'
2123
import { WorkflowMcpServersSkeleton } from '@/app/workspace/[workspaceId]/settings/components/workflow-mcp-servers/workflow-mcp-servers-skeleton'
2224
import type { SettingsSection } from '@/app/workspace/[workspaceId]/settings/navigation'
@@ -52,7 +54,7 @@ const Integrations = dynamic(
5254
import('@/app/workspace/[workspaceId]/settings/components/integrations/integrations').then(
5355
(m) => m.Integrations
5456
),
55-
{ loading: () => <CredentialsSkeleton /> }
57+
{ loading: () => <IntegrationsSkeleton /> }
5658
)
5759
const Credentials = dynamic(
5860
() =>
@@ -145,7 +147,7 @@ const RecentlyDeleted = dynamic(
145147
import(
146148
'@/app/workspace/[workspaceId]/settings/components/recently-deleted/recently-deleted'
147149
).then((m) => m.RecentlyDeleted),
148-
{ loading: () => <SettingsSectionSkeleton /> }
150+
{ loading: () => <RecentlyDeletedSkeleton /> }
149151
)
150152
const AccessControl = dynamic(
151153
() => import('@/ee/access-control/components/access-control').then((m) => m.AccessControl),

apps/sim/app/workspace/[workspaceId]/settings/components/admin/admin-skeleton.tsx

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,71 @@
11
import { Skeleton } from '@/components/emcn'
22

3+
/**
4+
* Skeleton component for admin settings loading state.
5+
* Matches the exact layout structure of the Admin component.
6+
*/
37
export function AdminSkeleton() {
48
return (
59
<div className='flex h-full flex-col gap-6'>
610
<div className='flex items-center justify-between'>
711
<Skeleton className='h-[14px] w-[120px]' />
812
<Skeleton className='h-[20px] w-[36px] rounded-full' />
913
</div>
14+
15+
<div className='h-px bg-[var(--border-secondary)]' />
16+
1017
<div className='flex flex-col gap-2'>
1118
<Skeleton className='h-[14px] w-[340px]' />
1219
<div className='flex gap-2'>
1320
<Skeleton className='h-9 flex-1 rounded-md' />
1421
<Skeleton className='h-9 w-[80px] rounded-md' />
1522
</div>
1623
</div>
17-
<div className='flex flex-col gap-2'>
24+
25+
<div className='h-px bg-[var(--border-secondary)]' />
26+
27+
<div className='flex flex-col gap-3'>
1828
<Skeleton className='h-[14px] w-[120px]' />
19-
<Skeleton className='h-[200px] w-full rounded-lg' />
29+
30+
<div className='flex gap-2'>
31+
<Skeleton className='h-9 flex-1 rounded-md' />
32+
<Skeleton className='h-9 w-[80px] rounded-md' />
33+
</div>
34+
35+
<div className='flex flex-col gap-0.5'>
36+
<div className='flex items-center gap-3 border-[var(--border-secondary)] border-b px-3 py-2'>
37+
<Skeleton className='h-[12px] w-[200px]' />
38+
<Skeleton className='h-[12px] flex-1' />
39+
<Skeleton className='h-[12px] w-[80px]' />
40+
<Skeleton className='h-[12px] w-[80px]' />
41+
<Skeleton className='h-[12px] w-[250px]' />
42+
</div>
43+
44+
{Array.from({ length: 5 }).map((_, i) => (
45+
<div
46+
key={i}
47+
className='flex items-center gap-3 border-[var(--border-secondary)] border-b px-3 py-2 last:border-b-0'
48+
>
49+
<Skeleton className='h-[14px] w-[200px]' />
50+
<Skeleton className='h-[14px] flex-1' />
51+
<Skeleton className='h-[20px] w-[50px] rounded-full' />
52+
<Skeleton className='h-[20px] w-[50px] rounded-full' />
53+
<div className='flex w-[250px] justify-end gap-1'>
54+
<Skeleton className='h-[28px] w-[80px] rounded-md' />
55+
<Skeleton className='h-[28px] w-[64px] rounded-md' />
56+
<Skeleton className='h-[28px] w-[40px] rounded-md' />
57+
</div>
58+
</div>
59+
))}
60+
</div>
61+
62+
<div className='flex items-center justify-between'>
63+
<Skeleton className='h-[14px] w-[160px]' />
64+
<div className='flex gap-1'>
65+
<Skeleton className='h-[28px] w-[64px] rounded-md' />
66+
<Skeleton className='h-[28px] w-[48px] rounded-md' />
67+
</div>
68+
</div>
2069
</div>
2170
</div>
2271
)

apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/api-key-skeleton.tsx

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,31 @@ export function ApiKeysSkeleton() {
2525
return (
2626
<div className='flex h-full flex-col gap-4.5'>
2727
<div className='flex items-center gap-2'>
28-
<Skeleton className='h-[30px] flex-1 rounded-lg' />
29-
<Skeleton className='h-[30px] w-[80px] rounded-md' />
28+
<Skeleton className='h-[38px] flex-1 rounded-lg' />
29+
<Skeleton className='h-[38px] w-[90px] rounded-md' />
3030
</div>
31-
<div className='flex flex-col gap-2'>
32-
<ApiKeySkeleton />
33-
<ApiKeySkeleton />
31+
32+
<div className='min-h-0 flex-1 overflow-y-auto'>
33+
<div className='flex flex-col gap-4.5'>
34+
<div className='flex flex-col gap-2'>
35+
<Skeleton className='h-5 w-[80px]' />
36+
<Skeleton className='h-5 w-[180px]' />
37+
</div>
38+
39+
<div className='flex flex-col gap-2'>
40+
<Skeleton className='h-5 w-[60px]' />
41+
<ApiKeySkeleton />
42+
<ApiKeySkeleton />
43+
</div>
44+
</div>
45+
</div>
46+
47+
<div className='mt-6 flex items-center justify-between'>
48+
<div className='flex items-center gap-2'>
49+
<Skeleton className='h-5 w-[170px]' />
50+
<Skeleton className='h-3 w-3 rounded-full' />
51+
</div>
52+
<Skeleton className='h-5 w-9 rounded-full' />
3453
</div>
3554
</div>
3655
)

apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/api-keys.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,14 @@ export function ApiKeys() {
158158
<div ref={scrollContainerRef} className='min-h-0 flex-1 overflow-y-auto'>
159159
{isLoading ? (
160160
<div className='flex flex-col gap-4.5'>
161+
{/* Workspace section header */}
161162
<div className='flex flex-col gap-2'>
162-
<Skeleton className='h-5 w-[70px]' />
163-
<div className='text-[var(--text-muted)] text-sm'>
164-
<Skeleton className='h-5 w-[140px]' />
165-
</div>
163+
<Skeleton className='h-5 w-[80px]' />
164+
<Skeleton className='h-5 w-[180px]' />
166165
</div>
166+
{/* Personal section header + keys */}
167167
<div className='flex flex-col gap-2'>
168-
<Skeleton className='h-5 w-[55px]' />
168+
<Skeleton className='h-5 w-[60px]' />
169169
<ApiKeySkeleton />
170170
<ApiKeySkeleton />
171171
</div>
@@ -310,6 +310,15 @@ export function ApiKeys() {
310310
</div>
311311

312312
{/* Allow Personal API Keys Toggle - Fixed at bottom */}
313+
{isLoading && canManageWorkspaceKeys && (
314+
<div className='mt-6 flex items-center justify-between'>
315+
<div className='flex items-center gap-2'>
316+
<Skeleton className='h-5 w-[170px]' />
317+
<Skeleton className='h-3 w-3 rounded-full' />
318+
</div>
319+
<Skeleton className='h-5 w-9 rounded-full' />
320+
</div>
321+
)}
313322
{!isLoading && canManageWorkspaceKeys && (
314323
<Tooltip.Provider delayDuration={150}>
315324
<div className='mt-6 flex items-center justify-between'>

apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok-skeleton.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ export function BYOKKeySkeleton() {
99
<div className='flex items-center gap-3'>
1010
<Skeleton className='h-9 w-9 flex-shrink-0 rounded-md' />
1111
<div className='flex min-w-0 flex-col justify-center gap-[1px]'>
12-
<Skeleton className='h-[14px] w-[100px]' />
13-
<Skeleton className='h-[13px] w-[200px]' />
12+
<Skeleton className='h-[16px] w-[100px]' />
13+
<Skeleton className='h-[14px] w-[200px]' />
1414
</div>
1515
</div>
16-
<Skeleton className='h-[32px] w-[72px] rounded-md' />
16+
<div className='flex flex-shrink-0 items-center gap-2'>
17+
<Skeleton className='h-[32px] w-[72px] rounded-md' />
18+
<Skeleton className='h-[32px] w-[64px] rounded-md' />
19+
</div>
1720
</div>
1821
)
1922
}
Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,70 @@
11
import { Skeleton } from '@/components/emcn'
22

3-
const GRID_COLS = 'grid grid-cols-[minmax(0,1fr)_8px_minmax(0,1fr)_auto] items-center'
3+
const GRID_COLS = 'grid grid-cols-[minmax(0,1fr)_8px_minmax(0,1fr)_auto_auto] items-center'
4+
const COL_SPAN_ALL = 'col-span-5'
45

56
/**
6-
* Skeleton component for a single secret row in the grid layout.
7+
* Skeleton for a single integration credential row.
78
*/
89
export function CredentialSkeleton() {
910
return (
10-
<div className={GRID_COLS}>
11+
<div className='flex items-center justify-between gap-3'>
12+
<div className='flex min-w-0 items-center gap-2.5'>
13+
<Skeleton className='h-8 w-8 flex-shrink-0 rounded-md' />
14+
<div className='flex min-w-0 flex-col justify-center gap-[1px]'>
15+
<Skeleton className='h-4 w-[120px] rounded' />
16+
<Skeleton className='h-3.5 w-[160px] rounded' />
17+
</div>
18+
</div>
19+
<div className='flex flex-shrink-0 items-center gap-1'>
20+
<Skeleton className='h-9 w-[60px] rounded-md' />
21+
<Skeleton className='h-9 w-[88px] rounded-md' />
22+
</div>
23+
</div>
24+
)
25+
}
26+
27+
/**
28+
* Skeleton for a single secret row matching the credentials grid layout.
29+
*/
30+
function CredentialRowSkeleton() {
31+
return (
32+
<div className='contents'>
1133
<Skeleton className='h-9 rounded-md' />
1234
<div />
1335
<Skeleton className='h-9 rounded-md' />
14-
<div className='ml-2 flex items-center gap-0'>
15-
<Skeleton className='h-9 w-9 rounded-md' />
16-
<Skeleton className='h-9 w-9 rounded-md' />
17-
</div>
36+
<Skeleton className='ml-2 h-9 w-[60px] rounded-md' />
37+
<Skeleton className='h-9 w-9 rounded-md' />
1838
</div>
1939
)
2040
}
2141

2242
/**
23-
* Skeleton for the Secrets section shown during dynamic import loading.
43+
* Skeleton for the Credentials (Secrets) page shown during dynamic import loading.
2444
*/
2545
export function CredentialsSkeleton() {
2646
return (
2747
<div className='flex h-full flex-col gap-4'>
2848
<div className='flex items-center gap-2'>
2949
<Skeleton className='h-[30px] flex-1 rounded-lg' />
30-
<Skeleton className='h-[30px] w-[56px] rounded-md' />
3150
<Skeleton className='h-[30px] w-[50px] rounded-md' />
3251
</div>
33-
<div className='flex flex-col gap-2'>
34-
<Skeleton className='h-5 w-[70px]' />
35-
<div className='text-[var(--text-muted)] text-small'>
36-
<Skeleton className='h-5 w-[160px]' />
52+
53+
<div className='min-h-0 flex-1 overflow-y-auto'>
54+
<div className='flex flex-col gap-4'>
55+
<div className={`${GRID_COLS} gap-y-2`}>
56+
<Skeleton className={`${COL_SPAN_ALL} h-5 w-[70px]`} />
57+
<CredentialRowSkeleton />
58+
<CredentialRowSkeleton />
59+
60+
<div className={`${COL_SPAN_ALL} h-[8px]`} />
61+
62+
<Skeleton className={`${COL_SPAN_ALL} h-5 w-[55px]`} />
63+
<CredentialRowSkeleton />
64+
<CredentialRowSkeleton />
65+
</div>
3766
</div>
3867
</div>
39-
<div className='flex flex-col gap-2'>
40-
<Skeleton className='h-5 w-[55px]' />
41-
<CredentialSkeleton />
42-
<CredentialSkeleton />
43-
</div>
4468
</div>
4569
)
4670
}

apps/sim/app/workspace/[workspaceId]/settings/components/custom-tools/custom-tool-skeleton.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ export function CustomToolSkeleton() {
77
return (
88
<div className='flex items-center justify-between gap-3'>
99
<div className='flex min-w-0 flex-col justify-center gap-[1px]'>
10-
<Skeleton className='h-[14px] w-[100px]' />
11-
<Skeleton className='h-[13px] w-[200px]' />
10+
<Skeleton className='h-4 w-[100px]' />
11+
<Skeleton className='h-3.5 w-[200px]' />
1212
</div>
1313
<div className='flex flex-shrink-0 items-center gap-2'>
14-
<Skeleton className='h-[30px] w-[40px] rounded-sm' />
14+
<Skeleton className='h-[30px] w-[52px] rounded-sm' />
1515
<Skeleton className='h-[30px] w-[54px] rounded-sm' />
1616
</div>
1717
</div>

apps/sim/app/workspace/[workspaceId]/settings/components/general/general-skeleton.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ export function GeneralSkeleton() {
1111
<Skeleton className='h-9 w-9 rounded-full' />
1212
<div className='flex flex-1 flex-col justify-center gap-[1px]'>
1313
<div className='flex items-center gap-2'>
14-
<Skeleton className='h-5 w-24' />
14+
<Skeleton className='h-4 w-24' />
1515
<Skeleton className='h-[10.5px] w-[10.5px]' />
1616
</div>
17-
<Skeleton className='h-5 w-40' />
17+
<Skeleton className='h-3.5 w-40' />
1818
</div>
1919
</div>
2020

0 commit comments

Comments
 (0)