Skip to content

Commit 345c8d0

Browse files
committed
Showcase improvements
1 parent 9e00b24 commit 345c8d0

File tree

6 files changed

+86
-64
lines changed

6 files changed

+86
-64
lines changed

src/components/ImageUpload.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export function ImageUpload({
103103
? 'w-24'
104104
: aspectRatio === 'video'
105105
? 'max-w-md'
106-
: 'w-32'
106+
: 'w-40'
107107

108108
return (
109109
<div className={className}>
@@ -154,38 +154,38 @@ export function ImageUpload({
154154
)}
155155
>
156156
{isUploading ? (
157-
<>
157+
<div className="p-4 text-center">
158158
<Loader2
159159
className={twMerge(
160-
'text-blue-500 animate-spin',
160+
'text-blue-500 animate-spin mx-auto',
161161
isSmall ? 'w-5 h-5' : 'w-8 h-8',
162162
)}
163163
/>
164164
{!isSmall && (
165-
<span className="mt-2 text-sm text-gray-600 dark:text-gray-400">
165+
<span className="mt-2 block text-sm text-gray-600 dark:text-gray-400">
166166
Uploading...
167167
</span>
168168
)}
169-
</>
169+
</div>
170170
) : (
171-
<>
171+
<div className="p-4 text-center">
172172
<Upload
173173
className={twMerge(
174-
'text-gray-400',
174+
'text-gray-400 mx-auto',
175175
isSmall ? 'w-5 h-5' : 'w-8 h-8',
176176
)}
177177
/>
178178
{!isSmall && (
179179
<>
180-
<span className="mt-2 text-sm text-gray-600 dark:text-gray-400">
180+
<span className="mt-2 block text-sm text-gray-600 dark:text-gray-400">
181181
Click or drag to upload
182182
</span>
183-
<span className="mt-1 text-xs text-gray-500">
183+
<span className="mt-1 block text-xs text-gray-500">
184184
PNG, JPG up to 4MB
185185
</span>
186186
</>
187187
)}
188-
</>
188+
</div>
189189
)}
190190
</div>
191191
)}

src/components/Navbar.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
Grid2X2,
3030
LogOut,
3131
Settings,
32+
Sparkles,
3233
} from 'lucide-react'
3334
import { ThemeToggle } from './ThemeToggle'
3435
import { SearchButton } from './SearchButton'
@@ -541,6 +542,11 @@ export function Navbar({ children }: { children: React.ReactNode }) {
541542
icon: <Users />,
542543
to: '/partners',
543544
},
545+
{
546+
label: 'Showcase',
547+
icon: <Sparkles />,
548+
to: '/showcase',
549+
},
544550
{
545551
label: 'Blog',
546552
icon: <Music />,

src/components/PartnersSection.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { partners } from '~/utils/partners'
44
import { PartnersGrid } from './PartnersGrid'
55
import { PartnershipCallout } from './PartnershipCallout'
66
import { LibraryId } from '~/libraries'
7+
import { Button } from './Button'
78

89
type PartnersSectionProps = {
910
libraryId?: LibraryId
@@ -37,17 +38,17 @@ export function PartnersSection({
3738
<PartnershipCallout libraryId={libraryId} />
3839
{showPreviousLink ? (
3940
<div className="text-center mt-6">
40-
<Link
41+
<Button
42+
as={Link}
4143
to="/partners"
4244
search={
4345
libraryId
4446
? { libraries: [libraryId], status: 'inactive' }
4547
: { status: 'inactive' }
4648
}
47-
className="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg border border-gray-300 dark:border-gray-800 bg-white dark:bg-gray-900 shadow-xs hover:shadow-sm hover:border-gray-400 dark:hover:border-gray-700 transition-all"
4849
>
4950
View Previous Partners →
50-
</Link>
51+
</Button>
5152
</div>
5253
) : null}
5354
</div>

src/components/ShowcaseSection.tsx

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,44 @@ import {
77
} from '~/queries/showcases'
88
import { ShowcaseCard, ShowcaseCardSkeleton } from './ShowcaseCard'
99
import { buttonStyles } from './Button'
10-
import { ArrowRight } from 'lucide-react'
10+
import { ArrowRight, Plus } from 'lucide-react'
1111

1212
interface ShowcaseSectionProps {
1313
title?: string
1414
subtitle?: string
1515
libraryId?: string
1616
limit?: number
1717
showViewAll?: boolean
18+
minItems?: number
19+
}
20+
21+
function SubmitShowcasePlaceholder({ libraryId }: { libraryId?: string }) {
22+
return (
23+
<Link
24+
to="/showcase/submit"
25+
search={libraryId ? { libraryId } : undefined}
26+
className="group block rounded-xl overflow-hidden bg-white dark:bg-gray-800 shadow-lg hover:shadow-xl transition-all duration-300 border-2 border-dashed border-gray-300 dark:border-gray-600 hover:border-blue-400 dark:hover:border-blue-500"
27+
>
28+
<div className="aspect-video flex items-center justify-center bg-gray-50 dark:bg-gray-900/50">
29+
<div className="text-center p-6">
30+
<div className="w-12 h-12 mx-auto mb-3 rounded-full bg-gray-100 dark:bg-gray-800 flex items-center justify-center group-hover:bg-blue-100 dark:group-hover:bg-blue-900/30 transition-colors">
31+
<Plus className="w-6 h-6 text-gray-400 group-hover:text-blue-500 transition-colors" />
32+
</div>
33+
<p className="text-sm font-medium text-gray-600 dark:text-gray-400 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
34+
Submit your project
35+
</p>
36+
</div>
37+
</div>
38+
<div className="p-4">
39+
<h3 className="font-bold text-lg text-gray-500 dark:text-gray-400 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
40+
Your Project Here
41+
</h3>
42+
<p className="text-sm text-gray-500 dark:text-gray-500 mt-1">
43+
Share what you've built with the community
44+
</p>
45+
</div>
46+
</Link>
47+
)
1848
}
1949

2050
export function ShowcaseSection({
@@ -23,6 +53,7 @@ export function ShowcaseSection({
2353
libraryId,
2454
limit = 6,
2555
showViewAll = true,
56+
minItems = 3,
2657
}: ShowcaseSectionProps) {
2758
const queryOptions = libraryId
2859
? getShowcasesByLibraryQueryOptions({ libraryId, limit })
@@ -31,11 +62,7 @@ export function ShowcaseSection({
3162
const { data, isLoading } = useQuery(queryOptions)
3263

3364
const showcases = data?.showcases || []
34-
35-
// Don't render anything if no showcases
36-
if (!isLoading && showcases.length === 0) {
37-
return null
38-
}
65+
const placeholdersNeeded = Math.max(0, minItems - showcases.length)
3966

4067
return (
4168
<section className="py-16">
@@ -50,7 +77,7 @@ export function ShowcaseSection({
5077

5178
{isLoading ? (
5279
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
53-
{Array.from({ length: limit }).map((_, i) => (
80+
{Array.from({ length: Math.max(limit, minItems) }).map((_, i) => (
5481
<ShowcaseCardSkeleton key={i} />
5582
))}
5683
</div>
@@ -59,11 +86,17 @@ export function ShowcaseSection({
5986
{showcases.map(({ showcase, user }) => (
6087
<ShowcaseCard key={showcase.id} showcase={showcase} user={user} />
6188
))}
89+
{Array.from({ length: placeholdersNeeded }).map((_, i) => (
90+
<SubmitShowcasePlaceholder
91+
key={`placeholder-${i}`}
92+
libraryId={libraryId}
93+
/>
94+
))}
6295
</div>
6396
)}
6497

6598
{showViewAll && (
66-
<div className="mt-8 text-center">
99+
<div className="mt-8 flex justify-center">
67100
<Link
68101
to="/showcase"
69102
search={libraryId ? { libraryId } : undefined}

src/components/ShowcaseSubmitForm.tsx

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,25 @@ export function ShowcaseSubmitForm() {
151151
/>
152152
</div>
153153

154+
{/* Project URL */}
155+
<div>
156+
<label
157+
htmlFor="url"
158+
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
159+
>
160+
Project URL *
161+
</label>
162+
<input
163+
type="url"
164+
id="url"
165+
value={url}
166+
onChange={(e) => setUrl(e.target.value)}
167+
required
168+
className="mt-1 block w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
169+
placeholder="https://your-project.com"
170+
/>
171+
</div>
172+
154173
{/* Tagline */}
155174
<div>
156175
<label
@@ -192,25 +211,6 @@ export function ShowcaseSubmitForm() {
192211
/>
193212
</div>
194213

195-
{/* Project URL */}
196-
<div>
197-
<label
198-
htmlFor="url"
199-
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
200-
>
201-
Project URL *
202-
</label>
203-
<input
204-
type="url"
205-
id="url"
206-
value={url}
207-
onChange={(e) => setUrl(e.target.value)}
208-
required
209-
className="mt-1 block w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
210-
placeholder="https://your-project.com"
211-
/>
212-
</div>
213-
214214
{/* Screenshot */}
215215
<ImageUpload
216216
value={screenshotUrl}

src/routes/_libraries/index.tsx

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { Layers, Zap, Shield, Code2 } from 'lucide-react'
2828
import { Card } from '~/components/Card'
2929
import LibraryCard from '~/components/LibraryCard'
3030
import { FeaturedShowcases } from '~/components/ShowcaseSection'
31+
import { Button } from '~/components/Button'
3132

3233
export const textColors = [
3334
`text-rose-500`,
@@ -250,25 +251,9 @@ function Index() {
250251
</div>
251252

252253
<div className="px-4 lg:max-w-(--breakpoint-lg) md:mx-auto mt-8 text-center">
253-
<Link
254-
to="/libraries"
255-
className="inline-flex items-center gap-2 px-6 py-3 rounded-xl border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900 shadow-xs hover:shadow-sm hover:border-gray-400 dark:hover:border-gray-600 hover:-translate-y-1 transition-all duration-300 text-gray-900 dark:text-gray-100 font-medium"
256-
>
257-
<span>More Libraries</span>
258-
<svg
259-
className="w-4 h-4"
260-
fill="none"
261-
viewBox="0 0 24 24"
262-
stroke="currentColor"
263-
>
264-
<path
265-
strokeLinecap="round"
266-
strokeLinejoin="round"
267-
strokeWidth={2}
268-
d="M9 5l7 7-7 7"
269-
/>
270-
</svg>
271-
</Link>
254+
<Button as={Link} to="/libraries">
255+
More Libraries →
256+
</Button>
272257
</div>
273258

274259
{/* Why TanStack Section */}
@@ -527,12 +512,9 @@ function Index() {
527512
))}
528513
</div>
529514
<div className="text-center mt-6">
530-
<Link
531-
to="/maintainers"
532-
className="inline-flex items-center text-sm text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 transition-colors"
533-
>
515+
<Button as={Link} to="/maintainers">
534516
View All Maintainers →
535-
</Link>
517+
</Button>
536518
</div>
537519
</div>
538520

0 commit comments

Comments
 (0)