Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions apps/sim/app/(auth)/components/auth-loading-skeleton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* @vitest-environment jsdom
*/
import type { ReactElement } from 'react'
import { renderToStaticMarkup } from 'react-dom/server'
import { describe, expect, it } from 'vitest'
import {
AuthLoadingAlternateActions,
AuthLoadingField,
AuthLoadingFrame,
AuthLoadingSkeleton,
} from '@/app/(auth)/components/auth-loading-skeleton'

function render(element: ReactElement): HTMLDivElement {
const container = document.createElement('div')
container.innerHTML = renderToStaticMarkup(element)
return container
}

describe('auth loading skeletons', () => {
it.each([
['title', 'h-[38px]', 'rounded-[4px]'],
['label', 'h-[14px]', 'rounded-[4px]'],
['control', 'h-[44px]', 'rounded-[10px]'],
['divider', 'h-[1px]', 'rounded-[1px]'],
] as const)('retains the %s placeholder geometry', (shape, height, radius) => {
const container = render(<AuthLoadingSkeleton shape={shape} className='w-[93px]' />)
const skeleton = container.firstElementChild

expect(skeleton?.classList.contains('animate-pulse')).toBe(true)
expect(skeleton?.classList.contains('bg-[var(--surface-active)]')).toBe(true)
expect(skeleton?.classList.contains(height)).toBe(true)
expect(skeleton?.classList.contains(radius)).toBe(true)
expect(skeleton?.classList.contains('w-[93px]')).toBe(true)
})

it('keeps one label, three controls, and one divider in the shared field and actions', () => {
const container = render(
<AuthLoadingFrame>
<AuthLoadingField labelWidthClassName='w-[86px]' />
<AuthLoadingAlternateActions />
</AuthLoadingFrame>
)
const frame = container.firstElementChild
const skeletons = Array.from(container.querySelectorAll('.animate-pulse'))

expect(frame?.classList.contains('flex-col')).toBe(true)
expect(skeletons).toHaveLength(5)
expect(skeletons.filter((el) => el.classList.contains('h-[14px]'))).toHaveLength(1)
expect(skeletons.filter((el) => el.classList.contains('h-[44px]'))).toHaveLength(3)
expect(skeletons.filter((el) => el.classList.contains('h-[1px]'))).toHaveLength(1)
expect(skeletons[0].classList.contains('w-[86px]')).toBe(true)
})
})
58 changes: 58 additions & 0 deletions apps/sim/app/(auth)/components/auth-loading-skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { ReactNode } from 'react'
import { cn, Skeleton } from '@sim/emcn'
import { cva, type VariantProps } from 'class-variance-authority'
Comment thread
BillLeoutsakosvl346 marked this conversation as resolved.

const authLoadingSkeletonVariants = cva('', {
variants: {
shape: {
title: 'h-[38px] rounded-[4px]',
label: 'h-[14px] rounded-[4px]',
control: 'h-[44px] rounded-[10px]',
divider: 'h-[1px] rounded-[1px]',
},
},
})
Comment thread
BillLeoutsakosvl346 marked this conversation as resolved.

interface AuthLoadingSkeletonProps extends VariantProps<typeof authLoadingSkeletonVariants> {
className?: string
}

/** Placeholder geometry shared by the auth route loading states. */
export function AuthLoadingSkeleton({ shape, className }: AuthLoadingSkeletonProps) {
return <Skeleton className={cn(authLoadingSkeletonVariants({ shape }), className)} />
}

interface AuthLoadingFrameProps {
children: ReactNode
}

export function AuthLoadingFrame({ children }: AuthLoadingFrameProps) {
return <div className='flex flex-col items-center'>{children}</div>
}

interface AuthLoadingFieldProps {
labelWidthClassName: string
className?: string
}

export function AuthLoadingField({ labelWidthClassName, className }: AuthLoadingFieldProps) {
return (
<div className={cn('w-full space-y-2', className)}>
<AuthLoadingSkeleton shape='label' className={labelWidthClassName} />
<AuthLoadingSkeleton shape='control' className='w-full' />
</div>
)
}

/** The divider and paired provider-action placeholders on login and signup. */
export function AuthLoadingAlternateActions() {
return (
<>
<AuthLoadingSkeleton shape='divider' className='mt-6 w-full' />
<div className='mt-6 flex w-full gap-3'>
<AuthLoadingSkeleton shape='control' className='flex-1' />
<AuthLoadingSkeleton shape='control' className='flex-1' />
</div>
</>
)
}
33 changes: 14 additions & 19 deletions apps/sim/app/(auth)/login/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
import { Skeleton } from '@sim/emcn'
import {
AuthLoadingAlternateActions,
AuthLoadingField,
AuthLoadingFrame,
AuthLoadingSkeleton,
} from '@/app/(auth)/components/auth-loading-skeleton'

export default function LoginLoading() {
return (
<div className='flex flex-col items-center'>
<Skeleton className='h-[38px] w-[80px] rounded-[4px]' />
<div className='mt-8 w-full space-y-2'>
<Skeleton className='h-[14px] w-[40px] rounded-[4px]' />
<Skeleton className='h-[44px] w-full rounded-[10px]' />
</div>
<div className='mt-4 w-full space-y-2'>
<Skeleton className='h-[14px] w-[64px] rounded-[4px]' />
<Skeleton className='h-[44px] w-full rounded-[10px]' />
</div>
<Skeleton className='mt-6 h-[44px] w-full rounded-[10px]' />
<Skeleton className='mt-6 h-[1px] w-full rounded-[1px]' />
<div className='mt-6 flex w-full gap-3'>
<Skeleton className='h-[44px] flex-1 rounded-[10px]' />
<Skeleton className='h-[44px] flex-1 rounded-[10px]' />
</div>
<Skeleton className='mt-6 h-[14px] w-[200px] rounded-[4px]' />
</div>
<AuthLoadingFrame>
<AuthLoadingSkeleton shape='title' className='w-[80px]' />
<AuthLoadingField labelWidthClassName='w-[40px]' className='mt-8' />
<AuthLoadingField labelWidthClassName='w-[64px]' className='mt-4' />
<AuthLoadingSkeleton shape='control' className='mt-6 w-full' />
<AuthLoadingAlternateActions />
<AuthLoadingSkeleton shape='label' className='mt-6 w-[200px]' />
</AuthLoadingFrame>
)
}
23 changes: 12 additions & 11 deletions apps/sim/app/(auth)/reset-password/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { Skeleton } from '@sim/emcn'
import {
AuthLoadingField,
AuthLoadingFrame,
AuthLoadingSkeleton,
} from '@/app/(auth)/components/auth-loading-skeleton'

export default function ResetPasswordLoading() {
return (
<div className='flex flex-col items-center'>
<Skeleton className='h-[38px] w-[160px] rounded-[4px]' />
<Skeleton className='mt-3 h-[14px] w-[280px] rounded-[4px]' />
<div className='mt-8 w-full space-y-2'>
<Skeleton className='h-[14px] w-[40px] rounded-[4px]' />
<Skeleton className='h-[44px] w-full rounded-[10px]' />
</div>
<Skeleton className='mt-6 h-[44px] w-full rounded-[10px]' />
<Skeleton className='mt-6 h-[14px] w-[120px] rounded-[4px]' />
</div>
<AuthLoadingFrame>
<AuthLoadingSkeleton shape='title' className='w-[160px]' />
<AuthLoadingSkeleton shape='label' className='mt-3 w-[280px]' />
<AuthLoadingField labelWidthClassName='w-[40px]' className='mt-8' />
<AuthLoadingSkeleton shape='control' className='mt-6 w-full' />
<AuthLoadingSkeleton shape='label' className='mt-6 w-[120px]' />
</AuthLoadingFrame>
)
}
38 changes: 15 additions & 23 deletions apps/sim/app/(auth)/signup/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
import { Skeleton } from '@sim/emcn'
import {
AuthLoadingAlternateActions,
AuthLoadingField,
AuthLoadingFrame,
AuthLoadingSkeleton,
} from '@/app/(auth)/components/auth-loading-skeleton'

export default function SignupLoading() {
return (
<div className='flex flex-col items-center'>
<Skeleton className='h-[38px] w-[100px] rounded-[4px]' />
<div className='mt-8 w-full space-y-2'>
<Skeleton className='h-[14px] w-[40px] rounded-[4px]' />
<Skeleton className='h-[44px] w-full rounded-[10px]' />
</div>
<div className='mt-4 w-full space-y-2'>
<Skeleton className='h-[14px] w-[40px] rounded-[4px]' />
<Skeleton className='h-[44px] w-full rounded-[10px]' />
</div>
<div className='mt-4 w-full space-y-2'>
<Skeleton className='h-[14px] w-[64px] rounded-[4px]' />
<Skeleton className='h-[44px] w-full rounded-[10px]' />
</div>
<Skeleton className='mt-6 h-[44px] w-full rounded-[10px]' />
<Skeleton className='mt-6 h-[1px] w-full rounded-[1px]' />
<div className='mt-6 flex w-full gap-3'>
<Skeleton className='h-[44px] flex-1 rounded-[10px]' />
<Skeleton className='h-[44px] flex-1 rounded-[10px]' />
</div>
<Skeleton className='mt-6 h-[14px] w-[220px] rounded-[4px]' />
</div>
<AuthLoadingFrame>
<AuthLoadingSkeleton shape='title' className='w-[100px]' />
<AuthLoadingField labelWidthClassName='w-[40px]' className='mt-8' />
<AuthLoadingField labelWidthClassName='w-[40px]' className='mt-4' />
<AuthLoadingField labelWidthClassName='w-[64px]' className='mt-4' />
<AuthLoadingSkeleton shape='control' className='mt-6 w-full' />
<AuthLoadingAlternateActions />
<AuthLoadingSkeleton shape='label' className='mt-6 w-[220px]' />
</AuthLoadingFrame>
)
}
23 changes: 12 additions & 11 deletions apps/sim/app/(auth)/sso/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { Skeleton } from '@sim/emcn'
import {
AuthLoadingField,
AuthLoadingFrame,
AuthLoadingSkeleton,
} from '@/app/(auth)/components/auth-loading-skeleton'

export default function SSOLoading() {
return (
<div className='flex flex-col items-center'>
<Skeleton className='h-[38px] w-[120px] rounded-[4px]' />
<Skeleton className='mt-3 h-[14px] w-[260px] rounded-[4px]' />
<div className='mt-8 w-full space-y-2'>
<Skeleton className='h-[14px] w-[80px] rounded-[4px]' />
<Skeleton className='h-[44px] w-full rounded-[10px]' />
</div>
<Skeleton className='mt-6 h-[44px] w-full rounded-[10px]' />
<Skeleton className='mt-6 h-[14px] w-[120px] rounded-[4px]' />
</div>
<AuthLoadingFrame>
<AuthLoadingSkeleton shape='title' className='w-[120px]' />
<AuthLoadingSkeleton shape='label' className='mt-3 w-[260px]' />
<AuthLoadingField labelWidthClassName='w-[80px]' className='mt-8' />
<AuthLoadingSkeleton shape='control' className='mt-6 w-full' />
<AuthLoadingSkeleton shape='label' className='mt-6 w-[120px]' />
</AuthLoadingFrame>
)
}
17 changes: 10 additions & 7 deletions apps/sim/app/(auth)/verify/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Skeleton } from '@sim/emcn'
import {
AuthLoadingFrame,
AuthLoadingSkeleton,
} from '@/app/(auth)/components/auth-loading-skeleton'

export default function VerifyLoading() {
return (
<div className='flex flex-col items-center'>
<Skeleton className='h-[38px] w-[180px] rounded-[4px]' />
<Skeleton className='mt-3 h-[14px] w-[300px] rounded-[4px]' />
<Skeleton className='mt-1 h-[14px] w-[240px] rounded-[4px]' />
<Skeleton className='mt-8 h-[44px] w-full rounded-[10px]' />
</div>
<AuthLoadingFrame>
<AuthLoadingSkeleton shape='title' className='w-[180px]' />
<AuthLoadingSkeleton shape='label' className='mt-3 w-[300px]' />
<AuthLoadingSkeleton shape='label' className='mt-1 w-[240px]' />
<AuthLoadingSkeleton shape='control' className='mt-8 w-full' />
</AuthLoadingFrame>
)
}
Loading