Skip to content

Commit

Permalink
feat: add slider for latest articles
Browse files Browse the repository at this point in the history
  • Loading branch information
fbuireu committed May 16, 2024
1 parent 5845918 commit 72236cf
Show file tree
Hide file tree
Showing 15 changed files with 452 additions and 283 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@
"lint:typecheck": "tsc --project . --noEmit"
},
"dependencies": {
"@astrojs/check": "^0.6.0",
"@astrojs/check": "^0.7.0",
"@astrojs/cloudflare": "^10.2.6",
"@astrojs/mdx": "^3.0.0",
"@astrojs/partytown": "^2.1.0",
"@astrojs/react": "^3.3.4",
"@astrojs/rss": "^4.0.5",
"@astrojs/rss": "^4.0.6",
"@astrojs/sitemap": "^3.1.4",
"@fontsource-variable/nunito-sans": "^5.0.14",
"@fontsource/baskervville": "^5.0.20",
"@hookform/resolvers": "^3.3.4",
"astro": "^4.8.3",
"@hookform/resolvers": "^3.4.0",
"astro": "^4.8.4",
"firebase": "^10.12.0",
"firebase-admin": "^12.1.0",
"gsap": "^3.12.5",
Expand All @@ -69,14 +69,14 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@astrojs/ts-plugin": "^1.7.0",
"@astrojs/ts-plugin": "^1.8.0",
"@biomejs/biome": "1.7.3",
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@testing-library/react": "^15.0.7",
"@testing-library/react-hooks": "^8.0.1",
"@types/markdown-it": "^14.1.1",
"@types/node": "^20.12.11",
"@types/node": "^20.12.12",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.3.0",
"@types/three": "^0.164.0",
Expand Down
18 changes: 18 additions & 0 deletions src/assets/images/svg-components/leftArrow/LeftArrow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
interface LeftArrowProps{
fill?: string
}

export const LeftArrow = ({fill='currentColor'}:LeftArrowProps) => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 25">
<g id="Left">
<polygon
points="24 12.001 2.914 12.001 8.208 6.706 7.501 5.999 1 12.501 7.5 19.001 8.207 18.294 2.914 13.001 24 13.001 24 12.001"
style={{fill}}
stroke="#232326"
strokeWidth="0.25"
/>
</g>
</svg>
);
};
1 change: 1 addition & 0 deletions src/assets/images/svg-components/leftArrow/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./LeftArrow.tsx";
1 change: 0 additions & 1 deletion src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import Testimonials from "@components/organisms/testimonials/Testimonials.astro"
import MyWork from "@components/organisms/myWork/MyWork.astro";
import LatestArticles from "@components/organisms/latestArticles/LatestArticles.astro";
// todo (current): fresh from the blog
// todo: tags page
// todo: add resume (PDF) in about?
// todo: dynamic content
Expand Down
109 changes: 109 additions & 0 deletions src/ui/components/molecules/latestArticles/LatestArticlesSlider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import type { CollectionEntry } from "astro:content";
import { createExcerpt } from "@shared/utils/createExcerpt";
import { slugify } from "@shared/utils/slugify";
import MarkdownIt from "markdown-it";
import { DEFAULT_DATE_FORMAT } from "src/consts.ts";
import { A11y, Keyboard, Navigation, Virtual } from "swiper/modules";
import { Swiper, SwiperSlide } from "swiper/react";
import type { SwiperOptions } from "swiper/types";
import "./latest-articles-slider.css";
import { LatestArticlesSliderNavigation } from './components/latestArticlesSliderNavigation';

interface LatestArticlesSLiderProps {
articles: CollectionEntry<"articles">[];
}

enum ArticleType {
DEFAULT = "default",
NO_IMAGE = "no_image",
}

const SLIDER_CONFIG: SwiperOptions = {
modules: [Navigation, Keyboard, Virtual, A11y],
loop: true,
slidesPerView: 4,
autoplay: {
delay: 3000,
pauseOnMouseEnter: true,
},
pagination: {
clickable: true,
},
keyboard: {
enabled: true,
},
breakpoints: {
1024: {
slidesPerView: 4,
spaceBetween: 32,
},
720: {
slidesPerView: 2,
spaceBetween: 32,
},
320: {
slidesPerView: 1,
},
},
containerModifierClass: "latest-articles-",
};
const parser: MarkdownIt = MarkdownIt("default", {});

export const LatestArticlesSlider = ({ articles }: LatestArticlesSLiderProps) => {
return (
<div className="latest-articles__slider common-wrapper">
<Swiper onResize={(e)=> console.log(e)} {...SLIDER_CONFIG}>
<ul className="latest__articles__list flex row-wrap justify-space-between">
{articles.map(({ slug, data: article, ...content }) => {
const { excerpt } = createExcerpt({
parser,
content: content.body,
});
const variant: ArticleType = article.featuredImage ? ArticleType.DEFAULT : ArticleType.NO_IMAGE;
const publishedDate = article.publishDate.toLocaleDateString("en", DEFAULT_DATE_FORMAT);
const href = `/articles/${slug}`;

return (
<li key={slug} className="latest__article__item__wrapper article__item clickable">
<SwiperSlide key={slug}>
<a className="latest__article__link-card" href={href} aria-label={article.title} />
<article
className={`latest__article__item ${
variant === ArticleType.DEFAULT ? '--default-variant' : '--no-image-variant'
}`}
>
{article.featuredImage && (
<img
className="latest__article__item__featured-image"
src={article.featuredImage}
alt={article.title}
loading="lazy"
decoding="async"
/>
)}
<time className="latest__article__item__publish-date" dateTime={publishedDate}>
{publishedDate}
</time>
<h3 className="latest__article__title font-serif inner-section-title">{article.title}</h3>
<p className="latest__article__author">
by <a href={`/tags/${slugify(article.author)}`}>{article.author}</a>
</p>
<p className="latest__article__excerpt">{excerpt}</p>
<ul className="latest__article__tags__list flex">
{article.tags?.map((tag: string) => (
<a className="latest__article__tag__item" href={`/tags/${slugify(tag)}`} key={tag}>
#{tag}
</a>
))}
</ul>
</article>
</SwiperSlide>
</li>
);
})}
</ul>
<LatestArticlesSliderNavigation />
</Swiper>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import "./latest-articles-slider-navigation.css";
import { useSwiper } from "swiper/react";
import { LeftArrow } from '@assets/images/svg-components/leftArrow';

export const LatestArticlesSliderNavigation = () => {
const swiper = useSwiper();

return (
<div className="latest-articles__slider__navigation flex row-nowrap">
<button
className="latest-articles__slider__navigation__button --left clickable"
type="button"
onClick={() => swiper.slidePrev()}
>
<LeftArrow fill="#ffffff"/>
</button>
<button
className="latest-articles__slider__navigation__button --right clickable"
type="button"
onClick={() => swiper.slideNext()}
>
<LeftArrow fill="#ffffff"/>
</button>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./LatestArticlesSliderNavigation.tsx";
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@layer latest-articles.slider.navigation {
.latest-articles__slider__navigation {
gap: 0 1rem;
position: absolute;
right: 0;
z-index: 10;

img {
width: 3rem;
}

@media (min-width: 1024px) {
display: none;
}
}

.latest-articles__slider__navigation__button {
height: 3rem;
width: 3rem;

svg{
height: 100%;
width: 100%;
}
&.--right {
rotate: 0.5turn;
}
}
}
1 change: 1 addition & 0 deletions src/ui/components/molecules/latestArticles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./LatestArticlesSlider.tsx";
104 changes: 104 additions & 0 deletions src/ui/components/molecules/latestArticles/latest-articles-slider.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
@layer latest-articles.slider {
.latest-articles__title {
color: var(--white);
padding: 2rem 0;

.latest-articles__title__link {
color: var(--primary-main);
display: inline-block;
}
}

.latest__articles__list {
align-items: stretch;
gap: 0 2rem;
padding: 2rem 0 4rem;
position: relative;
}

.latest__article__item__wrapper {
backface-visibility: hidden;
-webkit-font-smoothing: subpixel-antialiased;
max-width: calc(100% / 4 - 2rem);
position: relative;
transform: translateZ(0);
transition: 0.2s scale;
width: 100%;
will-change: transform;
}

.latest__article__link-card {
inset: 0;
position: absolute;
width: 100%;
}

.latest__article__item {
display: grid;
gap: 0.5rem 0;
height: 100%;

&.--no-image-variant {
grid:
'Publish-Date' auto
'Title' 1fr
'Author' auto
'Excerpt' auto
'Tags' auto
/ 1fr;
}

&.--default-variant {
grid:
'Publish-Date' auto
'Featured-Image' 1fr
'Title' auto
'Author' auto
'Excerpt' auto
'Tags' auto
/ 1fr;
}
}

.latest__article__title {
align-self: center;
color: var(--white);
grid-area: Title;
letter-spacing: normal;
}

.latest__article__item__publish-date {
grid-area: Publish-Date;
}

.latest__article__author {
color: var(--white);
grid-area: Author;

a {
color: var(--primary-main);
position: relative;
z-index: 10;
}
}

.latest__article__excerpt {
color: var(--white);
grid-area: Excerpt;
}

.latest__article__item__featured-image {
grid-area: Featured-Image;
object-fit: cover;
z-index: -1;
}

.latest__article__tags__list {
color: var(--white);
font-size: 1.1rem;
gap: 0 1rem;
grid-area: Tags;
position: relative;
z-index: 10;
}
}
Loading

0 comments on commit 72236cf

Please sign in to comment.