Skip to content

Migrate AmbassadorsCard, AmbassadorsBanner and AmbassadorsList to ShadCN +2 issues resolved #1731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
74 changes: 50 additions & 24 deletions components/AmbassadorsBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,59 @@
import Link from 'next/link';
import React from 'react';
import {
Card,
CardContent,
CardHeader,
CardTitle,
CardDescription,
} from '@/components/ui/card';
import { Button } from '@/components/ui/button';

const AmbassadorBanner: React.FC = () => {
return (
<div className='flex justify-center mx-4 sm:mx-6 md:mx-10 my-8 w-full'>
<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'>
<h3 className='text-xl sm:text-2xl md:text-3xl font-bold mb-4 text-gray-800 dark:text-slate-100 text-center'>
Become a JSON Schema Ambassador
</h3>
<p className='text-sm sm:text-base md:text-lg text-gray-600 dark:text-slate-100 mb-6 text-center'>
The JSON Schema Ambassador program is now open for applications! If
you're selected, you'll join JSON Schema's mission of helping
community members all over the world build the future of JSON Schema.
</p>
<div className='w-full grid grid-cols-1 sm:grid-cols-2 gap-4 my-4 mx-auto'>
<Link
href='https://github.com/json-schema-org/community/tree/main/programs/ambassadors#become-a-json-schema-ambassador'
className='inline-block px-6 py-3 bg-blue-600 text-white font-semibold text-center rounded hover:bg-blue-700 transition duration-300'
>
Become Ambassador
</Link>
<Link
href='https://github.com/json-schema-org/community/tree/main/programs/ambassadors'
className='inline-block bg-gray-300 text-slate-700 text-center px-6 py-3 rounded-md shadow hover:bg-gray-400 transition'
>
Learn More
</Link>
</div>
</div>
<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'>
<CardHeader className='p-0 mb-4'>
<CardTitle className='text-xl sm:text-2xl md:text-3xl font-bold mb-4 text-gray-800 dark:text-slate-100 text-center'>
Become a JSON Schema Ambassador
</CardTitle>
<CardDescription className='text-sm sm:text-base md:text-lg text-gray-600 dark:text-slate-100 mb-6 text-center'>
The JSON Schema Ambassador program is now open for applications! If
you're selected, you'll join JSON Schema's mission of helping
community members all over the world build the future of JSON
Schema.
</CardDescription>
</CardHeader>
<CardContent className='p-0'>
<div className='w-full grid grid-cols-1 sm:grid-cols-2 gap-4 my-4 mx-auto'>
<Button
asChild
className='px-6 py-3 bg-blue-600 hover:bg-blue-700 transition duration-300 text-white'
>
<Link
href='https://github.com/json-schema-org/community/tree/main/programs/ambassadors#become-a-json-schema-ambassador'
target='_blank'
rel='noopener noreferrer'
>
Become Ambassador
</Link>
</Button>
<Button
asChild
variant='secondary'
className='px-6 py-3 bg-gray-300 text-slate-700 hover:bg-gray-400 transition'
>
<Link
href='https://github.com/json-schema-org/community/tree/main/programs/ambassadors'
target='_blank'
rel='noopener noreferrer'
>
Learn More
</Link>
</Button>
</div>
</CardContent>
</Card>
</div>
);
};
Expand Down
154 changes: 95 additions & 59 deletions components/AmbassadorsCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
/* eslint-disable linebreak-style */
import React, { useState } from 'react';
import Image from 'next/image';
import {
Card,
CardContent,
CardHeader,
CardTitle,
CardDescription,
} from '@/components/ui/card';
import { Button } from '@/components/ui/button';

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

const {
name = 'Ambassador',
title,
bio,
company,
country,
contributions = [],
} = ambassador;
const { name, title, bio, company, country, contributions = [] } = ambassador;

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

return (
<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'>
<div className='absolute top-0 right-0 w-1 h-20 bg-black dark:bg-gray-400'></div>
<div className='absolute bottom-100 right-0 w-20 h-1 bg-black dark:bg-gray-400'></div>
<div className='absolute bottom-0 left-0 w-1 h-20 bg-black dark:bg-gray-400'></div>
<div className='absolute bottom-0 left-0 w-20 h-1 bg-black dark:bg-gray-400'></div>

<Image
className='w-full object-cover p-5 rounded-3xl'
src={imgSrc}
alt={`${name} profile`}
width={400}
height={320}
onError={() => setImgSrc(`/img/ambassadors/${name}.jpg`)}
/>

<div className='flex flex-col flex-grow p-6'>
<h3 className='text-xl font-semibold mb-2 text-gray-900 dark:text-white'>
{name}
</h3>
{title && (
<p className='text-gray-500 dark:text-slate-100 mb-1'>{title}</p>
)}
<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'>
{/* Decorative corner elements */}
<div className='absolute top-0 right-0 w-1 h-20 bg-gray-400'></div>
<div className='absolute top-0 right-0 w-20 h-1 bg-gray-400'></div>
<div className='absolute bottom-0 left-0 w-1 h-20 bg-gray-400'></div>
<div className='absolute bottom-0 left-0 w-20 h-1 bg-gray-400'></div>

{/* Image section */}
<div className='p-5'>
<div className='w-full h-80 relative overflow-hidden rounded-2xl'>
<Image
className='w-full h-full object-cover'
src={imgSrc}
alt={`${name} profile`}
fill
sizes='(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw'
onError={() => setImgSrc(`/img/ambassadors/${name}.jpg`)}
/>
</div>
</div>

<CardContent className='flex flex-col flex-grow p-6 pt-0'>
<CardHeader className='p-0 mb-4'>
<CardTitle className='text-xl font-semibold mb-2 text-gray-900 dark:text-white'>
{name}
</CardTitle>
{title && (
<CardDescription className='text-gray-500 dark:text-slate-100 mb-1'>
{title}
</CardDescription>
)}
</CardHeader>

{bio && (
<p className='text-gray-700 dark:text-slate-100 text-sm mb-4'>
{bio}
</p>
)}

{(company || country) && (
<p className='text-gray-500 dark:text-slate-100 mb-4'>
{company}
Expand All @@ -157,6 +171,7 @@ const AmbassadorCard = ({ ambassador }: { ambassador: Ambassador }) => {
</p>
)}

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

{/* Contributions button */}
{contributions.length > 0 && (
<button
<Button
onClick={() => setShowContributions(!showContributions)}
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 ${
showContributions ? 'rotate' : ''
showContributions
? 'scale-105 shadow-lg shadow-blue-500/50'
: 'scale-100 shadow-md'
}`}
variant='default'
>
{showContributions ? 'Hide Details' : 'Show Full Details'}
</button>
</Button>
)}

{showContributions && contributions.length > 0 && (
<div className='mt-4'>
<h4 className='text-lg font-semibold mb-2 text-gray-900 dark:text-white'>
Contributions
</h4>
<ul className='text-gray-600 dark:text-slate-100 text-sm'>
{contributions.map((contribution, index) => (
<li key={index} className='mb-2'>
<strong>{contribution.title}</strong>
{contribution.date &&
` (${contribution.date.month} ${contribution.date.year})`}{' '}
-
<a
href={contribution.link}
className='text-blue-600 dark:text-blue-400 ml-1 hover:underline'
target='_blank'
rel='noopener noreferrer'
{/* Contributions list with animation */}
<div
className={`overflow-hidden transition-all duration-500 ease-in-out ${
showContributions ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
}`}
>
{contributions.length > 0 && (
<div className='mt-4 pt-4 border-t border-gray-200 dark:border-gray-700'>
<h4 className='text-lg font-semibold mb-2 text-gray-900 dark:text-white'>
Contributions
</h4>
<ul className='text-gray-600 dark:text-slate-100 text-sm space-y-2'>
{contributions.map((contribution, index) => (
<li
key={index}
className={`transform transition-all duration-300 ease-out ${
showContributions
? 'translate-y-0 opacity-100'
: 'translate-y-4 opacity-0'
}`}
style={{
transitionDelay: `${index * 100}ms`,
}}
>
{contribution.type}
</a>
</li>
))}
</ul>
</div>
)}
</div>
</div>
<strong>{contribution.title}</strong>
{contribution.date &&
` (${contribution.date.month} ${contribution.date.year})`}{' '}
-
<a
href={contribution.link}
className='text-blue-600 dark:text-blue-400 ml-1 hover:underline transition-colors duration-200'
target='_blank'
rel='noopener noreferrer'
>
{contribution.type}
</a>
</li>
))}
</ul>
</div>
)}
</div>
</CardContent>
</Card>
);
};

Expand Down
37 changes: 25 additions & 12 deletions components/AmbassadorsList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import React from 'react';
import {
Card,
CardContent,
CardHeader,
CardTitle,
CardDescription,
} from '@/components/ui/card';

interface AmbassadorsLink {
title: string;
Expand All @@ -18,20 +25,26 @@ const AmbassadorList = ({ ambassadorList }: AmbassadorsListProps) => {
{ambassadorList.contents.map((link) => (
<li
key={link.title}
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'
className='flex flex-col items-center text-center'
data-testid='Ambassadors-list'
>
<img
src={link.icon}
alt={link.title}
className='w-[150px] h-auto object-contain mb-5'
/>
<h2 className='text-lg md:text-xl font-semibold text-gray-900 dark:text-white mb-3'>
{link.title}
</h2>
<p className='text-sm md:text-base text-gray-700 dark:text-slate-100 leading-relaxed'>
{link.details}
</p>
<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'>
<CardContent className='p-0'>
<img
src={link.icon}
alt={link.title}
className='w-[150px] h-auto object-contain mb-5 mx-auto'
/>
<CardHeader className='p-0 mb-3'>
<CardTitle className='text-lg md:text-xl font-semibold text-gray-900 dark:text-white'>
{link.title}
</CardTitle>
</CardHeader>
<CardDescription className='text-sm md:text-base text-gray-700 dark:text-slate-100 leading-relaxed'>
{link.details}
</CardDescription>
</CardContent>
</Card>
</li>
))}
</ul>
Expand Down
Loading