@@ -29,6 +29,7 @@ import {
2929 DropdownMenuItem ,
3030 DropdownMenuTrigger ,
3131} from '@/components/ui/dropdown-menu'
32+ import { Skeleton } from '@/components/ui/skeleton'
3233import { VerifiedBadge } from '@/components/ui/verified-badge'
3334import { useSession } from '@/lib/auth/auth-client'
3435import { cn } from '@/lib/core/utils/cn'
@@ -41,6 +42,95 @@ import { useStarTemplate, useTemplate } from '@/hooks/queries/templates'
4142
4243const logger = createLogger ( 'TemplateDetails' )
4344
45+ interface TemplateDetailsLoadingProps {
46+ isWorkspaceContext ?: boolean
47+ workspaceId ?: string | null
48+ }
49+
50+ function TemplateDetailsLoading ( { isWorkspaceContext, workspaceId } : TemplateDetailsLoadingProps ) {
51+ const breadcrumbItems = [
52+ {
53+ label : 'Templates' ,
54+ href :
55+ isWorkspaceContext && workspaceId ? `/workspace/${ workspaceId } /templates` : '/templates' ,
56+ } ,
57+ { label : 'Template' } ,
58+ ]
59+
60+ return (
61+ < div
62+ className = { cn (
63+ 'flex flex-col' ,
64+ isWorkspaceContext ? 'h-full flex-1 overflow-hidden' : 'min-h-screen'
65+ ) }
66+ >
67+ < div className = { cn ( 'flex flex-1' , isWorkspaceContext && 'overflow-hidden' ) } >
68+ < div
69+ className = { cn (
70+ 'flex flex-1 flex-col px-[24px] pt-[24px] pb-[24px]' ,
71+ isWorkspaceContext ? 'overflow-auto' : 'overflow-visible'
72+ ) }
73+ >
74+ { /* Breadcrumb navigation */ }
75+ < Breadcrumb items = { breadcrumbItems } />
76+
77+ { /* Template name and action buttons */ }
78+ < div className = 'mt-[14px] flex items-center justify-between' >
79+ < Skeleton className = 'h-[27px] w-[250px] rounded-[4px]' />
80+ < div className = 'flex items-center gap-[8px]' >
81+ < Skeleton className = 'h-[32px] w-[80px] rounded-[6px]' />
82+ </ div >
83+ </ div >
84+
85+ { /* Template tagline */ }
86+ < div className = 'mt-[4px]' >
87+ < Skeleton className = 'h-[21px] w-[400px] rounded-[4px]' />
88+ </ div >
89+
90+ { /* Creator and stats row */ }
91+ < div className = 'mt-[16px] flex items-center gap-[8px]' >
92+ { /* Star icon and count */ }
93+ < Skeleton className = 'h-[14px] w-[14px] rounded-[2px]' />
94+ < Skeleton className = 'h-[21px] w-[24px] rounded-[4px]' />
95+
96+ { /* Views icon and count */ }
97+ < Skeleton className = 'h-[16px] w-[16px] rounded-[2px]' />
98+ < Skeleton className = 'h-[21px] w-[32px] rounded-[4px]' />
99+
100+ { /* Vertical divider */ }
101+ < div className = 'mx-[4px] mb-[-1.5px] h-[18px] w-[1.25px] rounded-full bg-[var(--border)]' />
102+
103+ { /* Creator profile pic */ }
104+ < Skeleton className = 'h-[16px] w-[16px] rounded-full' />
105+ { /* Creator name */ }
106+ < Skeleton className = 'h-[21px] w-[100px] rounded-[4px]' />
107+ </ div >
108+
109+ { /* Credentials needed */ }
110+ < div className = 'mt-[12px]' >
111+ < Skeleton className = 'h-[18px] w-[280px] rounded-[4px]' />
112+ </ div >
113+
114+ { /* Canvas preview */ }
115+ < div className = 'relative mt-[24px] h-[450px] w-full flex-shrink-0 overflow-hidden rounded-[8px] border border-[var(--border)]' >
116+ < Skeleton className = 'h-full w-full rounded-none' />
117+ </ div >
118+
119+ { /* About this Workflow */ }
120+ < div className = 'mt-8' >
121+ < Skeleton className = 'mb-4 h-[24px] w-[180px] rounded-[4px]' />
122+ < div className = 'space-y-2' >
123+ < Skeleton className = 'h-[18px] w-full rounded-[4px]' />
124+ < Skeleton className = 'h-[18px] w-[90%] rounded-[4px]' />
125+ < Skeleton className = 'h-[18px] w-[75%] rounded-[4px]' />
126+ </ div >
127+ </ div >
128+ </ div >
129+ </ div >
130+ </ div >
131+ )
132+ }
133+
44134interface TemplateDetailsProps {
45135 isWorkspaceContext ?: boolean
46136}
@@ -207,11 +297,7 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
207297
208298 if ( loading ) {
209299 return (
210- < div className = 'flex h-screen items-center justify-center' >
211- < div className = 'text-center' >
212- < p className = 'font-sans text-muted-foreground text-sm' > Loading template...</ p >
213- </ div >
214- </ div >
300+ < TemplateDetailsLoading isWorkspaceContext = { isWorkspaceContext } workspaceId = { workspaceId } />
215301 )
216302 }
217303
@@ -542,9 +628,19 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
542628 }
543629
544630 return (
545- < div className = { cn ( 'flex flex-col' , isWorkspaceContext ? 'h-full flex-1' : 'min-h-screen' ) } >
546- < div className = 'flex flex-1 overflow-hidden' >
547- < div className = 'flex flex-1 flex-col overflow-auto px-[24px] pt-[24px] pb-[24px]' >
631+ < div
632+ className = { cn (
633+ 'flex flex-col' ,
634+ isWorkspaceContext ? 'h-full flex-1 overflow-hidden' : 'min-h-screen'
635+ ) }
636+ >
637+ < div className = { cn ( 'flex flex-1' , isWorkspaceContext && 'overflow-hidden' ) } >
638+ < div
639+ className = { cn (
640+ 'flex flex-1 flex-col px-[24px] pt-[24px] pb-[24px]' ,
641+ isWorkspaceContext ? 'overflow-auto' : 'overflow-visible'
642+ ) }
643+ >
548644 { /* Breadcrumb navigation */ }
549645 < Breadcrumb items = { breadcrumbItems } />
550646
@@ -697,7 +793,7 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
697793
698794 { /* Template tagline */ }
699795 { template . details ?. tagline && (
700- < p className = 'mt-[4px] font-medium text-[14px] text-[var(--text-tertiary)]' >
796+ < p className = 'mt-[4px] line-clamp-2 max-w-[40vw] font-medium text-[14px] text-[var(--text-tertiary)]' >
701797 { template . details . tagline }
702798 </ p >
703799 ) }
@@ -770,7 +866,7 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
770866
771867 { /* Canvas preview */ }
772868 < div
773- className = 'relative mt-[24px] h-[450px] w-full overflow-hidden rounded-[8px] border border-[var(--border)]'
869+ className = 'relative mt-[24px] h-[450px] w-full flex-shrink-0 overflow-hidden rounded-[8px] border border-[var(--border)]'
774870 onWheelCapture = { handleCanvasWheelCapture }
775871 >
776872 { renderWorkflowPreview ( ) }
0 commit comments