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" },
|
"[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
|
||||||
"[javascript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" },
|
"[javascript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" },
|
||||||
"[typescript]": { "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';
|
import type { LocalImage, SectionConfig } from './common';
|
||||||
|
|
||||||
interface Book {
|
export interface Book {
|
||||||
title: string;
|
title: string;
|
||||||
cover: LocalImage;
|
cover: LocalImage;
|
||||||
author: string;
|
author: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Person {
|
export interface Person {
|
||||||
name: string;
|
name: string;
|
||||||
image: LocalImage;
|
image: LocalImage;
|
||||||
url?: string;
|
url?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Video {
|
export interface Video {
|
||||||
title: string;
|
title: string;
|
||||||
thumbnail: LocalImage;
|
thumbnail: LocalImage;
|
||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Media {
|
export interface Media {
|
||||||
title: string;
|
title: string;
|
||||||
type: string;
|
type: string;
|
||||||
image: LocalImage;
|
image: LocalImage;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue