feat: ✨ add blog routes and components
This commit is contained in:
parent
3be32dbf89
commit
833797406a
37
components/BlogCard.css
Normal file
37
components/BlogCard.css
Normal file
|
@ -0,0 +1,37 @@
|
|||
.components__blog_card {
|
||||
min-width: 10rem;
|
||||
aspect-ratio: 3 / 4;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: var(--_gap-half);
|
||||
gap: var(--_gap);
|
||||
box-shadow: 0 0 0.4rem 0.2rem var(--_translucent);
|
||||
border: var(--_border-size) solid transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
||||
&:focus-visible,
|
||||
&:hover {
|
||||
border: var(--_border-size) solid var(--_accent-color);
|
||||
}
|
||||
|
||||
& h3 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.components__blog_card__spacer {
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.components__blog_card__text {
|
||||
text-wrap: balance;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.components__blog_card__footer {
|
||||
height: fit-content;
|
||||
display: flex;
|
||||
gap: var(--_gap);
|
||||
justify-content: space-between;
|
||||
}
|
54
components/BlogCard.tsx
Normal file
54
components/BlogCard.tsx
Normal file
|
@ -0,0 +1,54 @@
|
|||
type BlogCardProps = {
|
||||
img: string
|
||||
title: string
|
||||
text: string
|
||||
author: string
|
||||
lasUpdate: Date
|
||||
id: string
|
||||
}
|
||||
|
||||
export function BlogCard(
|
||||
{ img, title, text, author, lasUpdate, id }: BlogCardProps,
|
||||
) {
|
||||
return (
|
||||
<div class='components__blog_card' style={{ backgroundImage: img }}>
|
||||
<div class='components__blog_card__spacer'></div>
|
||||
<h3>
|
||||
<a href={`/blog/${id}`}>{title}</a>
|
||||
</h3>
|
||||
<div class='components__blog_card__text'>
|
||||
{`${text.slice(0, 150)} ...`}
|
||||
</div>
|
||||
<div class='components__blog_card__footer'>
|
||||
<div>
|
||||
<i class='ri-quill-pen-line'></i>
|
||||
<span>{author}</span>
|
||||
</div>
|
||||
<div>
|
||||
<i class='ri-refresh-line'></i>
|
||||
<span>{lasUpdate.toLocaleDateString()}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const text =
|
||||
'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui, perferendis enim blanditiis consequatur at porro quod, eligendi alias recusandae modi aliquam non? Quos voluptates quisquam provident animi nisi in ratione.'
|
||||
|
||||
export const blogMock: BlogCardProps[] = Array(50).fill(undefined).map(
|
||||
(_, index) => {
|
||||
return {
|
||||
author: 'PGP',
|
||||
lasUpdate: randomDate(),
|
||||
title: `Some title here ${index}`,
|
||||
text,
|
||||
img: `url("https://picsum.photos/id/${index}/300/200")`,
|
||||
id: String(index),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
function randomDate() {
|
||||
return new Date(Date.now() - Math.random() * 1e10)
|
||||
}
|
10
routes/blog/[id].tsx
Normal file
10
routes/blog/[id].tsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { PageProps } from '$fresh/server.ts'
|
||||
import { BlogCard, blogMock } from '../../components/BlogCard.tsx'
|
||||
|
||||
export default function Projet({ params }: PageProps) {
|
||||
const article = blogMock.at(Number(params.id))
|
||||
|
||||
return (
|
||||
article ? BlogCard(article) : <h3>Article inconnu</h3>
|
||||
)
|
||||
}
|
18
routes/blog/index.tsx
Normal file
18
routes/blog/index.tsx
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { BlogCard, blogMock } from '../../components/BlogCard.tsx'
|
||||
|
||||
export default function Blog() {
|
||||
return (
|
||||
<>
|
||||
<h1>Nos articles</h1>
|
||||
<section
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(15rem, 1fr));',
|
||||
gap: 'var(--_gap)',
|
||||
}}
|
||||
>
|
||||
{blogMock.map(BlogCard)}
|
||||
</section>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
import { Head } from '$fresh/runtime.ts'
|
||||
import { BlogCard, blogMock } from '../components/BlogCard.tsx'
|
||||
import { CohabitInfoTable } from '../components/CohabitInfoTable.tsx'
|
||||
import { Heros } from '../components/Heros.tsx'
|
||||
import { SponsorCards } from '../components/SponsorCards.tsx'
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
|
|
|
@ -72,3 +72,20 @@ pre,
|
|||
code {
|
||||
font-family: var(--_font-family-code);
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-block: var(--_gap);
|
||||
}
|
||||
|
||||
.cta {
|
||||
text-decoration: none;
|
||||
background-color: var(--_accent-color);
|
||||
color: var(--sand-0);
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
padding: 1rem 2rem;
|
||||
font-size: 150%;
|
||||
font-family: var(--_font-family-accent);
|
||||
border: var(--_border-size) solid var(--_accent-color);
|
||||
transition: all var(--_transition-delay) ease;
|
||||
}
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
@import url('../../components/Heros.css');
|
||||
@import url('../../components/SponsorCards.css');
|
||||
@import url('../../components/CohabitInfoTable.css');
|
||||
@import url('../../components/BlogCard.css');
|
||||
@import url('../../islands/ThemePicker.css');
|
||||
@import url('../../islands/SearchBox.css');
|
||||
|
|
Loading…
Reference in a new issue