diff --git a/astro.config.mjs b/astro.config.mjs
index e90a62c3..f7f6fa3e 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -19,6 +19,7 @@ export default defineConfig({
},
}),
],
+ prefetch: true,
output: 'server',
adapter: netlify(),
vite: {
diff --git a/src/consts.ts b/src/consts.ts
index 5fc306ba..7e8853df 100644
--- a/src/consts.ts
+++ b/src/consts.ts
@@ -1,2 +1,9 @@
export const SITE_TITLE = 'Bianca Fiore';
export const SITE_DESCRIPTION = 'Welcome to my website!';
+
+export const DEFAULT_DATE_OPTIONS: Intl.DateTimeFormatOptions = {
+ weekday: 'long',
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+};
diff --git a/src/content/articles/first-post.md b/src/content/articles/first-post.md
index 169d2794..0e7c7ee9 100644
--- a/src/content/articles/first-post.md
+++ b/src/content/articles/first-post.md
@@ -3,6 +3,8 @@ title: 'First post'
description: 'Lorem ipsum dolor sit amet'
publishDate: 'Jul 08 2022'
featuredImage: ''
+tags: ['first', 'post']
+author: 'Bianca Fiore'
slug: 'first-post'
---
diff --git a/src/content/articles/markdown-style-guide.md b/src/content/articles/markdown-style-guide.md
index b2b14eb4..a293089a 100644
--- a/src/content/articles/markdown-style-guide.md
+++ b/src/content/articles/markdown-style-guide.md
@@ -3,6 +3,8 @@ title: 'Markdown Style Guide'
description: 'Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.'
publishDate: 'Jul 01 2022'
featuredImage: ''
+tags: ['second', 'post']
+author: 'Bianca Fiore'
slug: 'markdown-style-guide'
---
@@ -98,7 +100,7 @@ November 18, 2015.
#### Output
| Italics | Bold | Code |
-| --------- | -------- | ------ |
+|-----------|----------|--------|
| _italics_ | **bold** | `code` |
## Code Blocks
@@ -129,13 +131,13 @@ Output
```html
-
-
- Example HTML5 Document
-
-
- Test
-
+
+
+ Example HTML5 Document
+
+
+Test
+
```
@@ -162,40 +164,40 @@ Output
#### Syntax
```markdown
-- List item
-- Another item
-- And another item
+- List item
+- Another item
+- And another item
```
#### Output
-- List item
-- Another item
-- And another item
+- List item
+- Another item
+- And another item
### Nested list
#### Syntax
```markdown
-- Fruit
- - Apple
- - Orange
- - Banana
-- Dairy
- - Milk
- - Cheese
+- Fruit
+ - Apple
+ - Orange
+ - Banana
+- Dairy
+ - Milk
+ - Cheese
```
#### Output
-- Fruit
- - Apple
- - Orange
- - Banana
-- Dairy
- - Milk
- - Cheese
+- Fruit
+ - Apple
+ - Orange
+ - Banana
+- Dairy
+ - Milk
+ - Cheese
## Other Elements — abbr, sub, sup, kbd, mark
diff --git a/src/content/articles/second-post.md b/src/content/articles/second-post.md
index 6ea60b07..115aa3a2 100644
--- a/src/content/articles/second-post.md
+++ b/src/content/articles/second-post.md
@@ -3,6 +3,8 @@ title: 'Second post'
description: 'Lorem ipsum dolor sit amet'
publishDate: 'Jul 22 2022'
featuredImage: ''
+tags: ['post']
+author: 'Bianca Fiore'
slug: 'second-post'
---
diff --git a/src/content/articles/third-post.md b/src/content/articles/third-post.md
index d664cb6f..daa0b28b 100644
--- a/src/content/articles/third-post.md
+++ b/src/content/articles/third-post.md
@@ -3,6 +3,8 @@ title: 'Third post'
description: 'Lorem ipsum dolor sit amet'
publishDate: 'Jul 15 2022'
featuredImage: ''
+tags: []
+author: 'Bianca Fiore'
slug: 'third-post'
---
diff --git a/src/content/articles/using-mdx.mdx b/src/content/articles/using-mdx.mdx
index 70206593..ef3dbc8a 100644
--- a/src/content/articles/using-mdx.mdx
+++ b/src/content/articles/using-mdx.mdx
@@ -3,6 +3,8 @@ title: 'Using MDX'
description: 'Lorem ipsum dolor sit amet'
publishDate: 'Jul 02 2022'
featuredImage: ''
+tags: ['first', 'post']
+author: 'Bianca Fiore'
slug: 'using-mdx'
---
@@ -23,6 +25,8 @@ If you have existing content authored in MDX, this integration will hopefully ma
Here is how you import and use a UI component inside of MDX.
When you open this page in the browser, you should see the clickable button below.
+
+
import HeaderLink from '../../ui/components/atoms/headerLink/HeaderLink.astro';
@@ -34,5 +38,5 @@ import HeaderLink from '../../ui/components/atoms/headerLink/HeaderLink.astro';
- [MDX Syntax Documentation](https://mdxjs.com/docs/what-is-mdx)
- [Astro Usage Documentation](https://docs.astro.build/en/guides/markdown-content/#markdown-and-mdx-pages)
- **Note:** [Client Directives](https://docs.astro.build/en/reference/directives-reference/#client-directives) are
- still required to create interactive components. Otherwise, all components in your MDX will render as static HTML
- (no JavaScript) by default.
+still required to create interactive components. Otherwise, all components in your MDX will render as static HTML
+(no JavaScript) by default.
diff --git a/src/content/config.ts b/src/content/config.ts
index 026f76c2..ab42913e 100644
--- a/src/content/config.ts
+++ b/src/content/config.ts
@@ -7,6 +7,8 @@ const articles = defineCollection({
publishDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
featuredImage: z.string().optional(),
+ tags: z.string().array().optional(),
+ author: z.string(),
}),
});
diff --git a/src/pages/index.astro b/src/pages/index.astro
index f0b778f1..19e4ec14 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -5,11 +5,12 @@ import Testimonials from '@components/organisms/testimonials/Testimonials.astro'
import MyWork from '@components/organisms/myWork/MyWork.astro';
import LatestArticles from '@components/organisms/latestArticles/LatestArticles.astro';
-// current todo: fresh from the blog
+// current todo: fresh from the blog (variants)
// todo: latest articles following(https://scroll-driven-animations.style/demos/stacking-cards/css/)
// todo: reveal on enter viewport (check current implementation). add .reveal to test
// todo: SEO + HTML structure
// todo: view transitions
+// todo: theme toggle
// todo: add vitest
// todo: add CIs
---
@@ -18,13 +19,4 @@ import LatestArticles from '@components/organisms/latestArticles/LatestArticles.
-
-
-
-
-
-
-
-
-
diff --git a/src/pages/tags/[...tag].astro b/src/pages/tags/[...tag].astro
new file mode 100644
index 00000000..e76fbe13
--- /dev/null
+++ b/src/pages/tags/[...tag].astro
@@ -0,0 +1,32 @@
+---
+import { getCollection } from 'astro:content';
+import BaseLayout from 'src/ui/components/templates/baseLayout/BaseLayout.astro';
+import ArticleLayout from 'src/ui/components/templates/articleLayout/ArticleLayout.astro';
+
+export async function getStaticPaths() {
+ const allPosts = await getCollection('articles');
+ const uniqueTags = [...new Set(allPosts.map((post) => post.data.tags)?.flat())];
+
+ return uniqueTags?.map((tag) => {
+ const filteredPosts = allPosts.filter((post) =>
+ post.data.tags.includes(tag),
+ );
+ return {
+ params: { tag },
+ props: { posts: filteredPosts },
+ };
+ });
+}
+
+const { tag = '' } = Astro.params;
+const { posts } = Astro.props;
+---
+
+
+ Posts tagged with {tag}
+
+ {posts?.map((post) =>
+ ,
+ )}
+
+
diff --git a/src/pages/tags/index.astro b/src/pages/tags/index.astro
new file mode 100644
index 00000000..ef867d92
--- /dev/null
+++ b/src/pages/tags/index.astro
@@ -0,0 +1,7 @@
+---
+import BaseLayout from '@components/templates/baseLayout/BaseLayout.astro';
+---
+
+
+ Hello, blog!
+
diff --git a/src/ui/components/atoms/logo/logo.css b/src/ui/components/atoms/logo/logo.css
index c5ea42e8..91f97dcc 100644
--- a/src/ui/components/atoms/logo/logo.css
+++ b/src/ui/components/atoms/logo/logo.css
@@ -12,7 +12,7 @@
svg {
transition:
scale 0.2s,
- fill 0.2s;
+ fill 0.3s;
}
&.--is-scrolling:not(.--is-menu-open) svg {
diff --git a/src/ui/components/organisms/header/components/menuButton/menuButton.css b/src/ui/components/organisms/header/components/menuButton/menuButton.css
index e7c6156d..f379ecce 100644
--- a/src/ui/components/organisms/header/components/menuButton/menuButton.css
+++ b/src/ui/components/organisms/header/components/menuButton/menuButton.css
@@ -18,7 +18,7 @@
border: 1px solid var(--neutral-main);
height: calc(var(--header-height) * 0.85);
position: absolute;
- transition: border 0.3s;
+ transition: border 0.2s;
translate: 0 -25%;
width: calc(var(--header-height) * 0.85);
z-index: 20;
diff --git a/src/ui/components/organisms/header/utils/intersectionObserver/intersectionObserver.ts b/src/ui/components/organisms/header/utils/intersectionObserver/intersectionObserver.ts
index a1b9e80e..ede8ae17 100644
--- a/src/ui/components/organisms/header/utils/intersectionObserver/intersectionObserver.ts
+++ b/src/ui/components/organisms/header/utils/intersectionObserver/intersectionObserver.ts
@@ -1,39 +1,53 @@
+const SELECTORS = {
+ HEADER: '.header',
+ LATEST_ARTICLES: '.latest-articles__wrapper',
+ SITE_LOGO_SVG: '.site__logo svg',
+ HEADER_MENU_TEXT: '.header',
+ HEADER_MENU_OUTLINES: '.header__menu-button__outline',
+};
+
+const getComputedStyleValue = (property: string): string =>
+ getComputedStyle(document.documentElement).getPropertyValue(property);
+
+function isIntersecting(element: HTMLElement): boolean {
+ const { HEADER: HEADER_SELECTOR } = SELECTORS;
+ const headerOffsetHeight = (document.querySelector(HEADER_SELECTOR) as HTMLElement).offsetHeight / 2;
+ const threshold = element.offsetTop - headerOffsetHeight;
+ const sectionBottom = element.offsetTop + element.offsetHeight - headerOffsetHeight;
+
+ return window.scrollY >= threshold && window.scrollY < sectionBottom;
+}
+
export function intersectionObserver(): void {
- function handleScroll() {
- let hasIntersected = false;
- const WHITE = getComputedStyle(document.documentElement).getPropertyValue('--white');
- const BLACK = getComputedStyle(document.documentElement).getPropertyValue("--neutral-main'");
- const HEADER = document.querySelector('.header') as HTMLElement;
- const LATEST_ARTICLES = document.querySelector('.latest-articles__wrapper') as HTMLElement;
- const SITE_LOGO_SVG = document.querySelector('.site__logo svg') as HTMLElement;
- const HEADER_MENU_TEXT = document.querySelector('.header__menu-text') as HTMLElement;
- const HEADER_MENU_OUTLINES = document.querySelectorAll(
- '.header__menu-button__outline'
- ) as unknown as HTMLElement[];
- const ELEMENTS_TO_INTERSECT: HTMLElement[] = [LATEST_ARTICLES];
-
- if (!HEADER || !LATEST_ARTICLES) return;
-
- ELEMENTS_TO_INTERSECT.forEach(({ offsetTop, offsetHeight }) => {
- const headerOffsetHeight = HEADER.offsetHeight / 2;
- const threshold = offsetTop - headerOffsetHeight;
- const sectionBottom = offsetTop + offsetHeight - headerOffsetHeight;
-
- if (window.scrollY >= threshold && window.scrollY < sectionBottom) hasIntersected = true;
- });
-
- if (hasIntersected) {
- HEADER.classList.add('--hue-change');
- SITE_LOGO_SVG.style.fill = WHITE;
- HEADER_MENU_TEXT.style.color = WHITE;
- HEADER_MENU_OUTLINES.forEach((element) => (element.style.borderColor = WHITE));
- } else {
- HEADER.classList.remove('--hue-change');
- SITE_LOGO_SVG.style.fill = BLACK;
- HEADER_MENU_TEXT.style.color = BLACK;
- HEADER_MENU_OUTLINES.forEach((element) => (element.style.borderColor = BLACK));
- }
- }
+ const WHITE = getComputedStyleValue('--white');
+ const BLACK = getComputedStyleValue('--neutral-main');
+ const {
+ HEADER: HEADER_SELECTOR,
+ LATEST_ARTICLES: LATEST_ARTICLES_SELECTOR,
+ SITE_LOGO_SVG: SITE_LOGO_SVG_SELECTOR,
+ HEADER_MENU_TEXT: HEADER_MENU_TEXT_SELECTOR,
+ HEADER_MENU_OUTLINES: HEADER_MENU_OUTLINES_SELECTOR,
+ } = SELECTORS;
- window.addEventListener('scroll', handleScroll);
+ const HEADER = document.querySelector(HEADER_SELECTOR) as HTMLElement;
+ const LATEST_ARTICLES = document.querySelector(LATEST_ARTICLES_SELECTOR) as HTMLElement;
+ const SITE_LOGO_SVG = document.querySelector(SITE_LOGO_SVG_SELECTOR) as HTMLElement;
+ const HEADER_MENU_TEXT = document.querySelector(HEADER_MENU_TEXT_SELECTOR) as HTMLElement;
+ const HEADER_MENU_OUTLINES = document.querySelectorAll(HEADER_MENU_OUTLINES_SELECTOR) as unknown as HTMLElement[];
+
+ if (!HEADER || !LATEST_ARTICLES) return;
+
+ const hasIntersected = isIntersecting(LATEST_ARTICLES);
+
+ if (hasIntersected) {
+ SITE_LOGO_SVG.style.fill = WHITE;
+ HEADER_MENU_TEXT.style.color = WHITE;
+ HEADER_MENU_OUTLINES.forEach((element) => (element.style.borderColor = WHITE));
+ } else {
+ SITE_LOGO_SVG.style.fill = BLACK;
+ HEADER_MENU_TEXT.style.color = BLACK;
+ HEADER_MENU_OUTLINES.forEach((element) => (element.style.borderColor = BLACK));
+ }
}
+
+window.addEventListener('scroll', intersectionObserver);
diff --git a/src/ui/components/organisms/latestArticles/LatestArticles.astro b/src/ui/components/organisms/latestArticles/LatestArticles.astro
index 352f84e4..834051f7 100644
--- a/src/ui/components/organisms/latestArticles/LatestArticles.astro
+++ b/src/ui/components/organisms/latestArticles/LatestArticles.astro
@@ -1,6 +1,12 @@
---
import './latestArticles.css';
import { getCollection } from 'astro:content';
+import { DEFAULT_DATE_OPTIONS } from 'src/consts';
+
+const enum ArticleType {
+ FEATURED = 'featured',
+ DEFAULT = 'default',
+}
const MAX_ARTICLES = 4;
@@ -10,9 +16,12 @@ posts.sort((a, b) => new Date(b.data.publishDate) - new Date(a.data.publishDate)
-
+
{posts.map(({ slug, data }) => {
- const href = `/articles/${slug}`;
+ const variant: ArticleType = data.featuredImage ? ArticleType.FEATURED : ArticleType.DEFAULT;
+ const publishedDate = data.publishDate.toLocaleDateString('en', DEFAULT_DATE_OPTIONS);
+ const href = `/articles/${slug}`;
+ console.log(variant)
return (
-
@@ -21,9 +30,18 @@ posts.sort((a, b) => new Date(b.data.publishDate) - new Date(a.data.publishDate)
{data.title}
-
+ {data.featuredImage && (
+
+ )}
{data.description}
-
+
+ {data.author}
+ {data.tags?.map((tag) => (
+ {tag}
+ ))}
);
diff --git a/src/ui/components/organisms/latestArticles/latestArticles.css b/src/ui/components/organisms/latestArticles/latestArticles.css
index 67486f14..3c041878 100644
--- a/src/ui/components/organisms/latestArticles/latestArticles.css
+++ b/src/ui/components/organisms/latestArticles/latestArticles.css
@@ -12,4 +12,10 @@
display: inline-block;
}
}
+
+ .latest__article__item {
+ & > * {
+ color: var(--white);
+ }
+ }
}