Components for the favorites section (#27)
Co-authored-by: WindOfCodes <59533802+WindOfCodes@users.noreply.github.com> Co-authored-by: Konrad Szwarc <konrad.szwarc.dev@gmail.com> Co-authored-by: Bury <agnieszka.bury@capgemini.com>
This commit is contained in:
parent
8462d35f03
commit
cd71aff5a3
7 changed files with 196 additions and 5 deletions
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
|
@ -12,5 +12,7 @@
|
|||
"[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
|
||||
"[javascript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" },
|
||||
"[typescript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" },
|
||||
"[typescriptreact]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" }
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
34
src/components/atoms/book-tile.astro
Normal file
34
src/components/atoms/book-tile.astro
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
import { Image } from '@astrojs/image/components';
|
||||
|
||||
import Typography from '@/atoms/typography.astro';
|
||||
import type { Book } from '@/types/favorites-section';
|
||||
|
||||
export interface Props extends astroHTML.JSX.HTMLAttributes {
|
||||
value: Book;
|
||||
}
|
||||
|
||||
const { value, ...props } = Astro.props;
|
||||
const BookTile = 'a';
|
||||
---
|
||||
|
||||
<BookTile
|
||||
href={value.url}
|
||||
class:list={['flex', 'flex-col', 'gap-3', 'transition', 'duration-300', 'hover:translate-y-2', props.class]}
|
||||
>
|
||||
<Image
|
||||
class:list={['rounded-lg', 'shadow-md', 'object-cover']}
|
||||
src={value.cover}
|
||||
aspectRatio="1.3"
|
||||
alt={value.title}
|
||||
format="webp"
|
||||
/>
|
||||
<div class:list={['tile-content', 'gap-1']}>
|
||||
<Typography class:list={['leading-5', 'hover:text-gray-900']} variant="tile-title">
|
||||
{value.title}
|
||||
</Typography>
|
||||
<Typography variant="tile-subtitle">
|
||||
{value.author}
|
||||
</Typography>
|
||||
</div>
|
||||
</BookTile>
|
||||
34
src/components/atoms/media-tile.astro
Normal file
34
src/components/atoms/media-tile.astro
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
import { Image } from '@astrojs/image/components';
|
||||
|
||||
import Typography from '@/atoms/typography.astro';
|
||||
import type { Media } from '@/types/favorites-section';
|
||||
|
||||
export interface Props extends astroHTML.JSX.HTMLAttributes {
|
||||
value: Media;
|
||||
}
|
||||
|
||||
const { value, ...props } = Astro.props;
|
||||
const MediaTile = 'a';
|
||||
---
|
||||
|
||||
<MediaTile
|
||||
href={value.url}
|
||||
class:list={['flex', 'flex-col', 'gap-3', 'transition', 'duration-300', 'hover:translate-y-2', props.class]}
|
||||
>
|
||||
<Image
|
||||
class:list={['rounded-lg', 'shadow-md', 'object-cover']}
|
||||
src={value.image}
|
||||
alt={value.title}
|
||||
aspectRatio="1.1"
|
||||
format="webp"
|
||||
/>
|
||||
<div class:list={['tile-content', 'gap-1']}>
|
||||
<Typography class:list={['leading-5', 'hover:text-gray-900']} variant="tile-title">
|
||||
{value.title}
|
||||
</Typography>
|
||||
<Typography variant="tile-subtitle">
|
||||
{value.type}
|
||||
</Typography>
|
||||
</div>
|
||||
</MediaTile>
|
||||
34
src/components/atoms/person-tile.astro
Normal file
34
src/components/atoms/person-tile.astro
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
import { Image } from '@astrojs/image/components';
|
||||
|
||||
import Typography from '@/atoms/typography.astro';
|
||||
import type { Person } from '@/types/favorites-section';
|
||||
|
||||
export interface Props extends astroHTML.JSX.HTMLAttributes {
|
||||
value: Person;
|
||||
}
|
||||
|
||||
const { value, ...props } = Astro.props;
|
||||
const PersonTile = 'a';
|
||||
---
|
||||
|
||||
<PersonTile
|
||||
href={value.url}
|
||||
class:list={['flex', 'flex-col', 'gap-3', 'transition', 'duration-300', 'hover:translate-y-2', props.class]}
|
||||
>
|
||||
<Image
|
||||
class:list={['rounded-lg', 'shadow-md', 'object-cover', 'transition', 'duration-300']}
|
||||
src={value.image}
|
||||
alt={value.name}
|
||||
aspectRatio="1/1"
|
||||
format="webp"
|
||||
/>
|
||||
<div class:list={['tile-content', 'gap-1']}>
|
||||
<Typography class:list={['leading-5', 'hover:text-gray-900']} variant="tile-title">
|
||||
{value.name}
|
||||
</Typography>
|
||||
<Typography variant="tile-subtitle">
|
||||
{value.name}
|
||||
</Typography>
|
||||
</div>
|
||||
</PersonTile>
|
||||
36
src/components/atoms/video-tile.astro
Normal file
36
src/components/atoms/video-tile.astro
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
import { Image } from '@astrojs/image/components';
|
||||
|
||||
import Typography from '@/atoms/typography.astro';
|
||||
import type { Video } from '@/types/favorites-section';
|
||||
|
||||
export interface Props extends astroHTML.JSX.HTMLAttributes {
|
||||
value: Video;
|
||||
}
|
||||
|
||||
const { value, ...props } = Astro.props;
|
||||
const VideoTile = 'a';
|
||||
|
||||
const getVideoThumbnail = (url: string) => {
|
||||
return `https://img.youtube.com/vi/${url.split('/').pop()}/0.jpg`;
|
||||
};
|
||||
---
|
||||
|
||||
<VideoTile
|
||||
href={value.url}
|
||||
class:list={['flex', 'flex-col', 'gap-3', 'transition', 'duration-300', 'hover:translate-y-2', props.class]}
|
||||
>
|
||||
<Image
|
||||
class:list={['rounded-lg', 'shadow-md', 'object-cover']}
|
||||
src={getVideoThumbnail(value.url)}
|
||||
width="auto"
|
||||
aspectRatio="1.67"
|
||||
alt={value.title}
|
||||
format="webp"
|
||||
/>
|
||||
<div class:list={['tile-content', 'gap-1']}>
|
||||
<Typography class:list={['leading-5', 'hover:text-gray-900']} variant="tile-title">
|
||||
{value.title}
|
||||
</Typography>
|
||||
</div>
|
||||
</VideoTile>
|
||||
51
src/pages/playground/favorites.astro
Normal file
51
src/pages/playground/favorites.astro
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
import BookTile from '@/atoms/book-tile.astro';
|
||||
import MediaTile from '@/atoms/media-tile.astro';
|
||||
import PersonTile from '@/atoms/person-tile.astro';
|
||||
import Typography from '@/atoms/typography.astro';
|
||||
import VideoTile from '@/atoms/video-tile.astro';
|
||||
import type { Book, Media, Person, Video } from '@/types/favorites-section';
|
||||
|
||||
const book: Book = {
|
||||
cover: import('@/assets/favorites/books/book-1.jpeg'),
|
||||
title: 'The Pragmatic Programmer: From Journeyman to Master',
|
||||
author: 'Andy Hunt, Dave Thomas',
|
||||
url: 'https://www.goodreads.com/book/show/4099.The_Pragmatic_Programmer',
|
||||
};
|
||||
|
||||
const person: Person = {
|
||||
image: import('@/assets/favorites/people/person-1.jpg'),
|
||||
name: 'Kent C. Dodds',
|
||||
url: 'https://kentcdodds.com/',
|
||||
};
|
||||
|
||||
const video: Video = {
|
||||
thumbnail: import('@/assets/favorites/videos/video-1.jpeg'),
|
||||
title: 'Building Resilient Frontend Architecture - Monica Lent - GOTO 2019',
|
||||
url: 'https://youtu.be/TqfbAXCCVwE',
|
||||
};
|
||||
|
||||
const media: Media = {
|
||||
image: import('@/assets/favorites/media/media-1.jpeg'),
|
||||
title: 'Fireship.io',
|
||||
type: 'YouTube channel',
|
||||
url: 'https://www.youtube.com/c/Fireship',
|
||||
};
|
||||
---
|
||||
|
||||
<Typography class="m-2 font-mono" variant="item-title">Favourite Book</Typography>
|
||||
<div class="m-4 grid grid-cols-8">
|
||||
<BookTile value={book} />
|
||||
</div>
|
||||
<Typography class="m-2 font-mono" variant="item-title">Favourite Person</Typography>
|
||||
<div class="m-4 grid grid-cols-12">
|
||||
<PersonTile value={person} />
|
||||
</div>
|
||||
<Typography class="m-2 font-mono" variant="item-title">Favourite Video</Typography>
|
||||
<div class="m-4 grid grid-cols-6">
|
||||
<VideoTile value={video} />
|
||||
</div>
|
||||
<Typography class="m-2 font-mono" variant="item-title">Favourite Media</Typography>
|
||||
<div class="m-4 grid grid-cols-12">
|
||||
<MediaTile value={media} />
|
||||
</div>
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
import type { LocalImage, SectionConfig } from './common';
|
||||
|
||||
interface Book {
|
||||
export interface Book {
|
||||
title: string;
|
||||
cover: LocalImage;
|
||||
author: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
interface Person {
|
||||
export interface Person {
|
||||
name: string;
|
||||
image: LocalImage;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
interface Video {
|
||||
export interface Video {
|
||||
title: string;
|
||||
thumbnail: LocalImage;
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface Media {
|
||||
export interface Media {
|
||||
title: string;
|
||||
type: string;
|
||||
image: LocalImage;
|
||||
|
|
|
|||
Loading…
Reference in a new issue