Svelte 5 for portfolio page.

This commit is contained in:
Bradley Shellnut 2024-12-03 09:35:23 -08:00
parent e6a2f8fcb6
commit e8c6b83a1e
6 changed files with 132 additions and 65 deletions

View file

@ -63,6 +63,7 @@
"@resvg/resvg-js": "^2.6.2",
"@sveltejs/adapter-vercel": "^5.5.0",
"@types/nprogress": "^0.2.3",
"@unpic/svelte": "^0.0.56",
"@vercel/og": "^0.6.4",
"bits-ui": "^0.21.16",
"flexsearch": "^0.7.43",

View file

@ -17,6 +17,9 @@ importers:
'@types/nprogress':
specifier: ^0.2.3
version: 0.2.3
'@unpic/svelte':
specifier: ^0.0.56
version: 0.0.56(svelte@5.3.1)
'@vercel/og':
specifier: ^0.6.4
version: 0.6.4
@ -1395,6 +1398,14 @@ packages:
'@types/unist@2.0.6':
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
'@unpic/core@0.0.52':
resolution: {integrity: sha512-XRX0ePG0nH/K9x/coCQwFzSzg66INBNgPZR2FeSis6BHyxw3sBjL4KDzYse6d/Zx0F3APWsWkK2htaGRznjHMw==}
'@unpic/svelte@0.0.56':
resolution: {integrity: sha512-YkZaHLYEQycs4MoBH0YXt29hdSaS6RoUOpSf1IaZ4MnfJOrRcjpAxIsN8uMaLu8g7IyxO9dWHmPmmECpKluA5g==}
peerDependencies:
svelte: '*'
'@vercel/nft@0.27.1':
resolution: {integrity: sha512-K6upzYHCV1cq2gP83r1o8uNV1vwvAlozvMqp7CEjYWxo0CMI8/4jKcDkVjlypVhrfZ54SXwh9QbH0ZIk/vQCsw==}
engines: {node: '>=16'}
@ -2634,6 +2645,9 @@ packages:
strip-literal@2.1.0:
resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==}
style-object-to-css-string@1.1.3:
resolution: {integrity: sha512-bISQoUsir/qGfo7vY8rw00ia9nnyE1jvYt3zZ2jhdkcXZ6dAEi74inMzQ6On57vFI+I4Fck6wOv5UI9BEwJDgw==}
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@ -2789,6 +2803,9 @@ packages:
unist-util-visit@3.1.0:
resolution: {integrity: sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==}
unpic@3.20.0:
resolution: {integrity: sha512-reWY4Ez9FCjw8J7fGByyyi1Z1fv20xjkFgDa9xI7vqdg89fcLzUYkROKo7yZ5WHRelq6x+pL4ohPRzEdU020aQ==}
update-browserslist-db@1.1.0:
resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==}
hasBin: true
@ -3944,6 +3961,17 @@ snapshots:
'@types/unist@2.0.6': {}
'@unpic/core@0.0.52':
dependencies:
unpic: 3.20.0
'@unpic/svelte@0.0.56(svelte@5.3.1)':
dependencies:
'@unpic/core': 0.0.52
style-object-to-css-string: 1.1.3
svelte: 5.3.1
unpic: 3.20.0
'@vercel/nft@0.27.1':
dependencies:
'@mapbox/node-pre-gyp': 1.0.11
@ -5335,6 +5363,8 @@ snapshots:
dependencies:
js-tokens: 9.0.0
style-object-to-css-string@1.1.3: {}
supports-preserve-symlinks-flag@1.0.0: {}
svelte-check@4.1.0(picomatch@4.0.2)(svelte@5.3.1)(typescript@5.7.2):
@ -5483,6 +5513,8 @@ snapshots:
unist-util-is: 5.2.0
unist-util-visit-parents: 4.1.1
unpic@3.20.0: {}
update-browserslist-db@1.1.0(browserslist@4.23.3):
dependencies:
browserslist: 4.23.3

View file

@ -1,21 +1,30 @@
<script lang="ts">
import LazyImage from './LazyImage.svelte';
import type { Picture } from 'vite-imagetools';
import type { Snippet } from 'svelte';
import { ExternalLinkType } from '../types/externalLinkType';
export let name: string;
export let src: Record<string, any>;
export let alt: string;
export let style = "";
export let loading: "lazy" | "eager" = "lazy";
const {
links,
details,
portfolioDetails,
externalLinks,
name,
src,
alt,
style,
fetchpriority = 'auto',
loading = 'lazy',
}: { links: Snippet<ExternalLinkType[]>, details: Snippet<string>, portfolioDetails: string, externalLinks: ExternalLinkType[], name: string; src: string | Picture; alt: string; style: string; fetchpriority?: 'high' | 'low' | 'auto'; loading?: 'lazy' | 'eager' } = $props();
</script>
<div class="portfolio">
<div class="portfolio-picture">
<h2>{name}</h2>
<LazyImage {style} {src} {alt} {loading} />
<slot name="portfolio-links" />
<enhanced:img {src} {style} {alt} {fetchpriority} {loading} />
{@render links(externalLinks)}
</div>
<div class="portfolio-details">
<slot name="portfolio-details" />
{@render details()}
</div>
</div>

View file

@ -0,0 +1,9 @@
import type { IconifyIcon } from "iconify-icon";
export type ExternalLinkType = {
ariaLabel: string;
href: string;
icon?: IconifyIcon;
showIcon: boolean;
text: string;
};

View file

@ -43,10 +43,10 @@ export const load: PageServerLoad = async ({ fetch, setHeaders, url }) => {
url: currentPageUrl
});
const [albums, articles]: [Album[], ArticlePageLoad] = await Promise.all([
await fetchBandcampAlbums(),
(await fetch('/api/articles?page=1&limit=3')).json()
]);
// const [albums, articles]: [Album[], ArticlePageLoad] = await Promise.all([
// await fetchBandcampAlbums(),
// (await fetch('/api/articles?page=1&limit=3')).json()
// ]);
setHeaders({
'cache-control': 'max-age=43200'
@ -54,7 +54,7 @@ export const load: PageServerLoad = async ({ fetch, setHeaders, url }) => {
return {
baseUrl,
metaTagsChild: metaTags,
albums,
articlesData: articles
albums: await fetchBandcampAlbums(),
articlesData: await (await fetch('/api/articles?page=1&limit=3')).json()
};
};

View file

@ -1,33 +1,53 @@
<script lang="ts">
import { createTabs, melt } from '@melt-ui/svelte';
import GitHub from '@iconify-icons/simple-icons/github';
import Portfolio from '$lib/components/Portfolio.svelte';
import personalSite from "$lib/assets/images/portfolio/Bradley_Shellnut_New_Site.png?as=run";
import weddingWebsite from "$lib/assets/images/portfolio/Wedding_Website.png?as=run";
import oldSite from '$lib/assets/images/portfolio/Old_Website_Bradley_Shellnut.png?as=run';
import shellnutArchitectWebsite from "$lib/assets/images/portfolio/Mark_Shellnut_Architect.png?as=run";
// @ts-expect-error: Cannot find module '$lib/content/uses/development.md' or its corresponding type declarations.ts(2307)
import PersonalWebsiteSvelteKit from "$lib/content/portfolio/personal/personal-website-sveltekit.md";
// @ts-expect-error: Cannot find module '$lib/content/uses/development.md' or its corresponding type declarations.ts(2307)
import WeddingWebsite from '$lib/content/portfolio/personal/wedding-website.md';
// @ts-expect-error: Cannot find module '$lib/content/uses/development.md' or its corresponding type declarations.ts(2307)
import MarkShellnutArchitect from '$lib/content/portfolio/professional/mark-shellnut-architect.md';
// @ts-expect-error: Cannot find module '$lib/content/uses/development.md' or its corresponding type declarations.ts(2307)
import OldWebsite from '$lib/content/portfolio/personal/old-website.md';
import ExternalLink from '$lib/components/ExternalLink.svelte';
import ExternalLink from '$lib/components/ExternalLink.svelte';
import Portfolio from '$lib/components/Portfolio.svelte';
// @ts-expect-error: Cannot find module '$lib/content/uses/development.md' or its corresponding type declarations.ts(2307)
import OldWebsite from '$lib/content/portfolio/personal/old-website.md';
// @ts-expect-error: Cannot find module '$lib/content/uses/development.md' or its corresponding type declarations.ts(2307)
import PersonalWebsiteSvelteKit from '$lib/content/portfolio/personal/personal-website-sveltekit.md';
// @ts-expect-error: Cannot find module '$lib/content/uses/development.md' or its corresponding type declarations.ts(2307)
import WeddingWebsite from '$lib/content/portfolio/personal/wedding-website.md';
// @ts-expect-error: Cannot find module '$lib/content/uses/development.md' or its corresponding type declarations.ts(2307)
import MarkShellnutArchitect from '$lib/content/portfolio/professional/mark-shellnut-architect.md';
import type { ExternalLinkType } from '$lib/types/externalLinkType';
import GitHub from '@iconify-icons/simple-icons/github';
import { createTabs, melt } from '@melt-ui/svelte';
import personalSite from '../../lib/assets/images/portfolio/Bradley_Shellnut_New_Site.png?enhanced';
import shellnutArchitectWebsite from '../../lib/assets/images/portfolio/Mark_Shellnut_Architect.png?enhanced';
import oldSite from '../../lib/assets/images/portfolio/Old_Website_Bradley_Shellnut.png?enhanced';
import weddingWebsite from '../../lib/assets/images/portfolio/Wedding_Website.png?enhanced';
const {
elements: { root, list, content, trigger }
} = createTabs({
defaultValue: 'personal'
});
const {
elements: { root, list, content, trigger },
} = createTabs({
defaultValue: 'personal',
});
const triggers = [
const triggers = [
{ id: 'personal', title: 'Personal Sites' },
{ id: 'professional', title: 'Professional Sites'}
];
{ id: 'professional', title: 'Professional Sites' },
];
</script>
{#snippet links(externalLinks: ExternalLinkType[])}
<span>
{#each externalLinks as link}
<ExternalLink
ariaLabel={link.ariaLabel}
href={link.href}
icon={link.icon}
showIcon={link.showIcon}
>
{link.text}
</ExternalLink>
{/each}
</span>
{/snippet}
{#snippet details(portfolioDetails: string)}
{portfolioDetails}
{/snippet}
<h1>Portfolio!</h1>
<div use:melt={$root} class="root tab-group">
<div use:melt={$list} aria-label="tabs portfolios" class="list tab-list">
@ -42,42 +62,38 @@
style="max-height: 550px;"
src={personalSite}
loading="eager"
alt="Picture of Bradley Shellnut's Personal Website">
<span slot="portfolio-links">
<ExternalLink ariaLabel="View GitHub repository for my personal website" href="https://github.com/BradNut/personal-website-sveltekit" icon={GitHub} showIcon>GitHub repository</ExternalLink>
</span>
<PersonalWebsiteSvelteKit slot="portfolio-details" />
alt="Picture of Bradley Shellnut's Personal Website"
{links}
{details}
portfolioDetails={PersonalWebsiteSvelteKit}
externalLinks={[{ ariaLabel: 'View GitHub repository for my personal website', href: 'https://github.com/BradNut/personal-website-sveltekit', icon: GitHub, showIcon: true, text: 'GitHub repository'}]}>
</Portfolio>
<Portfolio name="Wedding Website"
style="max-height: 550px;"
src={weddingWebsite}
alt="Picture of NextJS Wedding Website">
<span slot="portfolio-links">
<ExternalLink ariaLabel="View Wedding Website" href="https://weddingsite-six.vercel.app/" showIcon>View Site</ExternalLink>
<ExternalLink ariaLabel="View GitHub repository for the wedding site" href="https://github.com/BradNut/weddingsite" icon={GitHub} showIcon>GitHub repository</ExternalLink>
</span>
<WeddingWebsite slot="portfolio-details" />
</Portfolio>
alt="Picture of NextJS Wedding Website"
{links}
{details}
portfolioDetails={WeddingWebsite}
externalLinks={[{ ariaLabel: 'View GitHub repository for the wedding site', href: 'https://github.com/BradNut/weddingsite', icon: GitHub, showIcon: true, text: 'GitHub repository'}]}/>
<Portfolio name="Old Personal Website"
style="max-height: 320px;"
src={oldSite}
alt="Home Page of the old bradleyshellnut.com website">
<span slot="portfolio-links">
<ExternalLink ariaLabel="Archive of bradleyshellnut.com" href="https://web.archive.org/web/20201205233507/https://bradleyshellnut.com/about" showIcon>Link to an archive snapshot</ExternalLink>
</span>
<OldWebsite slot="portfolio-details" />
</Portfolio>
alt="Home Page of the old bradleyshellnut.com website"
{links}
{details}
portfolioDetails={OldWebsite}
externalLinks={[{ ariaLabel: 'Archive of bradleyshellnut.com', href: 'https://web.archive.org/web/20201205233507/https://bradleyshellnut.com/about', icon: GitHub, showIcon: true, text: 'Link to an archive snapshot'}]}/>
</div>
<div use:melt={$content('professional')} class="content">
<Portfolio name="Mark Shellnut Architect"
style="max-height: 550px;"
src={shellnutArchitectWebsite}
alt="Picture of Mark Shellnut Architect's Website">
<span slot="portfolio-links">
<ExternalLink ariaLabel="View markshellnutarchitect.com" href="https://markshellnutarchitect.com" showIcon>Link to Mark Shellnut's Website</ExternalLink>
</span>
<MarkShellnutArchitect slot="portfolio-details" />
</Portfolio>
alt="Picture of Mark Shellnut Architect's Website"
{links}
{details}
portfolioDetails={MarkShellnutArchitect}
externalLinks={[{ ariaLabel: 'View Mark Shellnut Architect', href: 'https://markshellnutarchitect.com', showIcon: false, text: 'Link to Mark Shellnut Architect'}]} />
</div>
</div>