Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d1816c1b6a | |||
| 89118578f5 | |||
| f279c58b28 | |||
| ec59cad1a5 | |||
| 3af4a77674 | |||
|
9b5317bec7
|
|||
|
84e6b146c8
|
|||
| b42a6974f6 | |||
| 29017b1d75 | |||
| 3e5aa65840 | |||
| b7787cb723 | |||
| 28ed0f2fa0 | |||
| c7493ad09c | |||
| 34e39aca23 | |||
| f71b28adf0 | |||
| 901a641b59 | |||
|
3e25b27c46
|
|||
| d408309775 | |||
| 05c6ec41d4 | |||
|
b26605cc3b
|
|||
| 7f91b3c8e8 | |||
|
4ab3bd076f
|
|||
| 58355e764e | |||
|
36cb8655c2
|
|||
| 8b58fe33a8 | |||
| 8a41c2e8a4 | |||
|
df8a60573a
|
|||
|
2bf8bee7a1
|
|||
| c7e525ab4b | |||
| 827c2afe47 | |||
|
81cb4b21af
|
|||
|
9be8a64851
|
|||
| e161b786cc | |||
|
4ef9e92d5d
|
|||
| ee13896366 | |||
|
c92b1f2801
|
|||
| 858e4d484b | |||
|
3b97243ca9
|
|||
| e71eb5100f | |||
|
518777c5d4
|
|||
| 9b2bceba88 | |||
|
57a2f1f11b
|
|||
| 217e0447a8 | |||
| 93708dac75 | |||
| d9d935818c | |||
| 2ad4697825 | |||
| 5d37b99c80 | |||
| ec9518a236 | |||
| d56ea50663 | |||
| 20ef5697f1 | |||
| e0b72bfcbd | |||
| 28724b4024 | |||
| 6520a0f50b | |||
| f8c7c3f997 | |||
| 6815d5a68b | |||
| e1339a53a2 | |||
| c3f521f80a | |||
| 457a8969f3 |
@@ -34,7 +34,7 @@ jobs:
|
|||||||
- name: Set up Bun
|
- name: Set up Bun
|
||||||
uses: oven-sh/setup-bun@v2.2.0
|
uses: oven-sh/setup-bun@v2.2.0
|
||||||
with:
|
with:
|
||||||
bun-version: 1.3.13
|
bun-version: 1.3.14
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: bun install --frozen-lockfile
|
run: bun install --frozen-lockfile
|
||||||
@@ -140,7 +140,7 @@ jobs:
|
|||||||
- name: Set up Bun
|
- name: Set up Bun
|
||||||
uses: oven-sh/setup-bun@v2.2.0
|
uses: oven-sh/setup-bun@v2.2.0
|
||||||
with:
|
with:
|
||||||
bun-version: 1.3.13
|
bun-version: 1.3.14
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: bun install --frozen-lockfile
|
run: bun install --frozen-lockfile
|
||||||
@@ -213,7 +213,7 @@ jobs:
|
|||||||
type=semver,pattern={{major}},value=${{ needs.semantic-release.outputs.new-release-version }}
|
type=semver,pattern={{major}},value=${{ needs.semantic-release.outputs.new-release-version }}
|
||||||
|
|
||||||
- name: Build and Push Image
|
- name: Build and Push Image
|
||||||
uses: docker/build-push-action@v7.1.0
|
uses: docker/build-push-action@v7.2.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
@@ -317,7 +317,7 @@ jobs:
|
|||||||
type=semver,pattern={{major}},value=${{ needs.semantic-release.outputs.new-release-version }}
|
type=semver,pattern={{major}},value=${{ needs.semantic-release.outputs.new-release-version }}
|
||||||
|
|
||||||
- name: Build and Push Image
|
- name: Build and Push Image
|
||||||
uses: docker/build-push-action@v7.1.0
|
uses: docker/build-push-action@v7.2.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ jobs:
|
|||||||
- name: Set up Bun
|
- name: Set up Bun
|
||||||
uses: oven-sh/setup-bun@v2.2.0
|
uses: oven-sh/setup-bun@v2.2.0
|
||||||
with:
|
with:
|
||||||
bun-version: 1.3.13
|
bun-version: 1.3.14
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: bun install --frozen-lockfile
|
run: bun install --frozen-lockfile
|
||||||
|
|||||||
@@ -1,3 +1,70 @@
|
|||||||
|
# [3.21.0](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.20.2...3.21.0) (2026-05-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **deps:** pin dependency @preline/collapse to 4.2.0 ([84e6b14](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/84e6b146c89f7b7a94f64ef5e14d431f850eb2e9))
|
||||||
|
* **deps:** update astro monorepo ([c92b1f2](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/c92b1f2801e85c5782db29e9a75eb78df1a70a41))
|
||||||
|
* **deps:** update dependency @iconify-json/simple-icons to v1.2.82 ([518777c](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/518777c5d4dcdde7690acea136ca23856db8ff1f))
|
||||||
|
* **deps:** update dependency @iconify-json/simple-icons to v1.2.83 ([2bf8bee](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/2bf8bee7a1d20e857cd95bcb1a61c5742cbe13b3))
|
||||||
|
* **deps:** update dependency astro to v6.3.3 ([4ef9e92](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/4ef9e92d5d84c9d69bf9e979435b85727fc622f1))
|
||||||
|
* **deps:** update dependency astro to v6.3.5 ([81cb4b2](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/81cb4b21aff6c9cc73dfba0a4f62ad75faa0d68e))
|
||||||
|
* **deps:** update dependency astro to v6.3.6 ([4ab3bd0](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/4ab3bd076fb06493a1a6b949dd745e6ef59e1fcd))
|
||||||
|
* **deps:** update dependency astro to v6.3.7 ([9b5317b](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/9b5317bec7dbd7f1092d18b8d70aed631942086b))
|
||||||
|
* **deps:** update dependency marked to v18.0.4 ([df8a605](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/df8a60573a70b73e60115cdf10c6c36518ae7bbe))
|
||||||
|
* **deps:** update dependency shiki to v4.1.0 ([b26605c](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/b26605cc3be80d50881d9041dfb20be7ca1f3c8a))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add compression features ([f279c58](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/f279c58b282fc1d24f6411548fbba1831e939a96))
|
||||||
|
* add custom font ([c7493ad](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/c7493ad09c5544090bd92c5fc219101a1f5f0b83))
|
||||||
|
* change collapse to preline ([b7787cb](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/b7787cb723b6a4dce0ef45e40d84be5869f1e6af))
|
||||||
|
* change font ([b42a697](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/b42a6974f62cb3aeb3e340d2daef2d621323a158))
|
||||||
|
* change large card hover ([29017b1](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/29017b1d75801f2142fee281b0ff7e164c4d134a))
|
||||||
|
* change timeline to preline ([3e5aa65](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/3e5aa658407290a65688e708509be9a724949646))
|
||||||
|
* remove apps page ([34e39ac](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/34e39aca23070f12cdd00a6774234e590f293156))
|
||||||
|
* replace slider with preline marquee ([901a641](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/901a641b59689e1a7a4278672b9a23386e8bdace))
|
||||||
|
* update background colors ([f71b28a](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/f71b28adf06779532b6303568a2b6e3b5020257a))
|
||||||
|
* update preline ([d408309](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/d408309775015ff30d1a0ddc7a5e095104e6c8bd))
|
||||||
|
|
||||||
|
## [3.20.2](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.20.1...3.20.2) (2026-05-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **content:** directus published update [skip ci] ([93708da](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/93708dac752e7fc001fc35d86145896fcfe474d1))
|
||||||
|
|
||||||
|
## [3.20.1](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.20.0...3.20.1) (2026-05-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **content:** directus published update [skip ci] ([2ad4697](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/2ad4697825060ecfabf515c45dc8d1acdc07c824))
|
||||||
|
|
||||||
|
# [3.20.0](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.19.4...3.20.0) (2026-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **deps:** update astro monorepo ([e1339a5](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/e1339a53a2b4c7392991db2179aaf63be1e0e38b))
|
||||||
|
* **deps:** update dependency @iconify-json/simple-icons to v1.2.81 ([e0b72bf](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/e0b72bfcbd89d195669666e01876b2ed50eafb5b))
|
||||||
|
* **deps:** update dependency astro to v6.2.2 ([28724b4](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/28724b40242d852f42298d0656a5da6e73a1884d))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* allow processing svg ([20ef569](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/20ef5697f15ff3d045dcd615eddc9887620ed9ea))
|
||||||
|
* merge ([d56ea50](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/d56ea50663f7fa3a4160ccbc34ac61ecc9838f03))
|
||||||
|
* reduce top transparency effect ([6815d5a](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/6815d5a68b4f44b1cfc920c32cf14b4e53b5c44f))
|
||||||
|
|
||||||
|
## [3.19.4](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.19.3...3.19.4) (2026-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **content:** directus published update [skip ci] ([457a896](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/457a8969f3460c5f6d1d652df9941ef56af7e215))
|
||||||
|
|
||||||
## [3.19.3](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.19.2...3.19.3) (2026-05-08)
|
## [3.19.3](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.19.2...3.19.3) (2026-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+13
-4
@@ -1,4 +1,4 @@
|
|||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig, fontProviders } from 'astro/config';
|
||||||
|
|
||||||
import node from '@astrojs/node';
|
import node from '@astrojs/node';
|
||||||
import sitemap from '@astrojs/sitemap';
|
import sitemap from '@astrojs/sitemap';
|
||||||
@@ -13,6 +13,7 @@ export default defineConfig({
|
|||||||
site: getSiteURL(),
|
site: getSiteURL(),
|
||||||
|
|
||||||
image: {
|
image: {
|
||||||
|
dangerouslyProcessSVG: true,
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{ protocol: 'https', hostname: '*.alexlebens.net' },
|
{ protocol: 'https', hostname: '*.alexlebens.net' },
|
||||||
{ protocol: 'https', hostname: '*.jsdelivr.net' },
|
{ protocol: 'https', hostname: '*.jsdelivr.net' },
|
||||||
@@ -23,6 +24,8 @@ export default defineConfig({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
prefetch: true,
|
||||||
|
|
||||||
integrations: [
|
integrations: [
|
||||||
sitemap(),
|
sitemap(),
|
||||||
icon({
|
icon({
|
||||||
@@ -41,12 +44,12 @@ export default defineConfig({
|
|||||||
}),
|
}),
|
||||||
(await import('@playform/compress')).default({
|
(await import('@playform/compress')).default({
|
||||||
CSS: true,
|
CSS: true,
|
||||||
JavaScript: false,
|
JavaScript: true,
|
||||||
HTML: {
|
HTML: {
|
||||||
'html-minifier-terser': {
|
'html-minifier-terser': {
|
||||||
collapseWhitespace: true,
|
collapseWhitespace: true,
|
||||||
minifyCSS: false,
|
minifyCSS: true,
|
||||||
minifyJS: false,
|
minifyJS: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Image: false,
|
Image: false,
|
||||||
@@ -54,6 +57,12 @@ export default defineConfig({
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
||||||
|
fonts: [{
|
||||||
|
provider: fontProviders.fontsource(),
|
||||||
|
name: "Fredoka",
|
||||||
|
cssVariable: "--font-base",
|
||||||
|
}],
|
||||||
|
|
||||||
markdown: {
|
markdown: {
|
||||||
syntaxHighlight: false,
|
syntaxHighlight: false,
|
||||||
},
|
},
|
||||||
|
|||||||
+16
-15
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "site-profile",
|
"name": "site-profile",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "3.19.3",
|
"version": "3.21.0",
|
||||||
"homepage": "https://www.alexlebens.dev",
|
"homepage": "https://www.alexlebens.dev",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://gitea.alexlebens.dev/alexlebens/site-profile/issues",
|
"url": "https://gitea.alexlebens.dev/alexlebens/site-profile/issues",
|
||||||
@@ -29,34 +29,35 @@
|
|||||||
"lint:fix": "eslint --fix \"src/**/*.{js,ts,jsx,tsx,astro}\""
|
"lint:fix": "eslint --fix \"src/**/*.{js,ts,jsx,tsx,astro}\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "0.9.8",
|
"@astrojs/check": "0.9.9",
|
||||||
"@astrojs/node": "10.0.6",
|
"@astrojs/node": "10.1.1",
|
||||||
"@astrojs/rss": "4.0.18",
|
"@astrojs/rss": "4.0.18",
|
||||||
"@astrojs/sitemap": "3.7.2",
|
"@astrojs/sitemap": "3.7.2",
|
||||||
"@directus/sdk": "21.2.2",
|
"@directus/sdk": "21.3.0",
|
||||||
"@iconify-json/mdi": "1.2.3",
|
"@iconify-json/mdi": "1.2.3",
|
||||||
"@iconify-json/pajamas": "1.2.15",
|
"@iconify-json/pajamas": "1.2.15",
|
||||||
"@iconify-json/simple-icons": "1.2.80",
|
"@iconify-json/simple-icons": "1.2.83",
|
||||||
"@playform/compress": "0.2.3",
|
"@playform/compress": "0.2.3",
|
||||||
|
"@preline/collapse": "4.2.0",
|
||||||
"@swup/astro": "1.8.0",
|
"@swup/astro": "1.8.0",
|
||||||
"@tailwindcss/postcss": "4.2.4",
|
"@tailwindcss/postcss": "4.3.0",
|
||||||
"@tailwindcss/vite": "4.2.4",
|
"@tailwindcss/vite": "4.3.0",
|
||||||
"@types/unist": "3.0.3",
|
"@types/unist": "3.0.3",
|
||||||
"astro": "6.1.9",
|
"astro": "6.3.7",
|
||||||
"astro-compress": "2.4.1",
|
"astro-compress": "2.4.1",
|
||||||
"astro-icon": "1.1.5",
|
"astro-icon": "1.1.5",
|
||||||
"dayjs": "1.11.20",
|
"dayjs": "1.11.20",
|
||||||
"markdown-it": "14.1.1",
|
"markdown-it": "14.1.1",
|
||||||
"marked": "18.0.2",
|
"marked": "18.0.4",
|
||||||
"marked-shiki": "1.2.1",
|
"marked-shiki": "1.2.1",
|
||||||
"mdast-util-to-string": "4.0.0",
|
"mdast-util-to-string": "4.0.0",
|
||||||
"photoswipe": "5.4.4",
|
"photoswipe": "5.4.4",
|
||||||
"preline": "4.1.3",
|
"preline": "4.2.0",
|
||||||
"reading-time": "1.5.0",
|
"reading-time": "1.5.0",
|
||||||
"sharp": "0.34.5",
|
"sharp": "0.34.5",
|
||||||
"sharp-ico": "0.1.5",
|
"sharp-ico": "0.1.5",
|
||||||
"shiki": "4.0.2",
|
"shiki": "4.1.0",
|
||||||
"tailwindcss": "4.2.4",
|
"tailwindcss": "4.3.0",
|
||||||
"ultrahtml": "1.6.0"
|
"ultrahtml": "1.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -65,11 +66,11 @@
|
|||||||
"@semantic-release/commit-analyzer": "13.0.1",
|
"@semantic-release/commit-analyzer": "13.0.1",
|
||||||
"@semantic-release/git": "10.0.1",
|
"@semantic-release/git": "10.0.1",
|
||||||
"@semantic-release/npm": "13.1.5",
|
"@semantic-release/npm": "13.1.5",
|
||||||
"@semantic-release/release-notes-generator": "14.1.0",
|
"@semantic-release/release-notes-generator": "14.1.1",
|
||||||
"@tailwindcss/forms": "0.5.11",
|
"@tailwindcss/forms": "0.5.11",
|
||||||
"@tailwindcss/typography": "0.5.19",
|
"@tailwindcss/typography": "0.5.19",
|
||||||
"@types/markdown-it": "14.1.2",
|
"@types/markdown-it": "14.1.2",
|
||||||
"eslint": "10.2.1",
|
"eslint": "10.4.0",
|
||||||
"eslint-config-prettier": "10.1.8",
|
"eslint-config-prettier": "10.1.8",
|
||||||
"eslint-plugin-astro": "1.7.0",
|
"eslint-plugin-astro": "1.7.0",
|
||||||
"eslint-plugin-format": "2.0.1",
|
"eslint-plugin-format": "2.0.1",
|
||||||
@@ -79,6 +80,6 @@
|
|||||||
"semantic-release": "25.0.3",
|
"semantic-release": "25.0.3",
|
||||||
"semantic-release-export-data": "1.2.0",
|
"semantic-release-export-data": "1.2.0",
|
||||||
"typescript": "6.0.3",
|
"typescript": "6.0.3",
|
||||||
"typescript-eslint": "8.59.1"
|
"typescript-eslint": "8.59.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const { post } = Astro.props;
|
|||||||
inferSize={true}
|
inferSize={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col justify-center bg-background-card md:bg-transparent group-hover:bg-neutral-100 md:group-hover:bg-transparent dark:group-hover:bg-neutral-800/90 md:dark:group-hover:bg-transparent rounded-b-2xl transition-all duration-300 p-6 gap-4">
|
<div class="card-base-hidden-md flex flex-col justify-center p-6 gap-4">
|
||||||
<h2 class="card-text-header">
|
<h2 class="card-text-header">
|
||||||
{post.title}
|
{post.title}
|
||||||
</h2>
|
</h2>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const { post } = Astro.props;
|
|||||||
href={`/blog/${post.slug}`}
|
href={`/blog/${post.slug}`}
|
||||||
data-astro-prefetch
|
data-astro-prefetch
|
||||||
>
|
>
|
||||||
<div class="flex flex-col bg-background-card md:bg-transparent group-hover:bg-neutral-100 md:group-hover:bg-transparent dark:group-hover:bg-neutral-800/90 md:dark:group-hover:bg-transparent rounded-b-2xl transition-all duration-300 p-6 gap-4">
|
<div class="card-base-hidden-md flex flex-col p-6 gap-4">
|
||||||
<h2 class="card-text-header">
|
<h2 class="card-text-header">
|
||||||
{post.title}
|
{post.title}
|
||||||
</h2>
|
</h2>
|
||||||
|
|||||||
@@ -18,15 +18,15 @@ const experiences = ((await directus.request(
|
|||||||
<h3 class="smooth-reveal card-text-header flex relative items-center w-full gap-3 pb-10">
|
<h3 class="smooth-reveal card-text-header flex relative items-center w-full gap-3 pb-10">
|
||||||
Experience
|
Experience
|
||||||
</h3>
|
</h3>
|
||||||
<ul class="flex flex-col w-full ml-8 pr-8">
|
<ul class="flex flex-col w-full gap-8">
|
||||||
{experiences.map((experience: Experience) => {
|
{experiences.map((experience: Experience, index: number) => {
|
||||||
const startYear = new Date(experience.startDate).getFullYear();
|
const startYear = new Date(experience.startDate).getFullYear();
|
||||||
const endYear = experience.endDate != null ? new Date(experience.endDate).getFullYear() : 'Present';
|
const endYear = experience.endDate != null ? new Date(experience.endDate).getFullYear() : 'Present';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li class="relative">
|
<li class="smooth-reveal card-base-hidden flex gap-x-4 -mx-4 md:-mx-8 px-4 md:px-8 py-4 md:py-6">
|
||||||
<div class="smooth-reveal group relative grid sm:grid-cols-18 sm:gap-8 md:gap-6 pb-16">
|
<div class="w-28 md:w-32 text-end pt-1 shrink-0">
|
||||||
<header class="relative sm:col-span-3 text-header font-semibold text-lg mt-1">
|
<header class="text-sm md:text-base font-semibold text-header">
|
||||||
<time datetime={experience.startDate} data-title={experience.startDate}>
|
<time datetime={experience.startDate} data-title={experience.startDate}>
|
||||||
{startYear}
|
{startYear}
|
||||||
</time>
|
</time>
|
||||||
@@ -35,115 +35,130 @@ const experiences = ((await directus.request(
|
|||||||
{endYear}
|
{endYear}
|
||||||
</time>
|
</time>
|
||||||
</header>
|
</header>
|
||||||
<div class="relative flex flex-col sm:col-span-12 pb-6">
|
</div>
|
||||||
<div class="absolute bg-accent -translate-x-[1.71rem] rounded-full h-2 w-2 mt-3"/>
|
<div class="relative last:after:hidden after:absolute after:top-6 after:-bottom-2 md:after:-bottom-4 after:inset-s-3.5 after:w-px after:translate-x-[-0.5px] after:bg-divider">
|
||||||
<h3>
|
<div class="relative z-10 size-7 flex justify-center items-center">
|
||||||
<div
|
<div class="size-2 rounded-full bg-accent"></div>
|
||||||
class="inline-flex items-center text-2xl leading-tight font-semibold"
|
</div>
|
||||||
aria-label="{position} - {company}"
|
</div>
|
||||||
>
|
<div class="grow pt-0.5">
|
||||||
<span class="text-header">
|
<h3>
|
||||||
{experience.position} <span>@</span>
|
<div
|
||||||
{experience.url ? (
|
class="inline-flex items-center text-2xl leading-tight font-semibold"
|
||||||
<a
|
aria-label="{position} - {company}"
|
||||||
class="hover:text-main"
|
>
|
||||||
href={experience.url}
|
<span class="text-header">
|
||||||
title={`Ver ${experience.name}`}
|
{experience.position} <span>@</span>
|
||||||
target="_blank"
|
{experience.url ? (
|
||||||
>
|
<a
|
||||||
{experience.name}
|
class="hover:text-main"
|
||||||
</a>
|
href={experience.url}
|
||||||
) : (
|
title={`Ver ${experience.name}`}
|
||||||
<span>{experience.name}</span>
|
target="_blank"
|
||||||
)}
|
>
|
||||||
</span>
|
{experience.name}
|
||||||
</div>
|
</a>
|
||||||
</h3>
|
) : (
|
||||||
{(experience.location || experience.location_type) && (
|
<span>{experience.name}</span>
|
||||||
<div class="text-secondary text-sm">
|
)}
|
||||||
{experience.location} {experience.location && experience.location_type && '-'} {experience.location_type}
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</h3>
|
||||||
<div class="text-md mt-4 flex flex-col gap-4" x-data="{ expanded: false }">
|
{(experience.location || experience.location_type) && (
|
||||||
{experience.summary && (
|
<div class="text-secondary text-sm">
|
||||||
|
{experience.location} {experience.location && experience.location_type && '-'} {experience.location_type}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div class="text-md mt-4 flex flex-col">
|
||||||
|
{experience.summary && (
|
||||||
|
<div class="flex flex-col gap-1 mb-4">
|
||||||
|
<h4 class="text-header font-semibold">
|
||||||
|
Summary:
|
||||||
|
</h4>
|
||||||
|
<ul class="flex flex-col text-primary list-disc gap-2 [&>li]:ml-4">
|
||||||
|
<li class="marker:text-main">
|
||||||
|
{experience.summary}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{(experience.responsibilities || experience.achievements) && (
|
||||||
|
<>
|
||||||
|
<div id={`hs-show-hide-collapse-heading-${index}`} class="hs-collapse hidden w-full overflow-hidden transition-[height] duration-500">
|
||||||
|
<div class="relative flex flex-col gap-4 pb-4">
|
||||||
|
{experience.responsibilities && (
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<h4 class="text-header font-semibold">
|
<h4 class="text-header font-semibold">
|
||||||
Summary:
|
Responsibilities:
|
||||||
</h4>
|
</h4>
|
||||||
<ul class="flex flex-col text-primary list-disc gap-2 [&>li]:ml-4">
|
<ul class="flex flex-col text-primary list-disc gap-2 [&>li]:ml-4">
|
||||||
|
{experience.responsibilities.map(responsibility => (
|
||||||
<li class="marker:text-main">
|
<li class="marker:text-main">
|
||||||
{experience.summary}
|
{responsibility}
|
||||||
</li>
|
</li>
|
||||||
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{(experience.responsibilities || experience.achievements) && (
|
{experience.achievements && (
|
||||||
<div class="relative flex flex-col gap-4" :class="expanded ? '' : 'mask-[linear-gradient(to_bottom,black_50%,transparent)]'" x-show="expanded" x-collapse.min.50px>
|
<div class="flex flex-col gap-1">
|
||||||
{experience.responsibilities && (
|
<h4 class="text-header font-semibold">
|
||||||
<div class="flex flex-col gap-1">
|
Achievements:
|
||||||
<h4 class="text-header font-semibold">
|
</h4>
|
||||||
Responsibilities:
|
<ul class="flex flex-col text-primary list-disc gap-2 [&>li]:ml-4">
|
||||||
</h4>
|
{experience.achievements.map(achievement => (
|
||||||
<ul class="flex flex-col text-primary list-disc gap-2 [&>li]:ml-4">
|
<li class="marker:text-main">
|
||||||
{experience.responsibilities.map(responsibility => (
|
{achievement}
|
||||||
<li class="marker:text-main">
|
</li>
|
||||||
{responsibility}
|
))}
|
||||||
</li>
|
</ul>
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{experience.achievements && (
|
|
||||||
<div class="flex flex-col gap-1">
|
|
||||||
<h4 class="text-header font-semibold">
|
|
||||||
Achievements:
|
|
||||||
</h4>
|
|
||||||
<ul class="flex flex-col text-primary list-disc gap-2 [&>li]:ml-4">
|
|
||||||
{experience.achievements.map(achievement => (
|
|
||||||
<li class="marker:text-main">
|
|
||||||
{achievement}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<button @click="expanded = ! expanded" class="group/more flex items-center justify-center text-primary hover:text-primary-hover text-xs underline transition-all gap-1.5 w-fit cursor-pointer">
|
</div>
|
||||||
<span x-text="expanded ? 'Show less' : 'Show more'">
|
</div>
|
||||||
Show more
|
<p class="mb-4">
|
||||||
</span>
|
<button
|
||||||
|
type="button"
|
||||||
|
class="hs-collapse-toggle inline-flex items-center gap-x-1 text-sm rounded-lg text-primary hover:text-primary-hover disabled:opacity-50 disabled:pointer-events-none"
|
||||||
|
id={`hs-show-hide-collapse-${index}`}
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls={`hs-show-hide-collapse-heading-${index}`}
|
||||||
|
data-hs-collapse={`#hs-show-hide-collapse-heading-${index}`}
|
||||||
|
>
|
||||||
|
<span class="hs-collapse-open:hidden">Read more</span>
|
||||||
|
<span class="hs-collapse-open:block hidden">Read less</span>
|
||||||
<svg
|
<svg
|
||||||
class="group-hover/more:translate-y-0.5 ease-out duration-300 h-4 w-4"
|
class="hs-collapse-open:rotate-180 shrink-0 size-4"
|
||||||
:class="{ 'rotate-180': expanded }"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
>
|
>
|
||||||
<polyline points="6 9 12 15 18 9" />
|
<path d="m6 9 6 6 6-6"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
</p>
|
||||||
<ul
|
</>
|
||||||
class="flex print:hidden flex-wrap gap-2 mt-2"
|
)}
|
||||||
aria-label="Technologies used"
|
<ul
|
||||||
>
|
class="flex print:hidden flex-wrap gap-2"
|
||||||
{experience.skills && experience.skills.map(skill => {
|
aria-label="Technologies used"
|
||||||
const iconName = skill.toLowerCase();
|
>
|
||||||
const skillName = skill.split(':')[1].replace(/^language-/, '').replace(/-/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase());
|
{experience.skills && experience.skills.map(skill => {
|
||||||
return (
|
const iconName = skill.toLowerCase();
|
||||||
<li class="flex items-center bg-steel/20 dark:bg-bermuda/20 text-neutral-800 dark:text-neutral-200 text-xs rounded-md border border-solid border-steel/20 dark:border-bermuda/20 gap-1 px-2 py-0.5">
|
const skillName = skill.split(':')[1].replace(/^language-/, '').replace(/-/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase());
|
||||||
<Icon name={`${iconName}`} class="h-4 w-4" /> <span>{skillName}</span>
|
return (
|
||||||
</li>
|
<li class="flex items-center bg-steel/20 dark:bg-bermuda/20 text-neutral-800 dark:text-neutral-200 text-xs rounded-md border border-solid border-steel/20 dark:border-bermuda/20 gap-1 px-2 py-0.5">
|
||||||
)
|
<Icon name={`${iconName}`} class="h-4 w-4" /> <span>{skillName}</span>
|
||||||
})}
|
</li>
|
||||||
</ul>
|
)
|
||||||
)}
|
})}
|
||||||
</div>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -152,8 +167,6 @@ const experiences = ((await directus.request(
|
|||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Alpine Plugins -->
|
<script>
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/collapse@3.x.x/dist/cdn.min.js"></script>
|
import "@preline/collapse/index.js";
|
||||||
|
</script>
|
||||||
<!-- Alpine Core -->
|
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
|
||||||
|
|||||||
@@ -18,150 +18,117 @@ const skills = ((await directus.request(
|
|||||||
<h3 class="smooth-reveal card-text-header flex relative items-center w-full gap-3 pb-5">
|
<h3 class="smooth-reveal card-text-header flex relative items-center w-full gap-3 pb-5">
|
||||||
Skills
|
Skills
|
||||||
</h3>
|
</h3>
|
||||||
<div>
|
<div class="smooth-reveal relative flex flex-col gap-2 mask-[linear-gradient(to_right,transparent,black_10%,black_90%,transparent)] before:pointer-events-none before:absolute before:inset-y-0 before:inset-s-0 before:z-2 before:w-20 after:pointer-events-none after:absolute after:inset-y-0 after:inset-e-0 after:z-2 after:w-20">
|
||||||
<div class="tech-stack-slider relative overflow-hidden py-4 sm:py-8 mask-[linear-gradient(to_right,transparent,black_10%,black_90%,transparent)]">
|
<div class="flex">
|
||||||
<!-- Main slider container -->
|
<div class="marquee-track-x animate-[marquee-x_120s_linear_infinite] hover:[animation-play-state:paused] flex w-max gap-4 py-10">
|
||||||
<div class="slider-track animate-slide flex">
|
<div class="flex gap-4">
|
||||||
{[...skills, ...skills, ...skills].map((skill: Skill) => {
|
{[...skills, ...skills, ...skills].map((skill: Skill) => {
|
||||||
return (
|
return (
|
||||||
<div class="skill-card card-base transform hover:-translate-y-2 hover:scale-105 transition-all duration-300 mx-2 min-w-55 sm:mx-4 sm:min-w-70">
|
<figure class="skill-card card-base transform hover:-translate-y-2 hover:scale-105 transition-all duration-300 mx-2 min-w-55 sm:mx-4 sm:min-w-70">
|
||||||
<div class="p-4 sm:p-6">
|
<div class="p-4 sm:p-6">
|
||||||
<div class="flex items-center justify-between mb-4 sm:mb-6">
|
<div class="flex items-center justify-between mb-4 sm:mb-6">
|
||||||
<div class="flex items-center gap-2 sm:gap-4">
|
<div class="flex items-center gap-2 sm:gap-4">
|
||||||
<div class="flex items-center justify-center rounded-lg text-primary">
|
<div class="flex items-center justify-center rounded-lg text-primary">
|
||||||
<Icon name={skill.icon} class="h-8 w-8 sm:h-12 sm:w-12" />
|
<Icon name={skill.icon} class="h-8 w-8 sm:h-12 sm:w-12" />
|
||||||
|
</div>
|
||||||
|
<h3 class="text-neutral-900 dark:text-neutral-100 text-base font-semibold sm:text-xl">
|
||||||
|
{skill.title}
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-neutral-900 dark:text-neutral-100 text-base font-semibold sm:text-xl">
|
<span class=" bg-neutral-200 dark:bg-neutral-800 text-neutral-700 dark:text-neutral-300 font-mono text-xs sm:text-sm rounded-full px-2 sm:px-2.5 py-0.5 sm:py-1">
|
||||||
{skill.title}
|
{skill.level}%
|
||||||
</h3>
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="relative bg-stone-500/20 dark:bg-stone-500/20 rounded-full h-1.5 sm:h-2 w-full">
|
||||||
|
<div
|
||||||
|
class="progress-bar-animate bg-linear-to-r from-steel via-bermuda to-steel absolute top-0 left-0 h-full rounded-full transition-all duration-1000"
|
||||||
|
style={`width: ${skill.level}%`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between text-secondary font-mono text-[10px] mt-1 sm:mt-2 sm:text-xs">
|
||||||
|
<span>Beginner</span>
|
||||||
|
<span>Advanced</span>
|
||||||
</div>
|
</div>
|
||||||
<span class=" bg-neutral-200 dark:bg-neutral-800 text-neutral-700 dark:text-neutral-300 font-mono text-xs sm:text-sm rounded-full px-2 sm:px-2.5 py-0.5 sm:py-1">
|
|
||||||
{skill.level}%
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="relative bg-stone-500/20 dark:bg-stone-500/20 rounded-full h-1.5 sm:h-2 w-full overflow-hidden">
|
</figure>
|
||||||
<div
|
);
|
||||||
class="progress-bar-animate bg-linear-to-r from-steel via-bermuda to-steel absolute top-0 left-0 h-full rounded-full transition-all duration-1000"
|
})}
|
||||||
style={`width: ${skill.level}%`}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-between text-secondary font-mono text-[10px] mt-1 sm:mt-2 sm:text-xs">
|
|
||||||
<span>Beginner</span>
|
|
||||||
<span>Advanced</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('astro:page-load', () => {
|
function initSkillCards() {
|
||||||
function setupInfiniteScroll() {
|
const cards = document.querySelectorAll<HTMLElement>('.skill-card');
|
||||||
const cards = document.querySelectorAll('.skill-card');
|
if (!cards.length) return;
|
||||||
if (!cards.length) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setupInfiniteScroll();
|
cards.forEach((card) => {
|
||||||
|
// Desktop/Mouse events
|
||||||
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
card.addEventListener('mouseenter', () => {
|
||||||
const cards = document.querySelectorAll('.skill-card');
|
card.style.setProperty('transition', 'transform 0.1s ease, box-shadow 0.1s ease', 'important');
|
||||||
|
|
||||||
if (!isTouchDevice) {
|
|
||||||
cards.forEach((card) => {
|
|
||||||
card.addEventListener('mousemove', (e) => {
|
|
||||||
const rect = card.getBoundingClientRect();
|
|
||||||
const x = e.clientX - rect.left;
|
|
||||||
const y = e.clientY - rect.top;
|
|
||||||
|
|
||||||
const centerX = rect.width / 2;
|
|
||||||
const centerY = rect.height / 2;
|
|
||||||
|
|
||||||
const angleX = (y - centerY) / 15;
|
|
||||||
const angleY = (centerX - x) / 15;
|
|
||||||
|
|
||||||
card.style.transform = `perspective(1000px) rotateX(${angleX}deg) rotateY(${angleY}deg) scale(1.08) translateZ(20px)`;
|
|
||||||
|
|
||||||
// Dynamic shadow based on tilt
|
|
||||||
const shadowX = (x - centerX) / 25;
|
|
||||||
const shadowY = (y - centerY) / 25;
|
|
||||||
card.style.boxShadow = `
|
|
||||||
${shadowX}px ${shadowY}px 20px rgba(0, 0, 0, 0.1),
|
|
||||||
0 10px 20px rgba(0, 0, 0, 0.05)
|
|
||||||
`;
|
|
||||||
});
|
|
||||||
|
|
||||||
card.addEventListener('mouseleave', () => {
|
|
||||||
card.style.transform = '';
|
|
||||||
card.style.boxShadow = '';
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
// Simpler effects for touch devices
|
|
||||||
cards.forEach((card) => {
|
|
||||||
card.addEventListener('touchstart', () => {
|
|
||||||
card.classList.add('is-touched');
|
|
||||||
});
|
|
||||||
|
|
||||||
card.addEventListener('touchend', () => {
|
card.addEventListener('mousemove', (e: MouseEvent) => {
|
||||||
setTimeout(() => {
|
const rect = card.getBoundingClientRect();
|
||||||
card.classList.remove('is-touched');
|
const x = e.clientX - rect.left;
|
||||||
}, 300);
|
const y = e.clientY - rect.top;
|
||||||
});
|
|
||||||
|
const centerX = rect.width / 2;
|
||||||
|
const centerY = rect.height / 2;
|
||||||
|
|
||||||
|
const angleX = (y - centerY) / 15;
|
||||||
|
const angleY = (centerX - x) / 15;
|
||||||
|
|
||||||
|
card.style.setProperty('transform', `perspective(1000px) rotateX(${angleX}deg) rotateY(${angleY}deg) scale(1.08) translateZ(20px)`, 'important');
|
||||||
|
|
||||||
|
const shadowX = (x - centerX) / 25;
|
||||||
|
const shadowY = (y - centerY) / 25;
|
||||||
|
card.style.setProperty('box-shadow', `
|
||||||
|
${shadowX}px ${shadowY}px 20px rgba(0, 0, 0, 0.1),
|
||||||
|
0 10px 20px rgba(0, 0, 0, 0.05)
|
||||||
|
`, 'important');
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
card.addEventListener('mouseleave', () => {
|
||||||
|
card.style.removeProperty('transform');
|
||||||
|
card.style.removeProperty('box-shadow');
|
||||||
|
card.style.removeProperty('transition');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mobile/Touch events
|
||||||
|
card.addEventListener('touchstart', () => {
|
||||||
|
card.classList.add('is-touched');
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
|
card.addEventListener('touchend', () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
card.classList.remove('is-touched');
|
||||||
|
}, 300);
|
||||||
|
}, { passive: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run exactly once on initial load, and again if navigating via Astro View Transitions
|
||||||
|
initSkillCards();
|
||||||
|
document.addEventListener('astro:after-swap', initSkillCards);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Specific css to enable sliding effect */
|
/* Skill card effects */
|
||||||
.slider-track {
|
|
||||||
width: fit-content;
|
|
||||||
animation: scroll 40s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes scroll {
|
|
||||||
0% {
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateX(calc(-220px * 6 - 16px * 6));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 640px) {
|
|
||||||
.slider-track {
|
|
||||||
animation: scroll 80s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes scroll {
|
|
||||||
0% {
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateX(calc(-280px * 6 - 32px * 6));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tech-stack-slider:hover .slider-track {
|
|
||||||
animation-play-state: paused;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skill-card {
|
.skill-card {
|
||||||
transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skill-card:hover {
|
.skill-card:hover {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reduce animation complexity on mobile */
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.skill-card {
|
.skill-card {
|
||||||
transition:
|
transition:
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ export const NavigationLinks: NavigationLink[] = [
|
|||||||
{ name: 'Home', url: '/' },
|
{ name: 'Home', url: '/' },
|
||||||
{ name: 'Blog', url: '/blog/' },
|
{ name: 'Blog', url: '/blog/' },
|
||||||
{ name: 'Categories', url: '/categories/' },
|
{ name: 'Categories', url: '/categories/' },
|
||||||
{ name: 'Apps', url: '/apps/' },
|
|
||||||
{ name: 'About Me', url: '/about/' },
|
{ name: 'About Me', url: '/about/' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import { Font } from "astro:assets";
|
||||||
|
|
||||||
import { readSingleton } from '@directus/sdk';
|
import { readSingleton } from '@directus/sdk';
|
||||||
|
|
||||||
import BaseHead from '@components/BaseHead.astro';
|
import BaseHead from '@components/BaseHead.astro';
|
||||||
@@ -38,6 +40,8 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
|||||||
structuredData={structuredData}
|
structuredData={structuredData}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Font cssVariable="--font-base" />
|
||||||
|
|
||||||
<!-- Set Theme -->
|
<!-- Set Theme -->
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
const theme = (() => {
|
const theme = (() => {
|
||||||
@@ -62,14 +66,14 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
|||||||
<script
|
<script
|
||||||
src="/vendor/preline/collapse2.1.0.min.js"
|
src="/vendor/preline/collapse2.1.0.min.js"
|
||||||
is:inline
|
is:inline
|
||||||
/>
|
></script>
|
||||||
|
|
||||||
<!-- Rybbit Tracking Snippet -->
|
<!-- Rybbit Tracking Snippet -->
|
||||||
<script
|
<script
|
||||||
src="https://rybbit.alexlebens.dev/api/script.js"
|
src="https://rybbit.alexlebens.dev/api/script.js"
|
||||||
data-site-id={global.rybbit_site_id}
|
data-site-id={global.rybbit_site_id}
|
||||||
defer
|
defer
|
||||||
/>
|
></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="bg-background selection:bg-yellow-400 m-0 p-0 overflow-hidden">
|
<body class="bg-background selection:bg-yellow-400 m-0 p-0 overflow-hidden">
|
||||||
@@ -150,16 +154,16 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
|||||||
-webkit-mask-image: linear-gradient(
|
-webkit-mask-image: linear-gradient(
|
||||||
to bottom,
|
to bottom,
|
||||||
transparent 0px,
|
transparent 0px,
|
||||||
transparent 90px,
|
transparent 84px,
|
||||||
black 140px,
|
black 114px,
|
||||||
black 100%
|
black 100%
|
||||||
);
|
);
|
||||||
|
|
||||||
mask-image: linear-gradient(
|
mask-image: linear-gradient(
|
||||||
to bottom,
|
to bottom,
|
||||||
transparent 0px,
|
transparent 0px,
|
||||||
transparent 90px,
|
transparent 84px,
|
||||||
black 140px,
|
black 114px,
|
||||||
black 100%
|
black 100%
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -171,7 +175,7 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
|||||||
.bg {
|
.bg {
|
||||||
animation: slide 25s ease-in-out infinite alternate;
|
animation: slide 25s ease-in-out infinite alternate;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
background-image: linear-gradient(-55deg, var(--bg-primary) 33.3%, var(--bg-secondary) 33.3%, var(--bg-secondary) 66.6%, var(--bg-tertiary) 66.6%);
|
background-image: linear-gradient(-55deg, var(--color-background-1) 33.3%, var(--color-background-2) 33.3%, var(--color-background-2) 66.6%, var(--color-background-3) 66.6%);
|
||||||
filter: blur(40px);
|
filter: blur(40px);
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@@ -180,15 +184,6 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
|||||||
opacity: .5;
|
opacity: .5;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
--bg-primary: #e5e5e5;
|
|
||||||
--bg-secondary: #dce3eb;
|
|
||||||
--bg-tertiary: #f4f6f8;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .bg {
|
|
||||||
--bg-primary: #3b3836;
|
|
||||||
--bg-secondary: #332f2e;
|
|
||||||
--bg-tertiary: #44403c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg2 {
|
.bg2 {
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
---
|
|
||||||
import { readSingleton } from '@directus/sdk';
|
|
||||||
|
|
||||||
import HeroSection from '@components/sections/HeroSection.astro';
|
|
||||||
import ApplicationSection from '@components/sections/ApplicationSection.astro';
|
|
||||||
import BaseLayout from '@layouts/BaseLayout.astro';
|
|
||||||
import directus from '@lib/directus';
|
|
||||||
|
|
||||||
const global = await directus.request(readSingleton('site_global'));
|
|
||||||
---
|
|
||||||
|
|
||||||
<BaseLayout
|
|
||||||
title="Applications"
|
|
||||||
description={global.about_applications}
|
|
||||||
structuredData={{
|
|
||||||
'@context': 'https://schema.org',
|
|
||||||
'@type': 'WebPage',
|
|
||||||
inLanguage: 'en-US',
|
|
||||||
'@id': Astro.url.href,
|
|
||||||
url: Astro.url.href,
|
|
||||||
name: `Applications | ${global.name}`,
|
|
||||||
description: global.about_applications,
|
|
||||||
isPartOf: {
|
|
||||||
'@type': 'WebSite',
|
|
||||||
url: global.site_url,
|
|
||||||
name: global.name,
|
|
||||||
description: global.about,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
|
|
||||||
<HeroSection
|
|
||||||
title="Applications"
|
|
||||||
subTitle={global.about_applications}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ApplicationSection className="smooth-reveal-2" />
|
|
||||||
|
|
||||||
</BaseLayout>
|
|
||||||
+45
-4
@@ -1,4 +1,5 @@
|
|||||||
@import 'tailwindcss';
|
@import 'tailwindcss';
|
||||||
|
|
||||||
@import './utilities-buttons.css';
|
@import './utilities-buttons.css';
|
||||||
@import './utilities-cards.css';
|
@import './utilities-cards.css';
|
||||||
@import './utilities-misc.css';
|
@import './utilities-misc.css';
|
||||||
@@ -6,6 +7,11 @@
|
|||||||
@plugin '@tailwindcss/typography';
|
@plugin '@tailwindcss/typography';
|
||||||
@plugin '@tailwindcss/forms';
|
@plugin '@tailwindcss/forms';
|
||||||
|
|
||||||
|
/* Preline */
|
||||||
|
@source "../../node_modules/@preline/collapse/*.js";
|
||||||
|
@import "../../node_modules/@preline/collapse/variants.css";
|
||||||
|
@import "../../node_modules/@preline/collapse/theme.css";
|
||||||
|
|
||||||
/* Dark mode support for Tailwind CSS v4 */
|
/* Dark mode support for Tailwind CSS v4 */
|
||||||
/* https://tailwindcss.com/docs/dark-mode */
|
/* https://tailwindcss.com/docs/dark-mode */
|
||||||
@custom-variant dark (&:where(.dark, .dark *));
|
@custom-variant dark (&:where(.dark, .dark *));
|
||||||
@@ -39,11 +45,16 @@
|
|||||||
--color-secondary: light-dark(var(--color-neutral-500), var(--color-neutral-400));
|
--color-secondary: light-dark(var(--color-neutral-500), var(--color-neutral-400));
|
||||||
--color-secondary-hover: light-dark(var(--color-neutral-800), var(--color-neutral-200));
|
--color-secondary-hover: light-dark(var(--color-neutral-800), var(--color-neutral-200));
|
||||||
|
|
||||||
/* Object colors */
|
/* Background colors */
|
||||||
--color-background: light-dark(var(--color-neutral-200), var(--color-stone-700));
|
--color-background: light-dark(var(--color-neutral-200), var(--color-mist-800));
|
||||||
--color-background-accent: light-dark(color-mix(in srgb, var(--color-slate-300) 40%, transparent), color-mix(in srgb, var(--color-stone-800) 20%, transparent));
|
--color-background-accent: light-dark(color-mix(in srgb, var(--color-slate-300) 40%, transparent), color-mix(in srgb, var(--color-mist-900) 20%, transparent));
|
||||||
--color-background-card: light-dark(color-mix(in srgb, var(--color-neutral-100) 80%, transparent), color-mix(in srgb, var(--color-neutral-800) 60%, transparent));
|
--color-background-card: light-dark(color-mix(in srgb, var(--color-mist-100) 80%, transparent), color-mix(in srgb, var(--color-mist-900) 40%, transparent));
|
||||||
|
|
||||||
|
--color-background-1: light-dark(color-mix(in srgb, var(--color-mist-200) 75%, var(--color-slate-100)), color-mix(in srgb, var(--color-mist-700) 95%, var(--color-mist-950)));
|
||||||
|
--color-background-2: light-dark(color-mix(in srgb, var(--color-mist-400) 10%, var(--color-slate-100)), color-mix(in srgb, var(--color-mist-700) 80%, var(--color-mist-950)));
|
||||||
|
--color-background-3: light-dark(color-mix(in srgb, var(--color-mist-200) 85%, var(--color-slate-100)), color-mix(in srgb, var(--color-mist-700) 85%, var(--color-mist-950)));
|
||||||
|
|
||||||
|
/* Object colors */
|
||||||
--color-divider: light-dark(color-mix(in srgb, var(--color-slate-400) 40%, transparent), color-mix(in srgb, var(--color-neutral-500) 50%, transparent));
|
--color-divider: light-dark(color-mix(in srgb, var(--color-slate-400) 40%, transparent), color-mix(in srgb, var(--color-neutral-500) 50%, transparent));
|
||||||
|
|
||||||
/* Typography */
|
/* Typography */
|
||||||
@@ -56,6 +67,9 @@
|
|||||||
|
|
||||||
--radius-markdown-img: 0.5rem;
|
--radius-markdown-img: 0.5rem;
|
||||||
|
|
||||||
|
/* Font */
|
||||||
|
--font-sans: var(--font-base);
|
||||||
|
|
||||||
/* Reveal Animations */
|
/* Reveal Animations */
|
||||||
--animate-reveal: reveal 0.8s ease forwards;
|
--animate-reveal: reveal 0.8s ease forwards;
|
||||||
--animate-reveal-fade: reveal-fade 1.8s ease forwards;
|
--animate-reveal-fade: reveal-fade 1.8s ease forwards;
|
||||||
@@ -114,6 +128,33 @@
|
|||||||
border-color var(--theme-transition);
|
border-color var(--theme-transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Preline marquee */
|
||||||
|
@keyframes marquee-x {
|
||||||
|
from {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(calc(-50% - 0.5rem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes marquee-y {
|
||||||
|
from {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateY(calc(-50% - 0.5rem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.marquee-track-x,
|
||||||
|
.marquee-track-y {
|
||||||
|
animation-duration: 1ms;
|
||||||
|
animation-iteration-count: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Typography */
|
/* Typography */
|
||||||
.prose blockquote {
|
.prose blockquote {
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
@utility button-base-hidden {
|
@utility button-base-hidden {
|
||||||
@apply transition-all duration-300
|
@apply transition-all duration-300
|
||||||
border border-transparent
|
border border-transparent
|
||||||
hover:bg-neutral-200 dark:hover:bg-neutral-700
|
hover:bg-mist-200 dark:hover:bg-mist-700
|
||||||
p-2
|
p-2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
@utility button-bg-neutral {
|
@utility button-bg-neutral {
|
||||||
@apply transition-all duration-300
|
@apply transition-all duration-300
|
||||||
border border-neutral-100 dark:border-stone-500/20
|
border border-neutral-100 dark:border-mist-700/20
|
||||||
bg-background-card hover:bg-neutral-100 dark:hover:bg-neutral-800/90
|
bg-background-card hover:bg-neutral-100 dark:hover:bg-neutral-800/90
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@utility card-base {
|
@utility card-base {
|
||||||
@apply transition-all duration-300
|
@apply transition-all duration-300
|
||||||
rounded-xl
|
rounded-xl
|
||||||
border border-neutral-100 dark:border-stone-500/20
|
border border-mist-100/20 dark:border-mist-700/20
|
||||||
bg-background-card hover:bg-neutral-100 dark:hover:bg-neutral-800/90
|
bg-background-card hover:bg-neutral-100 dark:hover:bg-mist-900/70
|
||||||
shadow-xs hover:shadow-md dark:shadow-md dark:hover:shadow-lg
|
shadow-xs hover:shadow-md dark:shadow-md dark:hover:shadow-lg
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10,7 +10,14 @@
|
|||||||
@apply transition-all duration-300
|
@apply transition-all duration-300
|
||||||
rounded-2xl
|
rounded-2xl
|
||||||
border border-transparent
|
border border-transparent
|
||||||
hover:bg-neutral-400/20 dark:hover:bg-neutral-800/40
|
hover:bg-mist-400/20 dark:hover:bg-mist-800/40
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility card-base-hidden-md {
|
||||||
|
@apply transition-all duration-300
|
||||||
|
rounded-b-2xl
|
||||||
|
bg-background-card md:bg-transparent
|
||||||
|
group-hover:bg-neutral-100 md:group-hover:bg-transparent dark:group-hover:bg-mist-900/70 md:dark:group-hover:bg-transparent
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility card-hover-icon-color {
|
@utility card-hover-icon-color {
|
||||||
@@ -21,7 +28,7 @@
|
|||||||
|
|
||||||
@utility card-hover-icon-scale {
|
@utility card-hover-icon-scale {
|
||||||
@apply transition-transform duration-300 will-change-transform
|
@apply transition-transform duration-300 will-change-transform
|
||||||
drop-shadow-md dark:drop-shadow-xl dark:drop-shadow-neutral-500/60
|
drop-shadow-md dark:drop-shadow-xl dark:drop-shadow-mist-500/60
|
||||||
group-hover:scale-3d group-hover:scale-105
|
group-hover:scale-3d group-hover:scale-105
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Nav */
|
/* Nav */
|
||||||
@utility nav-base {
|
@utility nav-base {
|
||||||
@apply border border-neutral-100 dark:border-stone-500/20
|
@apply border border-mist-100/20 dark:border-mist-700/20
|
||||||
bg-neutral-100 dark:bg-neutral-800
|
bg-mist-100/80 dark:bg-mist-900/40
|
||||||
shadow-xs dark:shadow-md
|
shadow-xs dark:shadow-md
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user