diff --git a/.github/renovate.json b/.github/renovate.json
index 39004bcb..0cf312c6 100644
--- a/.github/renovate.json
+++ b/.github/renovate.json
@@ -1,16 +1,8 @@
{
- "$schema": "https://docs.renovatebot.com/renovate-schema.json",
- "extends": [
- "config:recommended"
- ],
- "labels": [
- "dependencies",
- "renovate",
- "bot"
- ],
- "schedule": [
- "every weekend"
- ],
- "assigneesFromCodeOwners": true,
- "reviewersFromCodeOwners": true
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "extends": ["config:recommended"],
+ "labels": ["dependencies", "renovate", "bot"],
+ "schedule": ["every weekend"],
+ "assigneesFromCodeOwners": true,
+ "reviewersFromCodeOwners": true
}
diff --git a/.lintstagedrc.json b/.lintstagedrc.json
index 84179501..b0e661a0 100644
--- a/.lintstagedrc.json
+++ b/.lintstagedrc.json
@@ -1,14 +1,6 @@
{
- "src/**/*.{ts,tsx,css,astro}": [
- "yarn format:changed"
- ],
- "src/**/*.{ts,tsx,astro}": [
- "yarn lint:ts:changed"
- ],
- "src/**/*.css": [
- "yarn lint:styles"
- ],
- "src/**/*.{test,spec}.{ts,tsx}": [
- "yarn test --bail --findRelatedTests"
- ]
+ "src/**/*.{ts,tsx,css,astro}": ["yarn format:changed"],
+ "src/**/*.{ts,tsx,astro}": ["yarn lint:ts:changed"],
+ "src/**/*.css": ["yarn lint:styles"],
+ "src/**/*.{test,spec}.{ts,tsx}": ["yarn test --bail --findRelatedTests"]
}
diff --git a/.stylelintrc.cjs b/.stylelintrc.cjs
index e4e00405..dda339a9 100644
--- a/.stylelintrc.cjs
+++ b/.stylelintrc.cjs
@@ -1,12 +1,12 @@
/** @type {import('stylelint').Config} */
module.exports = {
- extends: "stylelint-config-recommended",
- plugins: ["stylelint-order"],
- allowEmptyInput: true,
- rules: {
- "order/properties-alphabetical-order": true,
- "selector-class-pattern": null,
- "value-keyword-case": null,
- "custom-property-pattern": null,
- },
+ extends: "stylelint-config-recommended",
+ plugins: ["stylelint-order"],
+ allowEmptyInput: true,
+ rules: {
+ "order/properties-alphabetical-order": true,
+ "selector-class-pattern": null,
+ "value-keyword-case": null,
+ "custom-property-pattern": null,
+ },
};
diff --git a/commitlint.config.ts b/commitlint.config.ts
index 127168e2..5367bd1a 100644
--- a/commitlint.config.ts
+++ b/commitlint.config.ts
@@ -1,18 +1,14 @@
import type { UserConfig } from "@commitlint/types";
const Configuration: UserConfig = {
- extends: ["@commitlint/config-conventional"],
- parserPreset: "conventional-changelog-atom",
- formatter: "@commitlint/format",
- rules: {
- "scope-case": [
- 2,
- "always",
- ["lower-case", "pascal-case", "camel-case"],
- ],
- "scope-enum": [2, "always", ["deps", "other"]],
- "header-max-length": [2, "always", 130],
- },
+ extends: ["@commitlint/config-conventional"],
+ parserPreset: "conventional-changelog-atom",
+ formatter: "@commitlint/format",
+ rules: {
+ "scope-case": [2, "always", ["lower-case", "pascal-case", "camel-case"]],
+ "scope-enum": [2, "always", ["deps", "other"]],
+ "header-max-length": [2, "always", 130],
+ },
};
export default Configuration;
diff --git a/package.json b/package.json
index 0abfbefb..140724ee 100644
--- a/package.json
+++ b/package.json
@@ -29,10 +29,10 @@
"sync": "astro sync",
"check": "astro check",
"test": "vitest --passWithNoTests",
- "test:changed": "yarn test --bail --findRelatedTests --passWithNoTests",
- "test:all": "yarn test --passWithNoTests",
- "test:ut": "yarn test --passWithNoTests",
- "test:e2e": "yarn test --passWithNoTests",
+ "test:changed": "yarn test --bail --findRelatedTests",
+ "test:all": "yarn test",
+ "test:ut": "yarn test",
+ "test:e2e": "yarn test",
"format": "biome check --write --no-errors-on-unmatched",
"format:all": "yarn format .",
"format:changed": "yarn format --changed",
diff --git a/src/pages/articles/index.astro b/src/pages/articles/index.astro
index b00d67b6..b6298a9e 100644
--- a/src/pages/articles/index.astro
+++ b/src/pages/articles/index.astro
@@ -20,8 +20,7 @@ const featuredArticle = getFeaturedArticle(articles);
{
articles
.filter((article) => article.data.slug !== featuredArticle.data.slug)
- .map((article, index) => {
- return;
+ .map((article, index) => (
- ;
- })}
+
+ ))}
diff --git a/src/pages/index.astro b/src/pages/index.astro
index f9ce3145..9a4068d8 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -7,8 +7,8 @@ import Welcome from "@modules/home/components/welcome/Welcome.astro";
// todo: check metadata all pages
// todo: add small transitions & animations
-// - home articles: show tags staggered in hover
// - CTAs with arrow: animate arrow
+// - add underline to links
// - Latest articles (https://codepen.io/jh3y/pen/MWLyGxo)
// todo: wait for wrangler webhook --> add Algolia + filters (+ URL filtering) https://www.algolia.com/developers/contentful-search-algolia/ (webhook problem)
// todo: how to deploy cloudfare pages
diff --git a/src/ui/modules/about/components/aboutLatestArticlesSlider/AboutLatestArticlesSlider.tsx b/src/ui/modules/about/components/aboutLatestArticlesSlider/AboutLatestArticlesSlider.tsx
index 2a27bab0..cb25768e 100644
--- a/src/ui/modules/about/components/aboutLatestArticlesSlider/AboutLatestArticlesSlider.tsx
+++ b/src/ui/modules/about/components/aboutLatestArticlesSlider/AboutLatestArticlesSlider.tsx
@@ -4,6 +4,7 @@ import { ArticleCard } from "@modules/core/components/articleCard/ArticleCard.ts
import { Slider } from "@modules/core/components/slider";
import type { SwiperOptions } from "swiper/types";
import "./about-latest-articles-slider.css";
+import type { CSSProperties } from "react";
interface AboutLatestArticlesSLiderProps {
articles: CollectionEntry<"articles">[];
@@ -52,11 +53,17 @@ export const AboutLatestArticlesSlider = ({ articles, origin }: AboutLatestArtic
{article.data.author.name}
{article.data.readingTime} min.
- {article.data.tags?.map((tag) => (
-
- {tag.name}
-
- ))}
+ {article.data.tags?.map((tag, index) => {
+ const style: CSSProperties & { [key: string]: string } = {
+ "--inline-index": String(index),
+ };
+
+ return (
+
+ {tag.name}
+
+ );
+ })}
);
diff --git a/src/ui/modules/core/components/articleCard/ArticleCard.astro b/src/ui/modules/core/components/articleCard/ArticleCard.astro
index cd9a90be..0feb9d81 100644
--- a/src/ui/modules/core/components/articleCard/ArticleCard.astro
+++ b/src/ui/modules/core/components/articleCard/ArticleCard.astro
@@ -13,7 +13,7 @@ const { pathname } = Astro.url;
const origin = getLocation(Astro.url);
---
-{" "}
+{' '}
{article.data.description}
{article.data.readingTime} min.
- {article.data.tags?.map(({slug, name}) => (
-
+ {article.data.tags?.map(({ slug, name }, index) => (
+
#{name}
))}
diff --git a/src/ui/modules/core/components/articleCard/ArticleCard.tsx b/src/ui/modules/core/components/articleCard/ArticleCard.tsx
index d78b85c5..d743dbf8 100644
--- a/src/ui/modules/core/components/articleCard/ArticleCard.tsx
+++ b/src/ui/modules/core/components/articleCard/ArticleCard.tsx
@@ -63,8 +63,8 @@ const ReadingTime = ({ children }: ArticleCardReadingTimeProps) => (
{children}
);
const Tags = ({ children }: ArticleCardTagsListProps) => {children};
-const Tag = ({ children, tag }: ArticleCardTagItemProps) => (
- {children}
+const Tag = ({ children, ...props }: ArticleCardTagItemProps) => (
+ {children}
);
ArticleCard.Title = Title;
diff --git a/src/ui/modules/core/components/articleCard/article-card.css b/src/ui/modules/core/components/articleCard/article-card.css
index 89fb7fa9..f014984e 100644
--- a/src/ui/modules/core/components/articleCard/article-card.css
+++ b/src/ui/modules/core/components/articleCard/article-card.css
@@ -3,55 +3,61 @@
@import url('atoms/articleCardImage/article-card-image.css');
@import url('atoms/articleCardPublishDate/article-card-publish-date.css');
@import url('atoms/articleCardTagsList/article-card-tags-list.css');
+@import url('atoms/articleCardTagItem/article-card-tag-item.css');
@import url('atoms/articleCardTitle/article-card-title.css');
@import url('atoms/articleCardReadingTime/article-card-reading-time.css');
- .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;
- }
+.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;
+}
+
+.article__link-card {
+ inset: 0;
+ position: absolute;
+ width: 100%;
+ z-index: 1;
- .article__link-card {
- inset: 0;
- position: absolute;
- width: 100%;
- z-index: 1;
+ &:hover ~ .article__item .article__tag__item {
+ transform: translateY(0);
}
+}
- .article__item {
- color: var(--white);
- display: grid;
- gap: 0.5rem 0;
- height: 100%;
+.article__item {
+ color: var(--white);
+ display: grid;
+ gap: 0.5rem 0;
+ height: 100%;
+ overflow: hidden;
- &.--no-image-variant {
- grid:
- 'Publish-Date Publish-Date' auto
- 'Title Title' auto
- 'Author Reading-Time' auto
- 'Excerpt Excerpt' auto
- 'Tags Tags' auto
- / 1fr 1fr;
- }
+ &.--no-image-variant {
+ grid:
+ 'Publish-Date Publish-Date' auto
+ 'Title Title' auto
+ 'Author Reading-Time' auto
+ 'Excerpt Excerpt' auto
+ 'Tags Tags' auto
+ / 1fr 1fr;
+ }
- &.--default-variant {
- grid:
- 'Publish-Date Publish-Date' auto
- 'Featured-Image Featured-Image' 1fr
- 'Title Title' auto
- 'Author Reading-Time' auto
- 'Excerpt Excerpt' auto
- 'Tags Tags' auto
- / 1fr 1fr;
- }
+ &.--default-variant {
+ grid:
+ 'Publish-Date Publish-Date' auto
+ 'Featured-Image Featured-Image' 1fr
+ 'Title Title' auto
+ 'Author Reading-Time' auto
+ 'Excerpt Excerpt' auto
+ 'Tags Tags' auto
+ / 1fr 1fr;
+ }
- &.--is-articles, &.--is-about, &.--is-tag{
- color: var(--neutral-main)
- }
+ &.--is-articles, &.--is-about, &.--is-tag {
+ color: var(--neutral-main)
}
+}
diff --git a/src/ui/modules/core/components/articleCard/atoms/articleCardAuthor/article-card-author.css b/src/ui/modules/core/components/articleCard/atoms/articleCardAuthor/article-card-author.css
index 8ec3d692..b2a25f6a 100644
--- a/src/ui/modules/core/components/articleCard/atoms/articleCardAuthor/article-card-author.css
+++ b/src/ui/modules/core/components/articleCard/atoms/articleCardAuthor/article-card-author.css
@@ -7,4 +7,8 @@
position: relative;
z-index: 10;
}
-}
\ No newline at end of file
+
+ &:has(a:hover) ~ .article__tags__list .article__tag__item {
+ transform: translateY(0);
+ }
+}
diff --git a/src/ui/modules/core/components/articleCard/atoms/articleCardTagItem/ArticleCardTagItem.tsx b/src/ui/modules/core/components/articleCard/atoms/articleCardTagItem/ArticleCardTagItem.tsx
index 2f9ca005..e886c2a9 100644
--- a/src/ui/modules/core/components/articleCard/atoms/articleCardTagItem/ArticleCardTagItem.tsx
+++ b/src/ui/modules/core/components/articleCard/atoms/articleCardTagItem/ArticleCardTagItem.tsx
@@ -1,13 +1,15 @@
import type { BaseTagDTO } from "@application/dto/tag/types.ts";
-import type { ReactNode } from "react";
+import type { CSSProperties, ReactNode } from "react";
+import "./article-card-tag-item.css";
export interface ArticleCardTagItemProps {
children: ReactNode;
tag: BaseTagDTO;
+ style: CSSProperties;
}
-export const ArticleCardTagItem = ({ children, tag }: ArticleCardTagItemProps) => (
-
+export const ArticleCardTagItem = ({ children, tag, style }: ArticleCardTagItemProps) => (
+
#{children}
);
diff --git a/src/ui/modules/core/components/articleCard/atoms/articleCardTagItem/article-card-tag-item.css b/src/ui/modules/core/components/articleCard/atoms/articleCardTagItem/article-card-tag-item.css
new file mode 100644
index 00000000..b190b73e
--- /dev/null
+++ b/src/ui/modules/core/components/articleCard/atoms/articleCardTagItem/article-card-tag-item.css
@@ -0,0 +1,5 @@
+.article__tag__item {
+ transform: translateY(100px);
+ transition: transform 0.3s ease;
+ transition-delay: calc(var(--inline-index) * 0.1s);
+}
diff --git a/src/ui/modules/core/components/articleCard/atoms/articleCardTagsList/article-card-tags-list.css b/src/ui/modules/core/components/articleCard/atoms/articleCardTagsList/article-card-tags-list.css
index e81f634f..7dcd4ba2 100644
--- a/src/ui/modules/core/components/articleCard/atoms/articleCardTagsList/article-card-tags-list.css
+++ b/src/ui/modules/core/components/articleCard/atoms/articleCardTagsList/article-card-tags-list.css
@@ -5,4 +5,8 @@
position: relative;
text-transform: lowercase;
z-index: 10;
+
+ &:hover .article__tag__item {
+ transform: translateY(0);
+ }
}
diff --git a/src/ui/modules/core/components/latestArticles/atoms/latestArticlesSlider/LatestArticlesSlider.tsx b/src/ui/modules/core/components/latestArticles/atoms/latestArticlesSlider/LatestArticlesSlider.tsx
index 25552e65..d37aa304 100644
--- a/src/ui/modules/core/components/latestArticles/atoms/latestArticlesSlider/LatestArticlesSlider.tsx
+++ b/src/ui/modules/core/components/latestArticles/atoms/latestArticlesSlider/LatestArticlesSlider.tsx
@@ -2,6 +2,7 @@ import type { CollectionEntry } from "astro:content";
import { DEFAULT_SWIPER_CONFIG } from "@const/const.ts";
import { ArticleCard } from "@modules/core/components/articleCard/ArticleCard";
import { Slider } from "@modules/core/components/slider";
+import type { CSSProperties } from "react";
import type { SwiperOptions } from "swiper/types";
import "./latest-articles-slider.css";
@@ -9,6 +10,7 @@ interface LatestArticlesSLiderProps {
articles: CollectionEntry<"articles">[];
origin: URL;
}
+
const SLIDER_CONFIG: SwiperOptions = {
...DEFAULT_SWIPER_CONFIG,
slidesPerView: 4,
@@ -55,11 +57,17 @@ export const LatestArticlesSlider = ({ articles, origin }: LatestArticlesSLiderP
{article.data.author.name}
{article.data.readingTime} min.
- {article.data.tags?.map((tag) => (
-
- {tag.name}
-
- ))}
+ {article.data.tags?.map((tag, index) => {
+ const style: CSSProperties & { [key: string]: string } = {
+ "--inline-index": String(index),
+ };
+
+ return (
+
+ {tag.name}
+
+ );
+ })}
);