1
1
import { Button } from '@/src/components/ui/button'
2
2
import { Heart } from 'lucide-react'
3
3
import Image from 'next/image'
4
+ import { ReactNode } from 'react'
4
5
import { z } from 'zod'
5
6
6
7
export async function SponsorsSection ( ) {
@@ -10,26 +11,32 @@ export async function SponsorsSection() {
10
11
< h2 className = "mb-12 text-center text-3xl font-bold tracking-tighter dark:text-white md:text-4xl xl:text-5xl" >
11
12
Sponsors
12
13
</ h2 >
13
- < div className = "flex flex-wrap justify-center gap-4 " >
14
+ < ul className = "grid grid-cols-1 gap-y-12 sm:grid-cols-3 " >
14
15
{ sponsors . map ( sponsor => (
15
- < a
16
- key = { sponsor . handle }
17
- href = { sponsor . url }
18
- className = "h-32 w-32 rounded-full text-center"
19
- >
20
- < Image
21
- src = { sponsor . img }
22
- alt = { sponsor . name ?? sponsor . handle }
23
- className = "rounded-full"
24
- width = { 128 }
25
- height = { 128 }
26
- />
27
- < span className = "mt-2 inline-block text-sm text-zinc-500" >
16
+ < li key = { sponsor . handle } className = "flex flex-col items-center" >
17
+ < a href = { sponsor . url } className = "h-32 w-32 rounded-full" >
18
+ < Image
19
+ src = { sponsor . img }
20
+ alt = { sponsor . name ?? sponsor . handle }
21
+ className = "rounded-full"
22
+ width = { 128 }
23
+ height = { 128 }
24
+ />
25
+ </ a >
26
+ < a
27
+ href = { sponsor . url }
28
+ className = "mt-2 inline-block text-sm font-semibold hover:underline"
29
+ >
28
30
{ sponsor . name ?? sponsor . handle }
29
- </ span >
30
- </ a >
31
+ </ a >
32
+ { Boolean ( sponsor . title ) && (
33
+ < span className = "mt-1 inline-block text-sm text-zinc-500" >
34
+ { sponsor . title }
35
+ </ span >
36
+ ) }
37
+ </ li >
31
38
) ) }
32
- </ div >
39
+ </ ul >
33
40
< div className = "mt-16 flex justify-center" >
34
41
< Button className = "mx-auto" asChild variant = "outline" >
35
42
< a href = "https://github.com/sponsors/franky47" >
@@ -47,7 +54,8 @@ const sponsorSchema = z.object({
47
54
name : z . string ( ) . nullish ( ) ,
48
55
handle : z . string ( ) ,
49
56
url : z . string ( ) . url ( ) ,
50
- img : z . string ( ) . url ( )
57
+ img : z . string ( ) . url ( ) ,
58
+ title : z . custom < ReactNode > ( )
51
59
} )
52
60
type Sponsors = z . infer < typeof sponsorSchema > [ ]
53
61
@@ -75,19 +83,40 @@ async function fetchSponsors(): Promise<Sponsors> {
75
83
// }
76
84
// }
77
85
return [
78
- // GitHub sponsors
79
86
{
80
- handle : 'rwieruch' ,
81
- name : 'Robin Wieruch' ,
82
- url : 'https://github.com/rwieruch' ,
83
- img : 'https://avatars.githubusercontent.com/u/2479967?u=cba76c8678af8e63ee2dd32853a4e262b35f9ac0&v=4'
87
+ handle : 'pontusab' ,
88
+ name : 'Pontus Abrahamsson' ,
89
+ url : 'https://x.com/pontusab' ,
90
+ img : 'https://avatars.githubusercontent.com/u/655158?v=4' ,
91
+ title : (
92
+ < >
93
+ Founder of{ ' ' }
94
+ < a href = "https://midday.ai" className = "hover:underline" >
95
+ Midday.ai
96
+ </ a >
97
+ </ >
98
+ )
84
99
} ,
85
- // Other sponsors
86
100
{
87
101
handle : 'YoannFleuryDev' ,
88
102
name : 'Yoann Fleury' ,
89
- url : 'https://twitter.com/YoannFleuryDev' ,
90
- img : 'https://pbs.twimg.com/profile_images/1594632934245498880/CJTKNRCO_400x400.jpg'
103
+ url : 'https://www.yoannfleury.dev/' ,
104
+ img : 'https://pbs.twimg.com/profile_images/1594632934245498880/CJTKNRCO_400x400.jpg' ,
105
+ title : 'Front end developer'
106
+ } ,
107
+ {
108
+ handle : 'rwieruch' ,
109
+ name : 'Robin Wieruch' ,
110
+ url : 'https://www.robinwieruch.de/' ,
111
+ img : 'https://avatars.githubusercontent.com/u/2479967?v=4' ,
112
+ title : (
113
+ < >
114
+ Author of{ ' ' }
115
+ < a href = "https://www.roadtoreact.com/" className = "hover:underline" >
116
+ The Road to React
117
+ </ a >
118
+ </ >
119
+ )
91
120
}
92
121
]
93
122
}
0 commit comments