Create profile card section (#55)

This commit is contained in:
Szymon Kin 2022-10-25 19:38:25 +02:00 committed by GitHub
parent 0e2d6125a8
commit 0e3bb5f849
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 126 additions and 14 deletions

View file

@ -1,9 +1,10 @@
--- ---
export interface Props { export interface Props {
href: string; href: string;
download?: astroHTML.JSX.AnchorHTMLAttributes['download'];
} }
const { href } = Astro.props; const { href, download } = Astro.props;
const classes = { const classes = {
main: 'inline-flex items-center px-4 h-10 text-base font-medium rounded-md shadow-sm text-white bg-primary-600 select-none cursor-pointer', main: 'inline-flex items-center px-4 h-10 text-base font-medium rounded-md shadow-sm text-white bg-primary-600 select-none cursor-pointer',
@ -13,4 +14,6 @@ const classes = {
}; };
--- ---
<a href={href} class:list={[classes.main, classes.hover, classes.active, classes.focus]}><slot /></a> <a href={href} class:list={[classes.main, classes.hover, classes.active, classes.focus]} download={download}
><slot />
</a>

View file

@ -6,13 +6,11 @@ import Icon from './icon';
export interface Props { export interface Props {
icon?: { icon?: {
name: IconName; name: IconName;
color: string; color?: string;
}; };
} }
const { const { icon } = Astro.props;
props: { icon },
} = Astro;
--- ---
<div class="flex items-center w-fit h-6 px-2.5 rounded text-sm font-medium text-gray-700 bg-gray-100 gap-x-1.5"> <div class="flex items-center w-fit h-6 px-2.5 rounded text-sm font-medium text-gray-700 bg-gray-100 gap-x-1.5">

View file

@ -25,8 +25,8 @@ const variantToElement = {
} as const; } as const;
const variantToClassName = { const variantToClassName = {
'main-title': 'text-4xl font-extrabold text-gray-900', 'main-title': 'text-3xl sm:text-4xl font-extrabold text-gray-900',
'main-subtitle': 'text-lg font-medium text-gray-700', 'main-subtitle': 'text-md sm:text-lg font-medium text-gray-700',
'section-title': 'text-3xl font-extrabold text-gray-900', 'section-title': 'text-3xl font-extrabold text-gray-900',
'section-subtitle': 'text-lg font-extrabold text-gray-900', 'section-subtitle': 'text-lg font-extrabold text-gray-900',
'item-title': 'text-xl font-extrabold text-gray-900', 'item-title': 'text-xl font-extrabold text-gray-900',
@ -34,7 +34,7 @@ const variantToClassName = {
'item-subtitle': 'text-md font-medium text-gray-700', 'item-subtitle': 'text-md font-medium text-gray-700',
'tile-title': 'text-sm font-medium text-gray-700', 'tile-title': 'text-sm font-medium text-gray-700',
'tile-subtitle': 'text-sm font-normal text-gray-500', 'tile-subtitle': 'text-sm font-normal text-gray-500',
paragraph: 'text-base leading-relaxed font-normal text-gray-500', paragraph: 'text-sm sm:text-base leading-relaxed font-normal text-gray-500',
}; };
export interface Props extends Omit<astroHTML.JSX.HTMLAttributes, 'slot'> { export interface Props extends Omit<astroHTML.JSX.HTMLAttributes, 'slot'> {

View file

@ -1,6 +1,6 @@
--- ---
export interface Props { export interface Props {
className: string; className?: string;
} }
const { className } = Astro.props; const { className } = Astro.props;

View file

@ -12,9 +12,7 @@ const { url, icon, iconColor, name, level } = Astro.props;
<div class:list={['flex', 'flex-col', 'gap-2']}> <div class:list={['flex', 'flex-col', 'gap-2']}>
<div class:list={['flex', 'gap-2', 'h-5']}> <div class:list={['flex', 'gap-2', 'h-5']}>
<a href={url} target="_blank" rel="noopener noreferrer"> <Icon client:load name={icon} color={iconColor} size={20} url={url} />
<Icon client:load name={icon} color={iconColor} size={20} />
</a>
<Typography variant="tile-subtitle" class="text-gray-700">{name}</Typography> <Typography variant="tile-subtitle" class="text-gray-700">{name}</Typography>
</div> </div>
<SkillLevel skillLevel={level} /> <SkillLevel skillLevel={level} />

View file

@ -1,8 +1,83 @@
--- ---
import { Image } from '@astrojs/image/components';
import Button from '@/atoms/button.astro';
import IconButton from '@/atoms/icon-button.astro';
import SectionCard from '@/atoms/section-card.astro'; import SectionCard from '@/atoms/section-card.astro';
import Tag from '@/atoms/tag.astro';
import Typography from '@/atoms/typography.astro';
import type { MainSection } from '@/types/main-section'; import type { MainSection } from '@/types/main-section';
export interface Props extends MainSection {} export interface Props extends MainSection {}
const {
image,
fullName,
role,
socials,
details,
description,
action: { label, url, downloadedFileName },
tags,
} = Astro.props;
--- ---
<SectionCard>Main section</SectionCard> <SectionCard>
<div class:list={['flex', 'gap-6', 'flex-col', 'sm:flex-row', 'items-start']}>
<div class:list={['flex', 'sm:flex-col', 'gap-4', 'items-center']}>
<Image
src={image}
alt={fullName}
class:list={['w-24', 'h-24', 'sm:w-36', 'sm:h-36', 'md:w-52', 'md:h-52', 'rounded-lg', 'max-w-none']}
/>
<Button href={url} download={downloadedFileName}>{label}</Button>
</div>
<div class:list={['w-full', 'flex', 'flex-col', 'gap-5']}>
<div class:list={['w-full', 'flex', 'flex-col', 'sm:flex-row', 'justify-between', 'gap-2']}>
<div class:list={['w-full']}>
<Typography variant="main-title">{fullName}</Typography>
<Typography variant="main-subtitle">{role}</Typography>
</div>
{
socials.length > 0 && (
<div class:list={['flex', 'gap-3', 'flex-wrap', 'sm:flex-nowrap']}>
{socials.map(({ icon, url: iconUrl }) => (
<IconButton href={iconUrl} icon={icon} size="small" target="_blank" />
))}
</div>
)
}
</div>
<div class:list={['flex', 'flex-col', 'gap-6']}>
<div class:list={['inline-grid', 'xl:grid-cols-[auto_auto]']}>
{
details.map(({ label: detailLabel, value }) => (
<div class="w-fit">
<Typography variant="paragraph">
<span class="text-gray-700">{detailLabel}: </span>
<span class="break-all">{value}</span>
</Typography>
</div>
))
}
</div>
<div class:list={['flex', 'flex-col', 'gap-4']}>
<Typography variant="paragraph">{description}</Typography>
<div class:list={['flex', 'flex-wrap', 'gap-3']}>
{
tags.map(({ icon, iconColor, name, url: tagUrl }) =>
tagUrl ? (
<a href={tagUrl} target="_blank" rel="noopener noreferrer">
<Tag icon={icon ? { name: icon, color: iconColor } : undefined}>{name}</Tag>
</a>
) : (
<Tag icon={icon ? { name: icon, color: iconColor } : undefined}>{name}</Tag>
)
)
}
</div>
</div>
</div>
</div>
</div>
</SectionCard>

View file

@ -0,0 +1,37 @@
---
import MainSection from '@/sections/main-section.astro';
import type { MainSection as MainSectionData } from '@/types/main-section';
const mainSectionData: MainSectionData = {
image: import('@/assets/my-image.jpeg'),
fullName: 'Mark Freeman',
role: 'Senior React Developer',
details: [
{ label: 'Phone', value: '+48 604 343 212' },
{ label: 'Email', value: 'veeeery.long.email.address@gmail.com' },
{ label: 'From', value: 'Warsaw, Poland' },
{ label: 'Salary range', value: '18 000 - 25 000 PLN' },
],
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sodales ac dui at vestibulum. In condimentum metus id dui tincidunt, in blandit mi vehicula. Nulla lacinia, erat sit amet elementum vulputate, lectus mauris volutpat mi, vitae accumsan metus elit ut nunc. Vestibulum lacinia enim eget eros fermentum scelerisque. Proin augue leo, posuere ut imperdiet vitae, fermentum eu ipsum. Sed sed neque sagittis, posuere urna nec, commodo leo. Pellentesque posuere justo vitae massa volutpat maximus.',
tags: [{ name: 'Open for freelance' }, { name: 'Available for mentoring' }, { name: 'Working on side project' }],
action: {
label: 'Download CV',
url: '#',
},
socials: [
{ name: 'Facebook', icon: 'fa6-brands:facebook-f', url: '#' },
{ name: 'GitHub', icon: 'fa6-brands:github', url: '#' },
{ name: 'LinkedIn', icon: 'fa6-brands:linkedin-in', url: '#' },
{ name: 'Twitter', icon: 'fa6-brands:twitter', url: '#' },
],
};
---
<body class="flex justify-center bg-gray-50">
<div class="flex gap-8 w-full max-w-6xl px-2 py-3 sm:px-8 sm:py-12 lg:px-16 lg:py-20 lg:ml-22">
<main class="w-full space-y-4 sm:space-y-6 lg:space-y-8">
<MainSection {...mainSectionData} />
</main>
</div>
</body>

View file

@ -10,6 +10,7 @@ export interface MainSection {
action: { action: {
label: string; label: string;
url: string; url: string;
downloadedFileName?: string;
}; };
socials: Social[]; socials: Social[];
config: Omit<SectionConfig, 'title'>; config: Omit<SectionConfig, 'title'>;