Compare commits
72 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 | |||
| a602f94270 | |||
| 8996928b1e | |||
| 0529e57ab9 | |||
| a7be4ae7a7 | |||
| f53f5bcfe4 | |||
| 922651232b | |||
| 3503441db3 | |||
| 1c2e2e840e | |||
| 20740e79c3 | |||
| 60948ffd1e | |||
| 9dffaee53b | |||
| dd74d06c57 | |||
| ce6ce345c3 | |||
| a1290e51ef |
@@ -34,7 +34,7 @@ jobs:
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@v2.2.0
|
||||
with:
|
||||
bun-version: 1.3.13
|
||||
bun-version: 1.3.14
|
||||
|
||||
- name: Install Dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
@@ -140,7 +140,7 @@ jobs:
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@v2.2.0
|
||||
with:
|
||||
bun-version: 1.3.13
|
||||
bun-version: 1.3.14
|
||||
|
||||
- name: Install Dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
@@ -213,7 +213,7 @@ jobs:
|
||||
type=semver,pattern={{major}},value=${{ needs.semantic-release.outputs.new-release-version }}
|
||||
|
||||
- name: Build and Push Image
|
||||
uses: docker/build-push-action@v7.1.0
|
||||
uses: docker/build-push-action@v7.2.0
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
@@ -317,7 +317,7 @@ jobs:
|
||||
type=semver,pattern={{major}},value=${{ needs.semantic-release.outputs.new-release-version }}
|
||||
|
||||
- name: Build and Push Image
|
||||
uses: docker/build-push-action@v7.1.0
|
||||
uses: docker/build-push-action@v7.2.0
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@v2.2.0
|
||||
with:
|
||||
bun-version: 1.3.13
|
||||
bun-version: 1.3.14
|
||||
|
||||
- name: Install Dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
+107
@@ -1,3 +1,110 @@
|
||||
# [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)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **content:** directus published update [skip ci] ([8996928](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/8996928b1edddafa4585b604e52908dea05042ad))
|
||||
|
||||
## [3.19.2](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.19.1...3.19.2) (2026-04-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **content:** directus published update [skip ci] ([a7be4ae](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/a7be4ae7a78311f51f230fb6a7a24b1e751ed502))
|
||||
|
||||
## [3.19.1](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.19.0...3.19.1) (2026-04-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **content:** directus published update [skip ci] ([9226512](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/922651232bc3bd035dbc0f035f07c81775df97ca))
|
||||
|
||||
# [3.19.0](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.18.8...3.19.0) (2026-04-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency @iconify-json/simple-icons to v1.2.80 ([9dffaee](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/9dffaee53b84e91c9dd35576f141c23dc2b8e300))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* use ceiling for math instead of percision ([dd74d06](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/dd74d06c57c6277bb1c2af93cb98de51a4a2fbc2))
|
||||
|
||||
## [3.18.8](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.18.7...3.18.8) (2026-04-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **content:** directus published update [skip ci] ([a1290e5](https://gitea.alexlebens.dev/alexlebens/site-profile/commit/a1290e51ef40a4f468b7a477826d48278fae75c1))
|
||||
|
||||
## [3.18.7](https://gitea.alexlebens.dev/alexlebens/site-profile/compare/3.18.6...3.18.7) (2026-04-27)
|
||||
|
||||
|
||||
|
||||
+13
-4
@@ -1,4 +1,4 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import { defineConfig, fontProviders } from 'astro/config';
|
||||
|
||||
import node from '@astrojs/node';
|
||||
import sitemap from '@astrojs/sitemap';
|
||||
@@ -13,6 +13,7 @@ export default defineConfig({
|
||||
site: getSiteURL(),
|
||||
|
||||
image: {
|
||||
dangerouslyProcessSVG: true,
|
||||
remotePatterns: [
|
||||
{ protocol: 'https', hostname: '*.alexlebens.net' },
|
||||
{ protocol: 'https', hostname: '*.jsdelivr.net' },
|
||||
@@ -23,6 +24,8 @@ export default defineConfig({
|
||||
}
|
||||
},
|
||||
|
||||
prefetch: true,
|
||||
|
||||
integrations: [
|
||||
sitemap(),
|
||||
icon({
|
||||
@@ -41,12 +44,12 @@ export default defineConfig({
|
||||
}),
|
||||
(await import('@playform/compress')).default({
|
||||
CSS: true,
|
||||
JavaScript: false,
|
||||
JavaScript: true,
|
||||
HTML: {
|
||||
'html-minifier-terser': {
|
||||
collapseWhitespace: true,
|
||||
minifyCSS: false,
|
||||
minifyJS: false,
|
||||
minifyCSS: true,
|
||||
minifyJS: true,
|
||||
},
|
||||
},
|
||||
Image: false,
|
||||
@@ -54,6 +57,12 @@ export default defineConfig({
|
||||
}),
|
||||
],
|
||||
|
||||
fonts: [{
|
||||
provider: fontProviders.fontsource(),
|
||||
name: "Fredoka",
|
||||
cssVariable: "--font-base",
|
||||
}],
|
||||
|
||||
markdown: {
|
||||
syntaxHighlight: false,
|
||||
},
|
||||
|
||||
+17
-16
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "site-profile",
|
||||
"type": "module",
|
||||
"version": "3.18.7",
|
||||
"version": "3.21.0",
|
||||
"homepage": "https://www.alexlebens.dev",
|
||||
"bugs": {
|
||||
"url": "https://gitea.alexlebens.dev/alexlebens/site-profile/issues",
|
||||
@@ -29,34 +29,35 @@
|
||||
"lint:fix": "eslint --fix \"src/**/*.{js,ts,jsx,tsx,astro}\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "0.9.8",
|
||||
"@astrojs/node": "10.0.6",
|
||||
"@astrojs/check": "0.9.9",
|
||||
"@astrojs/node": "10.1.1",
|
||||
"@astrojs/rss": "4.0.18",
|
||||
"@astrojs/sitemap": "3.7.2",
|
||||
"@directus/sdk": "21.2.2",
|
||||
"@directus/sdk": "21.3.0",
|
||||
"@iconify-json/mdi": "1.2.3",
|
||||
"@iconify-json/pajamas": "1.2.15",
|
||||
"@iconify-json/simple-icons": "1.2.79",
|
||||
"@iconify-json/simple-icons": "1.2.83",
|
||||
"@playform/compress": "0.2.3",
|
||||
"@preline/collapse": "4.2.0",
|
||||
"@swup/astro": "1.8.0",
|
||||
"@tailwindcss/postcss": "4.2.4",
|
||||
"@tailwindcss/vite": "4.2.4",
|
||||
"@tailwindcss/postcss": "4.3.0",
|
||||
"@tailwindcss/vite": "4.3.0",
|
||||
"@types/unist": "3.0.3",
|
||||
"astro": "6.1.9",
|
||||
"astro": "6.3.7",
|
||||
"astro-compress": "2.4.1",
|
||||
"astro-icon": "1.1.5",
|
||||
"dayjs": "1.11.20",
|
||||
"markdown-it": "14.1.1",
|
||||
"marked": "18.0.2",
|
||||
"marked": "18.0.4",
|
||||
"marked-shiki": "1.2.1",
|
||||
"mdast-util-to-string": "4.0.0",
|
||||
"photoswipe": "5.4.4",
|
||||
"preline": "4.1.3",
|
||||
"preline": "4.2.0",
|
||||
"reading-time": "1.5.0",
|
||||
"sharp": "0.34.5",
|
||||
"sharp-ico": "0.1.5",
|
||||
"shiki": "4.0.2",
|
||||
"tailwindcss": "4.2.4",
|
||||
"shiki": "4.1.0",
|
||||
"tailwindcss": "4.3.0",
|
||||
"ultrahtml": "1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -65,20 +66,20 @@
|
||||
"@semantic-release/commit-analyzer": "13.0.1",
|
||||
"@semantic-release/git": "10.0.1",
|
||||
"@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/typography": "0.5.19",
|
||||
"@types/markdown-it": "14.1.2",
|
||||
"eslint": "10.2.1",
|
||||
"eslint": "10.4.0",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-plugin-astro": "1.7.0",
|
||||
"eslint-plugin-format": "2.0.1",
|
||||
"prettier": "3.8.3",
|
||||
"prettier-plugin-astro": "0.14.1",
|
||||
"prettier-plugin-tailwindcss": "0.7.3",
|
||||
"prettier-plugin-tailwindcss": "0.8.0",
|
||||
"semantic-release": "25.0.3",
|
||||
"semantic-release-export-data": "1.2.0",
|
||||
"typescript": "6.0.3",
|
||||
"typescript-eslint": "8.59.0"
|
||||
"typescript-eslint": "8.59.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ const { post } = Astro.props;
|
||||
inferSize={true}
|
||||
/>
|
||||
</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">
|
||||
{post.title}
|
||||
</h2>
|
||||
|
||||
@@ -20,7 +20,7 @@ const { post } = Astro.props;
|
||||
href={`/blog/${post.slug}`}
|
||||
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">
|
||||
{post.title}
|
||||
</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">
|
||||
Experience
|
||||
</h3>
|
||||
<ul class="flex flex-col w-full ml-8 pr-8">
|
||||
{experiences.map((experience: Experience) => {
|
||||
<ul class="flex flex-col w-full gap-8">
|
||||
{experiences.map((experience: Experience, index: number) => {
|
||||
const startYear = new Date(experience.startDate).getFullYear();
|
||||
const endYear = experience.endDate != null ? new Date(experience.endDate).getFullYear() : 'Present';
|
||||
|
||||
return (
|
||||
<li class="relative">
|
||||
<div class="smooth-reveal group relative grid sm:grid-cols-18 sm:gap-8 md:gap-6 pb-16">
|
||||
<header class="relative sm:col-span-3 text-header font-semibold text-lg mt-1">
|
||||
<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="w-28 md:w-32 text-end pt-1 shrink-0">
|
||||
<header class="text-sm md:text-base font-semibold text-header">
|
||||
<time datetime={experience.startDate} data-title={experience.startDate}>
|
||||
{startYear}
|
||||
</time>
|
||||
@@ -35,115 +35,130 @@ const experiences = ((await directus.request(
|
||||
{endYear}
|
||||
</time>
|
||||
</header>
|
||||
<div class="relative flex flex-col sm:col-span-12 pb-6">
|
||||
<div class="absolute bg-accent -translate-x-[1.71rem] rounded-full h-2 w-2 mt-3"/>
|
||||
<h3>
|
||||
<div
|
||||
class="inline-flex items-center text-2xl leading-tight font-semibold"
|
||||
aria-label="{position} - {company}"
|
||||
>
|
||||
<span class="text-header">
|
||||
{experience.position} <span>@</span>
|
||||
{experience.url ? (
|
||||
<a
|
||||
class="hover:text-main"
|
||||
href={experience.url}
|
||||
title={`Ver ${experience.name}`}
|
||||
target="_blank"
|
||||
>
|
||||
{experience.name}
|
||||
</a>
|
||||
) : (
|
||||
<span>{experience.name}</span>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</h3>
|
||||
{(experience.location || experience.location_type) && (
|
||||
<div class="text-secondary text-sm">
|
||||
{experience.location} {experience.location && experience.location_type && '-'} {experience.location_type}
|
||||
</div>
|
||||
<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">
|
||||
<div class="relative z-10 size-7 flex justify-center items-center">
|
||||
<div class="size-2 rounded-full bg-accent"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grow pt-0.5">
|
||||
<h3>
|
||||
<div
|
||||
class="inline-flex items-center text-2xl leading-tight font-semibold"
|
||||
aria-label="{position} - {company}"
|
||||
>
|
||||
<span class="text-header">
|
||||
{experience.position} <span>@</span>
|
||||
{experience.url ? (
|
||||
<a
|
||||
class="hover:text-main"
|
||||
href={experience.url}
|
||||
title={`Ver ${experience.name}`}
|
||||
target="_blank"
|
||||
>
|
||||
{experience.name}
|
||||
</a>
|
||||
) : (
|
||||
<span>{experience.name}</span>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div class="text-md mt-4 flex flex-col gap-4" x-data="{ expanded: false }">
|
||||
{experience.summary && (
|
||||
</h3>
|
||||
{(experience.location || experience.location_type) && (
|
||||
<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">
|
||||
<h4 class="text-header font-semibold">
|
||||
Summary:
|
||||
Responsibilities:
|
||||
</h4>
|
||||
<ul class="flex flex-col text-primary list-disc gap-2 [&>li]:ml-4">
|
||||
{experience.responsibilities.map(responsibility => (
|
||||
<li class="marker:text-main">
|
||||
{experience.summary}
|
||||
{responsibility}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
{(experience.responsibilities || 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>
|
||||
{experience.responsibilities && (
|
||||
<div class="flex flex-col gap-1">
|
||||
<h4 class="text-header font-semibold">
|
||||
Responsibilities:
|
||||
</h4>
|
||||
<ul class="flex flex-col text-primary list-disc gap-2 [&>li]:ml-4">
|
||||
{experience.responsibilities.map(responsibility => (
|
||||
<li class="marker:text-main">
|
||||
{responsibility}
|
||||
</li>
|
||||
))}
|
||||
</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>
|
||||
)}
|
||||
{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>
|
||||
|
||||
<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">
|
||||
<span x-text="expanded ? 'Show less' : 'Show more'">
|
||||
Show more
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<p class="mb-4">
|
||||
<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
|
||||
class="group-hover/more:translate-y-0.5 ease-out duration-300 h-4 w-4"
|
||||
:class="{ 'rotate-180': expanded }"
|
||||
viewBox="0 0 24 24"
|
||||
class="hs-collapse-open:rotate-180 shrink-0 size-4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<polyline points="6 9 12 15 18 9" />
|
||||
<path d="m6 9 6 6 6-6"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<ul
|
||||
class="flex print:hidden flex-wrap gap-2 mt-2"
|
||||
aria-label="Technologies used"
|
||||
>
|
||||
{experience.skills && experience.skills.map(skill => {
|
||||
const iconName = skill.toLowerCase();
|
||||
const skillName = skill.split(':')[1].replace(/^language-/, '').replace(/-/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase());
|
||||
return (
|
||||
<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>
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
<ul
|
||||
class="flex print:hidden flex-wrap gap-2"
|
||||
aria-label="Technologies used"
|
||||
>
|
||||
{experience.skills && experience.skills.map(skill => {
|
||||
const iconName = skill.toLowerCase();
|
||||
const skillName = skill.split(':')[1].replace(/^language-/, '').replace(/-/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase());
|
||||
return (
|
||||
<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>
|
||||
</div>
|
||||
</li>
|
||||
@@ -152,8 +167,6 @@ const experiences = ((await directus.request(
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- Alpine Plugins -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/collapse@3.x.x/dist/cdn.min.js"></script>
|
||||
|
||||
<!-- Alpine Core -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<script>
|
||||
import "@preline/collapse/index.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">
|
||||
Skills
|
||||
</h3>
|
||||
<div>
|
||||
<div class="tech-stack-slider relative overflow-hidden py-4 sm:py-8 mask-[linear-gradient(to_right,transparent,black_10%,black_90%,transparent)]">
|
||||
<!-- Main slider container -->
|
||||
<div class="slider-track animate-slide flex">
|
||||
{[...skills, ...skills, ...skills].map((skill: Skill) => {
|
||||
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">
|
||||
<div class="p-4 sm:p-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 justify-center rounded-lg text-primary">
|
||||
<Icon name={skill.icon} class="h-8 w-8 sm:h-12 sm:w-12" />
|
||||
<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="flex">
|
||||
<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="flex gap-4">
|
||||
{[...skills, ...skills, ...skills].map((skill: Skill) => {
|
||||
return (
|
||||
<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="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 justify-center rounded-lg text-primary">
|
||||
<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>
|
||||
<h3 class="text-neutral-900 dark:text-neutral-100 text-base font-semibold sm:text-xl">
|
||||
{skill.title}
|
||||
</h3>
|
||||
<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 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>
|
||||
<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 class="relative bg-stone-500/20 dark:bg-stone-500/20 rounded-full h-1.5 sm:h-2 w-full overflow-hidden">
|
||||
<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>
|
||||
</figure>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
document.addEventListener('astro:page-load', () => {
|
||||
function setupInfiniteScroll() {
|
||||
const cards = document.querySelectorAll('.skill-card');
|
||||
if (!cards.length) return;
|
||||
}
|
||||
function initSkillCards() {
|
||||
const cards = document.querySelectorAll<HTMLElement>('.skill-card');
|
||||
if (!cards.length) return;
|
||||
|
||||
setupInfiniteScroll();
|
||||
|
||||
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
||||
const cards = document.querySelectorAll('.skill-card');
|
||||
|
||||
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 = '';
|
||||
});
|
||||
cards.forEach((card) => {
|
||||
// Desktop/Mouse events
|
||||
card.addEventListener('mouseenter', () => {
|
||||
card.style.setProperty('transition', 'transform 0.1s ease, box-shadow 0.1s ease', 'important');
|
||||
});
|
||||
} else {
|
||||
// Simpler effects for touch devices
|
||||
cards.forEach((card) => {
|
||||
card.addEventListener('touchstart', () => {
|
||||
card.classList.add('is-touched');
|
||||
});
|
||||
|
||||
card.addEventListener('touchend', () => {
|
||||
setTimeout(() => {
|
||||
card.classList.remove('is-touched');
|
||||
}, 300);
|
||||
});
|
||||
card.addEventListener('mousemove', (e: MouseEvent) => {
|
||||
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.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>
|
||||
|
||||
<style>
|
||||
/* Specific css to enable sliding effect */
|
||||
.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 effects */
|
||||
.skill-card {
|
||||
transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transform-style: preserve-3d;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.skill-card:hover {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* Reduce animation complexity on mobile */
|
||||
@media (max-width: 640px) {
|
||||
.skill-card {
|
||||
transition:
|
||||
|
||||
@@ -75,7 +75,7 @@ const readingTime = getReadingTime(post.content || '');
|
||||
</li>
|
||||
<li class="inline-flex items-center">
|
||||
<span class="shrink-0 overflow-hidden">
|
||||
{readingTime.minutes.toPrecision(1)} minutes
|
||||
{Math.ceil(readingTime.minutes)} minutes
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
@@ -13,7 +13,6 @@ export const NavigationLinks: NavigationLink[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Blog', url: '/blog/' },
|
||||
{ name: 'Categories', url: '/categories/' },
|
||||
{ name: 'Apps', url: '/apps/' },
|
||||
{ name: 'About Me', url: '/about/' },
|
||||
];
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
import { Font } from "astro:assets";
|
||||
|
||||
import { readSingleton } from '@directus/sdk';
|
||||
|
||||
import BaseHead from '@components/BaseHead.astro';
|
||||
@@ -38,6 +40,8 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
||||
structuredData={structuredData}
|
||||
/>
|
||||
|
||||
<Font cssVariable="--font-base" />
|
||||
|
||||
<!-- Set Theme -->
|
||||
<script is:inline>
|
||||
const theme = (() => {
|
||||
@@ -62,14 +66,14 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
||||
<script
|
||||
src="/vendor/preline/collapse2.1.0.min.js"
|
||||
is:inline
|
||||
/>
|
||||
></script>
|
||||
|
||||
<!-- Rybbit Tracking Snippet -->
|
||||
<script
|
||||
src="https://rybbit.alexlebens.dev/api/script.js"
|
||||
data-site-id={global.rybbit_site_id}
|
||||
defer
|
||||
/>
|
||||
></script>
|
||||
</head>
|
||||
|
||||
<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(
|
||||
to bottom,
|
||||
transparent 0px,
|
||||
transparent 90px,
|
||||
black 140px,
|
||||
transparent 84px,
|
||||
black 114px,
|
||||
black 100%
|
||||
);
|
||||
|
||||
mask-image: linear-gradient(
|
||||
to bottom,
|
||||
transparent 0px,
|
||||
transparent 90px,
|
||||
black 140px,
|
||||
transparent 84px,
|
||||
black 114px,
|
||||
black 100%
|
||||
);
|
||||
|
||||
@@ -171,7 +175,7 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
||||
.bg {
|
||||
animation: slide 25s ease-in-out infinite alternate;
|
||||
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);
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
@@ -180,15 +184,6 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
||||
opacity: .5;
|
||||
position: fixed;
|
||||
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 {
|
||||
|
||||
@@ -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>
|
||||
+47
-6
@@ -1,4 +1,5 @@
|
||||
@import 'tailwindcss';
|
||||
|
||||
@import './utilities-buttons.css';
|
||||
@import './utilities-cards.css';
|
||||
@import './utilities-misc.css';
|
||||
@@ -6,6 +7,11 @@
|
||||
@plugin '@tailwindcss/typography';
|
||||
@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 */
|
||||
/* https://tailwindcss.com/docs/dark-mode */
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
@@ -39,23 +45,31 @@
|
||||
--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));
|
||||
|
||||
/* Object colors */
|
||||
--color-background: light-dark(var(--color-neutral-200), var(--color-stone-700));
|
||||
--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-card: light-dark(color-mix(in srgb, var(--color-neutral-100) 80%, transparent), color-mix(in srgb, var(--color-neutral-800) 60%, transparent));
|
||||
/* Background colors */
|
||||
--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-mist-900) 20%, 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));
|
||||
|
||||
/* Typography */
|
||||
--color-prose-blog-body: var(--color-neutral-700);
|
||||
--color-prose-blog-headings: var(--color-neutral-900);
|
||||
--color-prose-blog-links: var(--color-orange-300);
|
||||
|
||||
|
||||
--color-prose-blog-invert-body: var(--color-neutral-400);
|
||||
--color-prose-blog-invert-headings: var(--color-neutral-200);
|
||||
|
||||
--radius-markdown-img: 0.5rem;
|
||||
|
||||
/* Font */
|
||||
--font-sans: var(--font-base);
|
||||
|
||||
/* Reveal Animations */
|
||||
--animate-reveal: reveal 0.8s ease forwards;
|
||||
--animate-reveal-fade: reveal-fade 1.8s ease forwards;
|
||||
@@ -74,7 +88,7 @@
|
||||
:root {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
|
||||
--theme-transition: 0.3s ease;
|
||||
}
|
||||
|
||||
@@ -114,6 +128,33 @@
|
||||
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 */
|
||||
.prose blockquote {
|
||||
font-style: normal;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
@utility button-base-hidden {
|
||||
@apply transition-all duration-300
|
||||
border border-transparent
|
||||
hover:bg-neutral-200 dark:hover:bg-neutral-700
|
||||
hover:bg-mist-200 dark:hover:bg-mist-700
|
||||
p-2
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
@utility button-bg-neutral {
|
||||
@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
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@utility card-base {
|
||||
@apply transition-all duration-300
|
||||
rounded-xl
|
||||
border border-neutral-100 dark:border-stone-500/20
|
||||
bg-background-card hover:bg-neutral-100 dark:hover:bg-neutral-800/90
|
||||
border border-mist-100/20 dark:border-mist-700/20
|
||||
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
|
||||
}
|
||||
|
||||
@@ -10,7 +10,14 @@
|
||||
@apply transition-all duration-300
|
||||
rounded-2xl
|
||||
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 {
|
||||
@@ -21,7 +28,7 @@
|
||||
|
||||
@utility card-hover-icon-scale {
|
||||
@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
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Nav */
|
||||
@utility nav-base {
|
||||
@apply border border-neutral-100 dark:border-stone-500/20
|
||||
bg-neutral-100 dark:bg-neutral-800
|
||||
@apply border border-mist-100/20 dark:border-mist-700/20
|
||||
bg-mist-100/80 dark:bg-mist-900/40
|
||||
shadow-xs dark:shadow-md
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user