Skip to content

Commit 86fa41a

Browse files
authored
Migrate AmbassadorsCard, AmbassadorsBanner and AmbassadorsList to ShadCN +2 issues resolved (#1731)
* implement ambessador card and add tests * add animation to the ambessador card * adjusting the tests for the animation * adapting ambessador list and banner components * adjusting card layout color * more color adjustments * adding tests and adjusting format * improve card teest coverage * format adjustments * fixing test coverage * format f3ixing
1 parent 0e43eb6 commit 86fa41a

File tree

6 files changed

+766
-95
lines changed

6 files changed

+766
-95
lines changed

components/AmbassadorsBanner.tsx

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,59 @@
11
import Link from 'next/link';
22
import React from 'react';
3+
import {
4+
Card,
5+
CardContent,
6+
CardHeader,
7+
CardTitle,
8+
CardDescription,
9+
} from '@/components/ui/card';
10+
import { Button } from '@/components/ui/button';
311

412
const AmbassadorBanner: React.FC = () => {
513
return (
614
<div className='flex justify-center mx-4 sm:mx-6 md:mx-10 my-8 w-full'>
7-
<div className='group relative h-auto w-full sm:w-5/6 md:w-4/5 lg:w-2/3 xl:w-1/2 rounded-lg border border-gray-200 bg-white p-6 sm:p-8 shadow-3xl dark:shadow-2xl dark:shadow-slate-900 transition-colors ease-in-out hover:bg-slate-100 dark:bg-slate-800 hover:dark:bg-slate-900/30'>
8-
<h3 className='text-xl sm:text-2xl md:text-3xl font-bold mb-4 text-gray-800 dark:text-slate-100 text-center'>
9-
Become a JSON Schema Ambassador
10-
</h3>
11-
<p className='text-sm sm:text-base md:text-lg text-gray-600 dark:text-slate-100 mb-6 text-center'>
12-
The JSON Schema Ambassador program is now open for applications! If
13-
you're selected, you'll join JSON Schema's mission of helping
14-
community members all over the world build the future of JSON Schema.
15-
</p>
16-
<div className='w-full grid grid-cols-1 sm:grid-cols-2 gap-4 my-4 mx-auto'>
17-
<Link
18-
href='https://github.com/json-schema-org/community/tree/main/programs/ambassadors#become-a-json-schema-ambassador'
19-
className='inline-block px-6 py-3 bg-blue-600 text-white font-semibold text-center rounded hover:bg-blue-700 transition duration-300'
20-
>
21-
Become Ambassador
22-
</Link>
23-
<Link
24-
href='https://github.com/json-schema-org/community/tree/main/programs/ambassadors'
25-
className='inline-block bg-gray-300 text-slate-700 text-center px-6 py-3 rounded-md shadow hover:bg-gray-400 transition'
26-
>
27-
Learn More
28-
</Link>
29-
</div>
30-
</div>
15+
<Card className='group relative h-auto w-full sm:w-5/6 md:w-4/5 lg:w-2/3 xl:w-1/2 rounded-lg border border-gray-200 bg-white p-6 sm:p-8 shadow-3xl dark:shadow-2xl dark:shadow-slate-900 transition-colors ease-in-out hover:bg-slate-100 dark:bg-slate-800 hover:dark:bg-slate-900/30'>
16+
<CardHeader className='p-0 mb-4'>
17+
<CardTitle className='text-xl sm:text-2xl md:text-3xl font-bold mb-4 text-gray-800 dark:text-slate-100 text-center'>
18+
Become a JSON Schema Ambassador
19+
</CardTitle>
20+
<CardDescription className='text-sm sm:text-base md:text-lg text-gray-600 dark:text-slate-100 mb-6 text-center'>
21+
The JSON Schema Ambassador program is now open for applications! If
22+
you're selected, you'll join JSON Schema's mission of helping
23+
community members all over the world build the future of JSON
24+
Schema.
25+
</CardDescription>
26+
</CardHeader>
27+
<CardContent className='p-0'>
28+
<div className='w-full grid grid-cols-1 sm:grid-cols-2 gap-4 my-4 mx-auto'>
29+
<Button
30+
asChild
31+
className='px-6 py-3 bg-blue-600 hover:bg-blue-700 transition duration-300 text-white'
32+
>
33+
<Link
34+
href='https://github.com/json-schema-org/community/tree/main/programs/ambassadors#become-a-json-schema-ambassador'
35+
target='_blank'
36+
rel='noopener noreferrer'
37+
>
38+
Become Ambassador
39+
</Link>
40+
</Button>
41+
<Button
42+
asChild
43+
variant='secondary'
44+
className='px-6 py-3 bg-gray-300 text-slate-700 hover:bg-gray-400 transition'
45+
>
46+
<Link
47+
href='https://github.com/json-schema-org/community/tree/main/programs/ambassadors'
48+
target='_blank'
49+
rel='noopener noreferrer'
50+
>
51+
Learn More
52+
</Link>
53+
</Button>
54+
</div>
55+
</CardContent>
56+
</Card>
3157
</div>
3258
);
3359
};

components/AmbassadorsCard.tsx

Lines changed: 95 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
/* eslint-disable linebreak-style */
12
import React, { useState } from 'react';
23
import Image from 'next/image';
4+
import {
5+
Card,
6+
CardContent,
7+
CardHeader,
8+
CardTitle,
9+
CardDescription,
10+
} from '@/components/ui/card';
11+
import { Button } from '@/components/ui/button';
312

413
interface Contribution {
514
title: string;
@@ -105,14 +114,7 @@ const AmbassadorCard = ({ ambassador }: { ambassador: Ambassador }) => {
105114
ambassador.img || '/api/placeholder/400/320',
106115
);
107116

108-
const {
109-
name = 'Ambassador',
110-
title,
111-
bio,
112-
company,
113-
country,
114-
contributions = [],
115-
} = ambassador;
117+
const { name, title, bio, company, country, contributions = [] } = ambassador;
116118

117119
const SocialIcons: SocialIcons[] = [
118120
'github',
@@ -122,33 +124,45 @@ const AmbassadorCard = ({ ambassador }: { ambassador: Ambassador }) => {
122124
];
123125

124126
return (
125-
<div className='relative flex flex-col max-w-sm md:max-w-md lg:max-w-lg mx-auto bg-white dark:bg-gray-800 shadow-lg rounded-lg overflow-hidden my-4 h-full'>
126-
<div className='absolute top-0 right-0 w-1 h-20 bg-black dark:bg-gray-400'></div>
127-
<div className='absolute bottom-100 right-0 w-20 h-1 bg-black dark:bg-gray-400'></div>
128-
<div className='absolute bottom-0 left-0 w-1 h-20 bg-black dark:bg-gray-400'></div>
129-
<div className='absolute bottom-0 left-0 w-20 h-1 bg-black dark:bg-gray-400'></div>
130-
131-
<Image
132-
className='w-full object-cover p-5 rounded-3xl'
133-
src={imgSrc}
134-
alt={`${name} profile`}
135-
width={400}
136-
height={320}
137-
onError={() => setImgSrc(`/img/ambassadors/${name}.jpg`)}
138-
/>
139-
140-
<div className='flex flex-col flex-grow p-6'>
141-
<h3 className='text-xl font-semibold mb-2 text-gray-900 dark:text-white'>
142-
{name}
143-
</h3>
144-
{title && (
145-
<p className='text-gray-500 dark:text-slate-100 mb-1'>{title}</p>
146-
)}
127+
<Card className='py-0 relative max-w-md md:max-w-lg lg:max-w-xl mx-auto bg-white dark:bg-gray-800 shadow-lg rounded-lg overflow-hidden my-4 h-full border-0'>
128+
{/* Decorative corner elements */}
129+
<div className='absolute top-0 right-0 w-1 h-20 bg-gray-400'></div>
130+
<div className='absolute top-0 right-0 w-20 h-1 bg-gray-400'></div>
131+
<div className='absolute bottom-0 left-0 w-1 h-20 bg-gray-400'></div>
132+
<div className='absolute bottom-0 left-0 w-20 h-1 bg-gray-400'></div>
133+
134+
{/* Image section */}
135+
<div className='p-5'>
136+
<div className='w-full h-80 relative overflow-hidden rounded-2xl'>
137+
<Image
138+
className='w-full h-full object-cover'
139+
src={imgSrc}
140+
alt={`${name} profile`}
141+
fill
142+
sizes='(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw'
143+
onError={() => setImgSrc(`/img/ambassadors/${name}.jpg`)}
144+
/>
145+
</div>
146+
</div>
147+
148+
<CardContent className='flex flex-col flex-grow p-6 pt-0'>
149+
<CardHeader className='p-0 mb-4'>
150+
<CardTitle className='text-xl font-semibold mb-2 text-gray-900 dark:text-white'>
151+
{name}
152+
</CardTitle>
153+
{title && (
154+
<CardDescription className='text-gray-500 dark:text-slate-100 mb-1'>
155+
{title}
156+
</CardDescription>
157+
)}
158+
</CardHeader>
159+
147160
{bio && (
148161
<p className='text-gray-700 dark:text-slate-100 text-sm mb-4'>
149162
{bio}
150163
</p>
151164
)}
165+
152166
{(company || country) && (
153167
<p className='text-gray-500 dark:text-slate-100 mb-4'>
154168
{company}
@@ -157,6 +171,7 @@ const AmbassadorCard = ({ ambassador }: { ambassador: Ambassador }) => {
157171
</p>
158172
)}
159173

174+
{/* Social icons */}
160175
<div className='flex justify-center mb-4 mt-auto'>
161176
{SocialIcons.map((platform) => {
162177
const username = ambassador[platform];
@@ -175,44 +190,65 @@ const AmbassadorCard = ({ ambassador }: { ambassador: Ambassador }) => {
175190
})}
176191
</div>
177192

193+
{/* Contributions button */}
178194
{contributions.length > 0 && (
179-
<button
195+
<Button
180196
onClick={() => setShowContributions(!showContributions)}
181197
className={`w-full bg-blue-600 dark:bg-blue-500 hover:bg-blue-700 dark:hover:bg-blue-400 text-white dark:text-slate-100 font-semibold py-2 px-4 rounded transition-all duration-300 transform ${
182-
showContributions ? 'rotate' : ''
198+
showContributions
199+
? 'scale-105 shadow-lg shadow-blue-500/50'
200+
: 'scale-100 shadow-md'
183201
}`}
202+
variant='default'
184203
>
185204
{showContributions ? 'Hide Details' : 'Show Full Details'}
186-
</button>
205+
</Button>
187206
)}
188207

189-
{showContributions && contributions.length > 0 && (
190-
<div className='mt-4'>
191-
<h4 className='text-lg font-semibold mb-2 text-gray-900 dark:text-white'>
192-
Contributions
193-
</h4>
194-
<ul className='text-gray-600 dark:text-slate-100 text-sm'>
195-
{contributions.map((contribution, index) => (
196-
<li key={index} className='mb-2'>
197-
<strong>{contribution.title}</strong>
198-
{contribution.date &&
199-
` (${contribution.date.month} ${contribution.date.year})`}{' '}
200-
-
201-
<a
202-
href={contribution.link}
203-
className='text-blue-600 dark:text-blue-400 ml-1 hover:underline'
204-
target='_blank'
205-
rel='noopener noreferrer'
208+
{/* Contributions list with animation */}
209+
<div
210+
className={`overflow-hidden transition-all duration-500 ease-in-out ${
211+
showContributions ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
212+
}`}
213+
>
214+
{contributions.length > 0 && (
215+
<div className='mt-4 pt-4 border-t border-gray-200 dark:border-gray-700'>
216+
<h4 className='text-lg font-semibold mb-2 text-gray-900 dark:text-white'>
217+
Contributions
218+
</h4>
219+
<ul className='text-gray-600 dark:text-slate-100 text-sm space-y-2'>
220+
{contributions.map((contribution, index) => (
221+
<li
222+
key={index}
223+
className={`transform transition-all duration-300 ease-out ${
224+
showContributions
225+
? 'translate-y-0 opacity-100'
226+
: 'translate-y-4 opacity-0'
227+
}`}
228+
style={{
229+
transitionDelay: `${index * 100}ms`,
230+
}}
206231
>
207-
{contribution.type}
208-
</a>
209-
</li>
210-
))}
211-
</ul>
212-
</div>
213-
)}
214-
</div>
215-
</div>
232+
<strong>{contribution.title}</strong>
233+
{contribution.date &&
234+
` (${contribution.date.month} ${contribution.date.year})`}{' '}
235+
-
236+
<a
237+
href={contribution.link}
238+
className='text-blue-600 dark:text-blue-400 ml-1 hover:underline transition-colors duration-200'
239+
target='_blank'
240+
rel='noopener noreferrer'
241+
>
242+
{contribution.type}
243+
</a>
244+
</li>
245+
))}
246+
</ul>
247+
</div>
248+
)}
249+
</div>
250+
</CardContent>
251+
</Card>
216252
);
217253
};
218254

components/AmbassadorsList.tsx

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
import React from 'react';
2+
import {
3+
Card,
4+
CardContent,
5+
CardHeader,
6+
CardTitle,
7+
CardDescription,
8+
} from '@/components/ui/card';
29

310
interface AmbassadorsLink {
411
title: string;
@@ -18,20 +25,26 @@ const AmbassadorList = ({ ambassadorList }: AmbassadorsListProps) => {
1825
{ambassadorList.contents.map((link) => (
1926
<li
2027
key={link.title}
21-
className='flex flex-col items-center text-center p-5 bg-white dark:bg-gray-800 rounded-lg shadow-lg transform transition hover:scale-105'
28+
className='flex flex-col items-center text-center'
2229
data-testid='Ambassadors-list'
2330
>
24-
<img
25-
src={link.icon}
26-
alt={link.title}
27-
className='w-[150px] h-auto object-contain mb-5'
28-
/>
29-
<h2 className='text-lg md:text-xl font-semibold text-gray-900 dark:text-white mb-3'>
30-
{link.title}
31-
</h2>
32-
<p className='text-sm md:text-base text-gray-700 dark:text-slate-100 leading-relaxed'>
33-
{link.details}
34-
</p>
31+
<Card className='dark:border-gray-700 w-full h-full p-5 bg-white dark:bg-gray-800 rounded-lg shadow-lg transform transition hover:scale-105'>
32+
<CardContent className='p-0'>
33+
<img
34+
src={link.icon}
35+
alt={link.title}
36+
className='w-[150px] h-auto object-contain mb-5 mx-auto'
37+
/>
38+
<CardHeader className='p-0 mb-3'>
39+
<CardTitle className='text-lg md:text-xl font-semibold text-gray-900 dark:text-white'>
40+
{link.title}
41+
</CardTitle>
42+
</CardHeader>
43+
<CardDescription className='text-sm md:text-base text-gray-700 dark:text-slate-100 leading-relaxed'>
44+
{link.details}
45+
</CardDescription>
46+
</CardContent>
47+
</Card>
3548
</li>
3649
))}
3750
</ul>

0 commit comments

Comments
 (0)