feat: add Sal.js scroll animations

This commit is contained in:
Stefan Imhoff
2023-06-10 20:31:47 +02:00
parent bb32c6494c
commit f6205c1e4a
24 changed files with 195 additions and 37 deletions

View File

@@ -41,6 +41,7 @@
"react-chartjs-2": "^5.2.0", "react-chartjs-2": "^5.2.0",
"react-dom": "npm:@preact/compat@^17.1.2", "react-dom": "npm:@preact/compat@^17.1.2",
"reading-time": "^1.5.0", "reading-time": "^1.5.0",
"sal.js": "^0.8.5",
"sharp": "^0.32.1", "sharp": "^0.32.1",
"tailwindcss": "^3.3.2", "tailwindcss": "^3.3.2",
"unist-util-visit": "^4.1.2" "unist-util-visit": "^4.1.2"

8
pnpm-lock.yaml generated
View File

@@ -84,6 +84,9 @@ dependencies:
reading-time: reading-time:
specifier: ^1.5.0 specifier: ^1.5.0
version: 1.5.0 version: 1.5.0
sal.js:
specifier: ^0.8.5
version: 0.8.5
sharp: sharp:
specifier: ^0.32.1 specifier: ^0.32.1
version: 0.32.1 version: 0.32.1
@@ -11357,6 +11360,11 @@ packages:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
dev: true dev: true
/sal.js@0.8.5:
resolution: {integrity: sha512-KUb3fNrVZ1oWxxkEAfQfQ4Mrd910yboIRHqsvioBkulQInqMVeSMah+J5f7ch7KXFLicKlAaE0TzTsG/eJ02Dg==}
engines: {node: '>=12.0.0'}
dev: false
/sass-formatter@0.7.6: /sass-formatter@0.7.6:
resolution: {integrity: sha512-hXdxU6PCkiV3XAiSnX+XLqz2ohHoEnVUlrd8LEVMAI80uB1+OTScIkH9n6qQwImZpTye1r1WG1rbGUteHNhoHg==} resolution: {integrity: sha512-hXdxU6PCkiV3XAiSnX+XLqz2ohHoEnVUlrd8LEVMAI80uB1+OTScIkH9n6qQwImZpTye1r1WG1rbGUteHNhoHg==}
dependencies: dependencies:

View File

@@ -1,6 +1,8 @@
--- ---
import cx from 'classnames'; import cx from 'classnames';
import { animation, animationDelay } from '../data/site';
import Picture from './Picture.astro'; import Picture from './Picture.astro';
import { Headline } from '.'; import { Headline } from '.';
@@ -19,6 +21,7 @@ const imageLength = entry.data.images.length;
<div class="p-gap lg:w-2/6"> <div class="p-gap lg:w-2/6">
<div <div
class="w-[66ch] lg:sticky lg:top-[calc(100vh_/_2_-_(max(30vh,_250px)_/_2))] lg:h-[max(30vh,_250px)] lg:w-full" class="w-[66ch] lg:sticky lg:top-[calc(100vh_/_2_-_(max(30vh,_250px)_/_2))] lg:h-[max(30vh,_250px)] lg:w-full"
{...animationDelay}
> >
<Headline>{entry.data.title}</Headline> <Headline>{entry.data.title}</Headline>
<slot /> <slot />
@@ -35,10 +38,7 @@ const imageLength = entry.data.images.length;
> >
{ {
entry.data.images.map(({ src }: { src: string }, index: number) => ( entry.data.images.map(({ src }: { src: string }, index: number) => (
<Picture <div
alt={entry.data.title}
aspect={entry.data.aspect}
breakpoints={[300, 500, 700, 1000, 1280]}
class={cx('col-span-full w-full !mbe-0 lg:col-span-3 lg:max-w-full', { class={cx('col-span-full w-full !mbe-0 lg:col-span-3 lg:max-w-full', {
'justify-self-start lg:col-start-1': 'justify-self-start lg:col-start-1':
randomPosition() === 'start' && imageLength > 1 && index > 0, randomPosition() === 'start' && imageLength > 1 && index > 0,
@@ -48,9 +48,16 @@ const imageLength = entry.data.images.length;
randomPosition() === 'end' && imageLength > 1 && index > 0, randomPosition() === 'end' && imageLength > 1 && index > 0,
'lg:col-start-2': imageLength === 1 || index === 0, 'lg:col-start-2': imageLength === 1 || index === 0,
})} })}
{...animation}
>
<Picture
alt={entry.data.title}
aspect={entry.data.aspect}
breakpoints={[300, 500, 700, 1000, 1280]}
format={['webp', 'avif']} format={['webp', 'avif']}
src={src} src={src}
/> />
</div>
)) ))
} }
</div> </div>

View File

@@ -6,6 +6,8 @@ interface Props {
entries: CollectionEntry<'journal'>[]; entries: CollectionEntry<'journal'>[];
} }
import { animation } from '../data/site';
import { pickTwoRandomColors } from '../utils'; import { pickTwoRandomColors } from '../utils';
import { Link, Subsubheadline } from '../components'; import { Link, Subsubheadline } from '../components';
@@ -17,7 +19,7 @@ const { entries } = Astro.props;
> >
{ {
entries.map(({ slug, data }) => ( entries.map(({ slug, data }) => (
<li class="journal-card image-shadow group"> <li class="journal-card image-shadow group" {...animation}>
<Link title={data.title} href={`/${slug}/`} class="relative block h-full w-full"> <Link title={data.title} href={`/${slug}/`} class="relative block h-full w-full">
<div class="absolute z-10 flex h-full w-full flex-col items-center justify-center p-10 text-center leading-tight text-white"> <div class="absolute z-10 flex h-full w-full flex-col items-center justify-center p-10 text-center leading-tight text-white">
<Subsubheadline class="!m-0 leading-tight">{data.title}</Subsubheadline> <Subsubheadline class="!m-0 leading-tight">{data.title}</Subsubheadline>

View File

@@ -3,6 +3,8 @@ import cx from 'classnames';
import type { CollectionEntry } from 'astro:content'; import type { CollectionEntry } from 'astro:content';
import { animation } from '../data/site';
import ProjectContent from '../components/ProjectContent.astro'; import ProjectContent from '../components/ProjectContent.astro';
import ProjectImage from '../components/ProjectImage.astro'; import ProjectImage from '../components/ProjectImage.astro';
@@ -20,7 +22,7 @@ const {
const classes = cx('col-start-1 col-end-19 grid grid-cols-18', className); const classes = cx('col-start-1 col-end-19 grid grid-cols-18', className);
--- ---
<article class={classes}> <article class={classes} {...animation}>
{ {
format === '50-start' && ( format === '50-start' && (
<figure class="col-start-2 col-end-18 m-0 grid grid-cols-2 items-center gap-x-gap gap-y-halfgap"> <figure class="col-start-2 col-end-18 m-0 grid grid-cols-2 items-center gap-x-gap gap-y-halfgap">
@@ -35,7 +37,10 @@ const classes = cx('col-start-1 col-end-19 grid grid-cols-18', className);
} }
{ {
format === '50-end' && ( format === '50-end' && (
<figure class="col-start-2 col-end-18 m-0 grid grid-cols-2 items-center gap-x-gap gap-y-halfgap"> <figure
class="col-start-2 col-end-18 m-0 grid grid-cols-2 items-center gap-x-gap gap-y-halfgap"
{...animation}
>
<div class="col-start-1 col-end-3 row-start-1 md:col-start-2 md:row-start-1"> <div class="col-start-1 col-end-3 row-start-1 md:col-start-2 md:row-start-1">
<ProjectImage project={project} /> <ProjectImage project={project} />
</div> </div>
@@ -47,7 +52,10 @@ const classes = cx('col-start-1 col-end-19 grid grid-cols-18', className);
} }
{ {
format === '70-start' && ( format === '70-start' && (
<figure class="col-start-1 col-end-19 row-start-1 grid grid-cols-18 gap-x-gap gap-y-halfgap"> <figure
class="col-start-1 col-end-19 row-start-1 grid grid-cols-18 gap-x-gap gap-y-halfgap"
{...animation}
>
<div class=" col-start-1 col-end-19 grid self-start xl:col-end-13"> <div class=" col-start-1 col-end-19 grid self-start xl:col-end-13">
<ProjectImage project={project} /> <ProjectImage project={project} />
</div> </div>
@@ -59,7 +67,10 @@ const classes = cx('col-start-1 col-end-19 grid grid-cols-18', className);
} }
{ {
format === '70-end' && ( format === '70-end' && (
<figure class="col-start-1 col-end-19 row-start-1 grid grid-cols-18 gap-x-gap gap-y-halfgap"> <figure
class="col-start-1 col-end-19 row-start-1 grid grid-cols-18 gap-x-gap gap-y-halfgap"
{...animation}
>
<div class=" col-start-1 col-end-19 row-start-1 grid self-start xl:col-start-7 xl:col-end-19"> <div class=" col-start-1 col-end-19 row-start-1 grid self-start xl:col-start-7 xl:col-end-19">
<ProjectImage project={project} /> <ProjectImage project={project} />
</div> </div>
@@ -71,7 +82,10 @@ const classes = cx('col-start-1 col-end-19 grid grid-cols-18', className);
} }
{ {
format === '100-start' && ( format === '100-start' && (
<figure class="col-start-1 col-end-19 row-start-1 grid grid-cols-18 gap-x-gap gap-y-halfgap"> <figure
class="col-start-1 col-end-19 row-start-1 grid grid-cols-18 gap-x-gap gap-y-halfgap"
{...animation}
>
<div class=" col-start-1 col-end-19 row-start-1"> <div class=" col-start-1 col-end-19 row-start-1">
<ProjectImage project={project} /> <ProjectImage project={project} />
</div> </div>
@@ -83,7 +97,10 @@ const classes = cx('col-start-1 col-end-19 grid grid-cols-18', className);
} }
{ {
format === '100-end' && ( format === '100-end' && (
<figure class="col-start-1 col-end-19 row-start-1 grid grid-cols-18 gap-x-gap gap-y-halfgap"> <figure
class="col-start-1 col-end-19 row-start-1 grid grid-cols-18 gap-x-gap gap-y-halfgap"
{...animation}
>
<div class=" col-start-1 col-end-19 row-start-1"> <div class=" col-start-1 col-end-19 row-start-1">
<ProjectImage project={project} /> <ProjectImage project={project} />
</div> </div>

28
src/components/Sal.astro Normal file
View File

@@ -0,0 +1,28 @@
---
import '../../node_modules/sal.js/dist/sal.css';
---
<script src="../../node_modules/sal.js/dist/sal.js" defer></script>
<script type="module">
if ('querySelector' in document && 'localStorage' in window && 'addEventListener' in window) {
sal({
threshold: 0.1,
});
}
</script>
<style is:global>
.no-js [data-sal|='fade'] {
opacity: 1;
}
.no-js [data-sal|='slide'],
.no-js [data-sal|='zoom'] {
opacity: 1;
transform: none;
}
.no-js [data-sal|='flip'] {
transform: none;
}
</style>

View File

@@ -1,3 +1,25 @@
const animationType = 'slide-up';
const delay = 300;
const duration = 800;
const easing = 'ease-out-sine';
export const site = { export const site = {
title: 'Stefan Imhoff',
description: 'Front-End Web Developer from Hamburg, Germany',
url: 'https://www.stefanimhoff.de',
author: 'Stefan Imhoff', author: 'Stefan Imhoff',
tagline: 'Front-End Web Developer • Designer • Minimalist • Japanophile',
faviconPath: '/assets/images/branding/favicons/',
twitter: '@kogakure',
};
export const animation = {
'data-sal': animationType,
'data-sal-duration': duration,
'data-sal-easing': easing,
};
export const animationDelay = {
...animation,
'data-sal-delay': delay,
}; };

View File

@@ -5,6 +5,7 @@ import { Sprite } from 'astro-icon';
import ThemeProvider from '../components/ThemeProvider.astro'; import ThemeProvider from '../components/ThemeProvider.astro';
import PageHeader from '../components/PageHeader.astro'; import PageHeader from '../components/PageHeader.astro';
import PageFooter from '../components/PageFooter.astro'; import PageFooter from '../components/PageFooter.astro';
import Sal from '../components/Sal.astro';
export interface Props { export interface Props {
backLink?: string; backLink?: string;
@@ -53,6 +54,7 @@ const { backLink, footer = true, header = true, title, description } = Astro.pro
rel="preload" rel="preload"
type="font/woff2" type="font/woff2"
/> />
<Sal />
<ThemeProvider /> <ThemeProvider />
</head> </head>
<body <body

View File

@@ -1,4 +1,6 @@
--- ---
import { animation, animationDelay } from '../data/site';
import GridLayout from '../layouts/GridLayout.astro'; import GridLayout from '../layouts/GridLayout.astro';
import PageTitle from '../components/PageTitle.astro'; import PageTitle from '../components/PageTitle.astro';
@@ -16,6 +18,7 @@ const description = 'Page not found.';
<Verse <Verse
class="z-10 col-start-1 col-end-17 row-start-2 text-3 italic mbe-10 mbs-10 md:col-start-3 md:col-end-9" class="z-10 col-start-1 col-end-17 row-start-2 text-3 italic mbe-10 mbs-10 md:col-start-3 md:col-end-9"
variant="left" variant="left"
{...animation}
> >
<Haiku components={mapping} /> <Haiku components={mapping} />
</Verse> </Verse>
@@ -23,6 +26,7 @@ const description = 'Page not found.';
aria-hidden="true" aria-hidden="true"
class="col-start-10 col-end-13 row-start-1 row-end-3 text-9 font-black text-black/[0.05] dark:text-white/[0.05]" class="col-start-10 col-end-13 row-start-1 row-end-3 text-9 font-black text-black/[0.05] dark:text-white/[0.05]"
role="img" role="img"
{...animationDelay}
> >
404 404
</span> </span>

View File

@@ -4,9 +4,12 @@ title: About
description: Im Stefan Imhoff, a Front-End Web Developer, and Designer from Hamburg, Germany. description: Im Stefan Imhoff, a Front-End Web Developer, and Designer from Hamburg, Germany.
--- ---
import { animation } from "../data/site";
import { mapping } from "../mdx-components.ts"; import { mapping } from "../mdx-components.ts";
export const components = mapping; export const components = mapping;
<div {...animation}>
Im _Stefan Imhoff_, a Senior Front-End Web Developer, and Designer from Hamburg, Germany. Im _Stefan Imhoff_, a Senior Front-End Web Developer, and Designer from Hamburg, Germany.
I find inspiration in a wide variety of media, from reading challenging and heterodox [books](https://goodreads.com/kogakure) about philosophy, science, and economics to listening to [podcasts](https://raindrop.io/kogakure/podcasts-24118384), watching [TV shows](https://www.themoviedb.org/u/kogakure/favorites/tv) and [movies](https://www.themoviedb.org/u/kogakure/favorites), and indulging in [Korean](https://www.themoviedb.org/list/8216385) and [Japanese](https://www.themoviedb.org/list/106001) dramas on Netflix. I find inspiration in a wide variety of media, from reading challenging and heterodox [books](https://goodreads.com/kogakure) about philosophy, science, and economics to listening to [podcasts](https://raindrop.io/kogakure/podcasts-24118384), watching [TV shows](https://www.themoviedb.org/u/kogakure/favorites/tv) and [movies](https://www.themoviedb.org/u/kogakure/favorites), and indulging in [Korean](https://www.themoviedb.org/list/8216385) and [Japanese](https://www.themoviedb.org/list/106001) dramas on Netflix.
@@ -15,6 +18,8 @@ As a passionate enthusiast of storytelling, I am convinced that humans understan
In my spare time, I enjoy exploring nature through activities such as [walking and cycling](https://hamburg.stefanimhoff.de/), and doing [Calisthenics](/calisthenics/). I have a keen appreciation for the beauty of everyday life and find joy in the small things. Whether its the peacefulness of a forest, the vastness of the sea, or the grandeur of a mountain, I am constantly inspired by natures magnificence. I enjoy both the power of thunderstorms and the warmth of sunny days. In my spare time, I enjoy exploring nature through activities such as [walking and cycling](https://hamburg.stefanimhoff.de/), and doing [Calisthenics](/calisthenics/). I have a keen appreciation for the beauty of everyday life and find joy in the small things. Whether its the peacefulness of a forest, the vastness of the sea, or the grandeur of a mountain, I am constantly inspired by natures magnificence. I enjoy both the power of thunderstorms and the warmth of sunny days.
</div>
--- ---
I see myself as a 🔲 [Minimalist](/minimalism/), 🏛️ Stoic, 🎧 Introvert, and ⛩️ Japanophile. I see myself as a 🔲 [Minimalist](/minimalism/), 🏛️ Stoic, 🎧 Introvert, and ⛩️ Japanophile.

View File

@@ -5,6 +5,8 @@ import { getCollection } from 'astro:content';
import { sortBySortKey } from '../utils'; import { sortBySortKey } from '../utils';
import { animation } from '../data/site';
import GridLayout from '../layouts/GridLayout.astro'; import GridLayout from '../layouts/GridLayout.astro';
import PageTitle from '../components/PageTitle.astro'; import PageTitle from '../components/PageTitle.astro';
import Picture from '../components/Picture.astro'; import Picture from '../components/Picture.astro';
@@ -25,6 +27,7 @@ const description = '…';
<article <article
class="col-start-1 col-end-18 grid md:col-start-4 md:col-end-12 xl:col-start-5 xl:col-end-11" class="col-start-1 col-end-18 grid md:col-start-4 md:col-end-12 xl:col-start-5 xl:col-end-11"
{...animation}
> >
<Intro components={mapping} /> <Intro components={mapping} />
</article> </article>
@@ -56,6 +59,7 @@ const description = '…';
'md:col-span-6 md:row-span-6': 'md:col-span-6 md:row-span-6':
data.images[0].aspectRatio === 1 && data.coverSize === 'large', data.images[0].aspectRatio === 1 && data.coverSize === 'large',
})} })}
{...animation}
> >
<Link title={data.title} href={`/ai-art/${slug}/`}> <Link title={data.title} href={`/ai-art/${slug}/`}>
<Picture <Picture

View File

@@ -5,11 +5,18 @@ description: …
intro: In publishing, a colophon is a brief statement containing information about the publication. intro: In publishing, a colophon is a brief statement containing information about the publication.
--- ---
import { animation, animationDelay } from "../data/site";
import { mapping } from "../mdx-components.ts"; import { mapping } from "../mdx-components.ts";
export const components = mapping; export const components = mapping;
<div {...animation}>
The source code of this website is available on [GitHub](https://github.com/kogakure/website-astro-stefanimhoff.de). You are welcome to learn from the source code and reuse code for your projects. Dont steal it. Learn from it. Remix. Reuse. Build your own things. 🤘 The source code of this website is available on [GitHub](https://github.com/kogakure/website-astro-stefanimhoff.de). You are welcome to learn from the source code and reuse code for your projects. Dont steal it. Learn from it. Remix. Reuse. Build your own things. 🤘
</div>
<div {...animationDelay}>
## Design ## Design
- I designed the website myself in [Affinity Designer](https://affinity.serif.com/designer/), using the Japanese art form of _shibui_ (渋い) as a source of inspiration. To learn more about the process, please read the essays about the [inspiration](/new-website-2020-inspiration/) and [design](/new-website-2020-design/). - I designed the website myself in [Affinity Designer](https://affinity.serif.com/designer/), using the Japanese art form of _shibui_ (渋い) as a source of inspiration. To learn more about the process, please read the essays about the [inspiration](/new-website-2020-inspiration/) and [design](/new-website-2020-design/).
@@ -17,6 +24,10 @@ The source code of this website is available on [GitHub](https://github.com/koga
- I created the Bonsai image on my homepage with [Stable Diffusion](https://stability.ai/), [ControlNet](https://github.com/lllyasviel/ControlNet), and [Affinity Photo](https://affinity.serif.com/photo/). - I created the Bonsai image on my homepage with [Stable Diffusion](https://stability.ai/), [ControlNet](https://github.com/lllyasviel/ControlNet), and [Affinity Photo](https://affinity.serif.com/photo/).
- The minimalistic icons are by [Remix Icon](https://remixicon.com/), which is [Jimmy Cheung](https://github.com/xiaochunjimmy) and [Wendy Gao](https://github.com/wendygaoyuan). - The minimalistic icons are by [Remix Icon](https://remixicon.com/), which is [Jimmy Cheung](https://github.com/xiaochunjimmy) and [Wendy Gao](https://github.com/wendygaoyuan).
</div>
<div {...animationDelay}>
## Technology ## Technology
- The website is built with [Astro](https://astro.build/), the all-in-one web framework. - The website is built with [Astro](https://astro.build/), the all-in-one web framework.
@@ -31,3 +42,5 @@ The source code of this website is available on [GitHub](https://github.com/koga
- I use [reading-time](https://github.com/ngryman/reading-time) to add the reading time to Remark. - I use [reading-time](https://github.com/ngryman/reading-time) to add the reading time to Remark.
- To parse and format dates I use [Moment.js](https://momentjs.com/). - To parse and format dates I use [Moment.js](https://momentjs.com/).
- I use [Plop](https://plopjs.com/) to generate content from templates. - I use [Plop](https://plopjs.com/) to generate content from templates.
</div>

View File

@@ -1,4 +1,6 @@
--- ---
import { animation, animationDelay } from '../data/site';
import GridLayout from '../layouts/GridLayout.astro'; import GridLayout from '../layouts/GridLayout.astro';
import PageTitle from '../components/PageTitle.astro'; import PageTitle from '../components/PageTitle.astro';
import DownloadLink from '../components/DownloadLink.astro'; import DownloadLink from '../components/DownloadLink.astro';
@@ -27,12 +29,12 @@ const description = '';
<GridLayout title={title} description={description} grid="wide" class="grid" innerGrid> <GridLayout title={title} description={description} grid="wide" class="grid" innerGrid>
<PageTitle grid="wide" innerGrid>Curriculum Vitae</PageTitle> <PageTitle grid="wide" innerGrid>Curriculum Vitae</PageTitle>
<article class="col-span-full md:col-start-1 md:col-end-9"> <article class="col-span-full md:col-start-1 md:col-end-9" {...animation}>
<Headline>{cv.summary.headline}</Headline> <Headline>{cv.summary.headline}</Headline>
<Intro components={mapping} /> <Intro components={mapping} />
</article> </article>
<article class="col-span-full md:col-start-10 md:col-end-18"> <article class="col-span-full md:col-start-10 md:col-end-18" {...animationDelay}>
<Headline>Personal Information</Headline> <Headline>Personal Information</Headline>
<Subheadline class="font-semibold">{cv.personal.name}</Subheadline> <Subheadline class="font-semibold">{cv.personal.name}</Subheadline>
<Text class="!mbe-0">{cv.personal.tagline}</Text> <Text class="!mbe-0">{cv.personal.tagline}</Text>

View File

@@ -2,6 +2,7 @@
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
import { sortByDate } from '../utils'; import { sortByDate } from '../utils';
import { animation, animationDelay } from '../data/site';
import GridLayout from '../layouts/GridLayout.astro'; import GridLayout from '../layouts/GridLayout.astro';
import PageTitle from '../components/PageTitle.astro'; import PageTitle from '../components/PageTitle.astro';
@@ -22,6 +23,7 @@ const description = '…';
<article <article
class="col-start-1 col-end-17 grid md:col-start-4 md:col-end-12 xl:col-start-5 xl:col-end-11" class="col-start-1 col-end-17 grid md:col-start-4 md:col-end-12 xl:col-start-5 xl:col-end-11"
{...animation}
> >
<Intro components={mapping} /> <Intro components={mapping} />
</article> </article>
@@ -29,6 +31,7 @@ const description = '…';
<nav class="col-start-1 col-end-17 md:col-start-2 md:col-end-14" aria-label="Haiku"> <nav class="col-start-1 col-end-17 md:col-start-2 md:col-end-14" aria-label="Haiku">
<ol <ol
class="grid list-none grid-cols-[repeat(auto-fill,_minmax(3rem,_1fr))] justify-items-center gap-[1rem]" class="grid list-none grid-cols-[repeat(auto-fill,_minmax(3rem,_1fr))] justify-items-center gap-[1rem]"
{...animationDelay}
> >
{ {
allHaiku.map(({ slug }) => ( allHaiku.map(({ slug }) => (

View File

@@ -2,6 +2,7 @@
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
import { sortByDate } from '../../utils'; import { sortByDate } from '../../utils';
import { animation, animationDelay } from '../../data/site';
import BaseLayout from '../../layouts/BaseLayout.astro'; import BaseLayout from '../../layouts/BaseLayout.astro';
import PageHeader from '../../components/PageHeader.astro'; import PageHeader from '../../components/PageHeader.astro';
@@ -41,13 +42,16 @@ const description = '…';
class="min-[700px]:grid-cols-[repeat(auto-fit,_minmax(25rem,_1fr)] col-span-full row-start-1 row-end-3 grid w-full grid-cols-[repeat(auto-fit,_minmax(15rem,_1fr))]" class="min-[700px]:grid-cols-[repeat(auto-fit,_minmax(25rem,_1fr)] col-span-full row-start-1 row-end-3 grid w-full grid-cols-[repeat(auto-fit,_minmax(15rem,_1fr))]"
> >
<div class="grid h-full w-full items-center"> <div class="grid h-full w-full items-center">
<div {...animation}>
<Verse <Verse
class="justify-center text-center text-3 font-black not-italic !leading-relaxed min-[700px]:text-4" class="justify-center text-center text-3 font-black not-italic !leading-relaxed min-[700px]:text-4"
> >
{entry.data.de} {entry.data.de}
</Verse> </Verse>
</div> </div>
</div>
<div class="grid h-full w-full items-center bg-[#d0cdc8] dark:bg-[#0e0d0c]"> <div class="grid h-full w-full items-center bg-[#d0cdc8] dark:bg-[#0e0d0c]">
<div {...animationDelay}>
<Verse <Verse
class="justify-center text-center text-3 font-black not-italic !leading-relaxed min-[700px]:text-4" class="justify-center text-center text-3 font-black not-italic !leading-relaxed min-[700px]:text-4"
> >
@@ -56,6 +60,7 @@ const description = '…';
</div> </div>
</div> </div>
</div> </div>
</div>
<Pagination <Pagination
nextText={`Haiku ${next.slug}`} nextText={`Haiku ${next.slug}`}
nextUrl={next.slug && `/haiku/${next.slug}`} nextUrl={next.slug && `/haiku/${next.slug}`}

View File

@@ -3,6 +3,8 @@ import { getCollection } from 'astro:content';
import { formatPosts } from '../utils'; import { formatPosts } from '../utils';
import { site, animation, animationDelay } from '../data/site';
import GridLayout from '../layouts/GridLayout.astro'; import GridLayout from '../layouts/GridLayout.astro';
import MoreLink from '../components/MoreLink.astro'; import MoreLink from '../components/MoreLink.astro';
@@ -27,9 +29,9 @@ const description = '…';
<GridLayout title={title} description={description} grid="fullsize" class="grid" innerGrid> <GridLayout title={title} description={description} grid="fullsize" class="grid" innerGrid>
<PageTitle class="!text-6 sm:!text-7"> <PageTitle class="!text-6 sm:!text-7">
Stefan Imhoff {site.title}
<small class="block text-[0.235em] font-light tracking-normal dark:text-[0.23em]" <small class="block text-[0.235em] font-light tracking-normal dark:text-[0.23em]"
>Front-End Web Developer • Designer • Minimalist • Japanophile</small >{site.tagline}</small
> >
</PageTitle> </PageTitle>
<div <div
@@ -45,6 +47,7 @@ const description = '…';
<article <article
class="col-start-2 col-end-18 row-start-3 self-center md:col-start-12 md:row-start-2 xl:col-start-13 xl:col-end-17" class="col-start-2 col-end-18 row-start-3 self-center md:col-start-12 md:row-start-2 xl:col-start-13 xl:col-end-17"
{...animation}
> >
<Headline>About Me</Headline> <Headline>About Me</Headline>
<AboutMe components={mapping} /> <AboutMe components={mapping} />
@@ -53,6 +56,7 @@ const description = '…';
<article <article
class="col-start-2 col-end-18 row-start-4 md:col-start-3 md:col-end-17 md:row-start-3 xl:col-start-5 xl:col-end-15" class="col-start-2 col-end-18 row-start-4 md:col-start-3 md:col-end-17 md:row-start-3 xl:col-start-5 xl:col-end-15"
{...animationDelay}
> >
<Headline>What I Do</Headline> <Headline>What I Do</Headline>
<div class="columns-1 gap-[2.775vw] mbe-10 md:columns-2 [&_p:last-of-type]:mbe-0"> <div class="columns-1 gap-[2.775vw] mbe-10 md:columns-2 [&_p:last-of-type]:mbe-0">
@@ -63,6 +67,7 @@ const description = '…';
<article <article
class="col-start-2 col-end-18 md:col-start-6 md:col-end-14 xl:col-start-7 xl:col-end-13" class="col-start-2 col-end-18 md:col-start-6 md:col-end-14 xl:col-start-7 xl:col-end-13"
{...animation}
> >
<Headline>Journal</Headline> <Headline>Journal</Headline>
<Journal components={mapping} /> <Journal components={mapping} />
@@ -71,6 +76,7 @@ const description = '…';
<article <article
class="min-[1794px]:[&_li:block col-start-2 col-end-18 grid w-full grid-cols-18 gap-y-gap mbe-12 min-[1097px]:[&_li:nth-child(n+5)]:hidden min-[1410px]:[&_li:nth-child(n+5)]:block min-[1411px]:[&_li:nth-child(n+6)]:hidden min-[1793px]:[&_li:nth-child(n+6)]:block" class="min-[1794px]:[&_li:block col-start-2 col-end-18 grid w-full grid-cols-18 gap-y-gap mbe-12 min-[1097px]:[&_li:nth-child(n+5)]:hidden min-[1410px]:[&_li:nth-child(n+5)]:block min-[1411px]:[&_li:nth-child(n+6)]:hidden min-[1793px]:[&_li:nth-child(n+6)]:block"
{...animation}
> >
<JournalList entries={formattedLatest} /> <JournalList entries={formattedLatest} />
</article> </article>

View File

@@ -3,6 +3,8 @@ import { getCollection } from 'astro:content';
import { formatPosts } from '../utils'; import { formatPosts } from '../utils';
import { animation, animationDelay } from '../data/site';
import GridLayout from '../layouts/GridLayout.astro'; import GridLayout from '../layouts/GridLayout.astro';
import PageTitle from '../components/PageTitle.astro'; import PageTitle from '../components/PageTitle.astro';
import JournalList from '../components/JournalList.astro'; import JournalList from '../components/JournalList.astro';
@@ -27,10 +29,11 @@ const description = 'I am writing essays about various topics in this Journal.';
<article <article
class="col-start-1 col-end-18 grid md:col-start-4 md:col-end-12 xl:col-start-5 xl:col-end-11" class="col-start-1 col-end-18 grid md:col-start-4 md:col-end-12 xl:col-start-5 xl:col-end-11"
{...animation}
> >
<Intro components={mapping} /> <Intro components={mapping} />
</article> </article>
<aside class="col-start-1 col-end-18 flex flex-wrap gap-y-3"> <aside class="col-start-1 col-end-18 flex flex-wrap gap-y-3" {...animationDelay}>
{uniqueTags.map((tag) => <Tag href={`/tag/${tag}/`}>{tag}</Tag>)} {uniqueTags.map((tag) => <Tag href={`/tag/${tag}/`}>{tag}</Tag>)}
</aside> </aside>
<nav class="col-start-1 col-end-18" aria-label="Journal"> <nav class="col-start-1 col-end-18" aria-label="Journal">

View File

@@ -4,11 +4,18 @@ title: Now
description: … description: …
--- ---
import { animation, animationDelay } from "../data/site";
import { mapping } from "../mdx-components.ts"; import { mapping } from "../mdx-components.ts";
export const components = mapping; export const components = mapping;
<div {...animation}>
This is my [Now](https://nownownow.com/) page, an idea by [Derek Silvers](https://sive.rs/) for a website with the focus of <q>what this person is focused on at this point in their life.</q> This is my [Now](https://nownownow.com/) page, an idea by [Derek Silvers](https://sive.rs/) for a website with the focus of <q>what this person is focused on at this point in their life.</q>
</div>
<div {...animationDelay}>
- Building the Design System of XING 👨‍💻 - Building the Design System of XING 👨‍💻
- Working from home 🏡 - Working from home 🏡
- Learning Japanese 🇯🇵 and Spanish 🇪🇸 on [Duolingo](https://www.duolingo.com/profile/kogakure) 🦉 - Learning Japanese 🇯🇵 and Spanish 🇪🇸 on [Duolingo](https://www.duolingo.com/profile/kogakure) 🦉
@@ -17,3 +24,5 @@ This is my [Now](https://nownownow.com/) page, an idea by [Derek Silvers](https:
- Creating and reviewing highlights with [Readwise](https://readwise.io/i/stefan805) 📝 every day - Creating and reviewing highlights with [Readwise](https://readwise.io/i/stefan805) 📝 every day
- Connecting ideas with the [Zettelkasten](https://en.wikipedia.org/wiki/Zettelkasten) 🗃️ note-taking methods, using [Obsidian](https://obsidian.md/) - Connecting ideas with the [Zettelkasten](https://en.wikipedia.org/wiki/Zettelkasten) 🗃️ note-taking methods, using [Obsidian](https://obsidian.md/)
- Always reading at least two or three [books](https://www.goodreads.com/kogakure) 📚 at the same time - Always reading at least two or three [books](https://www.goodreads.com/kogakure) 📚 at the same time
</div>

View File

@@ -3,6 +3,8 @@ import { getCollection } from 'astro:content';
import { sortBySortKey } from '../utils'; import { sortBySortKey } from '../utils';
import { animation } from '../data/site';
import GridLayout from '../layouts/GridLayout.astro'; import GridLayout from '../layouts/GridLayout.astro';
import PageTitle from '../components/PageTitle.astro'; import PageTitle from '../components/PageTitle.astro';
import ProjectContainer from '../components/ProjectContainer.astro'; import ProjectContainer from '../components/ProjectContainer.astro';
@@ -27,7 +29,7 @@ const description =
Projects Projects
</PageTitle> </PageTitle>
<article class="col-start-2 col-end-18 md:col-start-6 md:col-end-14"> <article class="col-start-2 col-end-18 md:col-start-6 md:col-end-14" {...animation}>
<Intro components={mapping} /> <Intro components={mapping} />
</article> </article>

View File

@@ -4,6 +4,7 @@ import cx from 'classnames';
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
import { sortBySortKey } from '../utils'; import { sortBySortKey } from '../utils';
import { animation } from '../data/site';
import GridLayout from '../layouts/GridLayout.astro'; import GridLayout from '../layouts/GridLayout.astro';
import PageTitle from '../components/PageTitle.astro'; import PageTitle from '../components/PageTitle.astro';
@@ -25,6 +26,7 @@ const description = 'This is a collection of Sketchnotes Ive drawn.';
<article <article
class="col-start-1 col-end-17 grid md:col-start-4 md:col-end-12 xl:col-start-5 xl:col-end-11" class="col-start-1 col-end-17 grid md:col-start-4 md:col-end-12 xl:col-start-5 xl:col-end-11"
{...animation}
> >
<Intro components={mapping} /> <Intro components={mapping} />
</article> </article>
@@ -50,6 +52,7 @@ const description = 'This is a collection of Sketchnotes Ive drawn.';
'md:col-span-5 md:row-span-6': 'md:col-span-5 md:row-span-6':
data.images[0].aspectRatio < 1 && data.coverSize === 'large', data.images[0].aspectRatio < 1 && data.coverSize === 'large',
})} })}
{...animation}
> >
<Link title={data.title} href={`/sketchnotes/${slug}/`}> <Link title={data.title} href={`/sketchnotes/${slug}/`}>
<Picture <Picture

View File

@@ -1,6 +1,8 @@
--- ---
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
import { animation } from '../data/site';
import GridLayout from '../layouts/GridLayout.astro'; import GridLayout from '../layouts/GridLayout.astro';
import PageTitle from '../components/PageTitle.astro'; import PageTitle from '../components/PageTitle.astro';
import { Tag } from '../components'; import { Tag } from '../components';
@@ -22,7 +24,7 @@ const description = '…';
title={title} title={title}
> >
<PageTitle grid="wide" innerGrid>Tags</PageTitle> <PageTitle grid="wide" innerGrid>Tags</PageTitle>
<aside class="col-start-1 col-end-18 flex flex-wrap gap-y-3"> <aside class="col-start-1 col-end-18 flex flex-wrap gap-y-3" {...animation}>
{uniqueTags.map((t) => <Tag href={`/tag/${t}/`}>{t}</Tag>)} {uniqueTags.map((t) => <Tag href={`/tag/${t}/`}>{t}</Tag>)}
</aside> </aside>
</GridLayout> </GridLayout>

View File

@@ -2,6 +2,7 @@
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
import { formatPosts } from '../../utils'; import { formatPosts } from '../../utils';
import { animationDelay } from '../../data/site';
import GridLayout from '../../layouts/GridLayout.astro'; import GridLayout from '../../layouts/GridLayout.astro';
import PageTitle from '../../components/PageTitle.astro'; import PageTitle from '../../components/PageTitle.astro';
@@ -53,7 +54,7 @@ const description = '…';
<PageTitle slot="title" class="capitalize"> <PageTitle slot="title" class="capitalize">
{tag} {tag}
</PageTitle> </PageTitle>
<aside class="col-start-1 col-end-18 flex flex-wrap gap-y-3"> <aside class="col-start-1 col-end-18 flex flex-wrap gap-y-3" {...animationDelay}>
{ {
uniqueTags.map((uTag) => ( uniqueTags.map((uTag) => (
<Tag active={uTag === tag} href={`/tag/${uTag}/`}> <Tag active={uTag === tag} href={`/tag/${uTag}/`}>

View File

@@ -13,8 +13,6 @@ export const components = mapping;
## Home Office ## Home Office
<AffiliateLink asin="" text="" />
My desk is a [Jarvis Bamboo Standing](https://www.fully.com/standing-desks/jarvis/jarvis-adjustable-height-desk-bamboo.html) Desk by Fully in 140 cm. The chair is a [Capisco](https://www.fully.com/chairs/for-standing-desks/hag-capisco-chair.html) by HÅG with black leather. I use a <AffiliateLink asin="B07PXDSSZP" text="black leather desk pad" /> in 75 cm. I use an aluminum <AffiliateLink asin="B01F01DRW6" text="MacBook stand" /> and a <AffiliateLink asin="B01M8HGTX8" text="bamboo book rest" /> on my desk. The <AffiliateLink asin="B07GGVNXSW" text="BenQ Screenbar Plus" /> provides good lighting. On top of the light is an <AffiliateLink asin="B09MFMTMPD" text="Anker PowerConf C200" /> webcam. My desk is a [Jarvis Bamboo Standing](https://www.fully.com/standing-desks/jarvis/jarvis-adjustable-height-desk-bamboo.html) Desk by Fully in 140 cm. The chair is a [Capisco](https://www.fully.com/chairs/for-standing-desks/hag-capisco-chair.html) by HÅG with black leather. I use a <AffiliateLink asin="B07PXDSSZP" text="black leather desk pad" /> in 75 cm. I use an aluminum <AffiliateLink asin="B01F01DRW6" text="MacBook stand" /> and a <AffiliateLink asin="B01M8HGTX8" text="bamboo book rest" /> on my desk. The <AffiliateLink asin="B07GGVNXSW" text="BenQ Screenbar Plus" /> provides good lighting. On top of the light is an <AffiliateLink asin="B09MFMTMPD" text="Anker PowerConf C200" /> webcam.
## Tech ## Tech

View File

@@ -8,6 +8,7 @@ import { Content as Intro } from '../text/traditional-colors-of-japan/intro.mdx'
import colors from '../data/colors-japan.json'; import colors from '../data/colors-japan.json';
import { mapping } from '../mdx-components'; import { mapping } from '../mdx-components';
import { animation, animationDelay } from '../data/site';
const title = 'The Traditional Colors of Japan'; const title = 'The Traditional Colors of Japan';
const description = const description =
@@ -17,11 +18,14 @@ const description =
<GridLayout title={title} description={description} grid="wide" class="grid" innerGrid> <GridLayout title={title} description={description} grid="wide" class="grid" innerGrid>
<PageTitle grid="wide" innerGrid>The Traditional Colors of&nbsp;Japan</PageTitle> <PageTitle grid="wide" innerGrid>The Traditional Colors of&nbsp;Japan</PageTitle>
<article class="col-start-1 col-end-17 grid md:col-end-8 xl:content-center"> <article class="col-start-1 col-end-17 grid md:col-end-8 xl:content-center" {...animation}>
<Intro components={mapping} /> <Intro components={mapping} />
</article> </article>
<article class="col-start-1 col-end-17 flex grid-cols-2 md:col-start-9 md:justify-end"> <article
class="col-start-1 col-end-17 flex grid-cols-2 md:col-start-9 md:justify-end"
{...animationDelay}
>
<AmazonBook <AmazonBook
alt="The Traditional Colors of Japan" alt="The Traditional Colors of Japan"
asin="475624100X" asin="475624100X"
@@ -37,7 +41,14 @@ const description =
<ColorStack> <ColorStack>
{ {
colors.map(({ name, description, color }) => ( colors.map(({ name, description, color }) => (
<ColorSwatch client:visible color={color} title={name} description={description} /> <div {...animation}>
<ColorSwatch
client:visible
color={color}
title={name}
description={description}
/>
</div>
)) ))
} }
</ColorStack> </ColorStack>