Recreate front page from SvelteKit
|
|
@ -1,8 +1,9 @@
|
|||
import { defineConfig } from "astro/config";
|
||||
|
||||
import tailwind from "@astrojs/tailwind";
|
||||
|
||||
import svelte from "@astrojs/svelte";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [tailwind()],
|
||||
integrations: [tailwind(), svelte()]
|
||||
});
|
||||
|
|
@ -10,8 +10,10 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/svelte": "^4.0.3",
|
||||
"@astrojs/tailwind": "^5.0.2",
|
||||
"astro": "^3.3.0",
|
||||
"svelte": "^4.0.0",
|
||||
"tailwindcss": "^3.0.24"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
3773
pnpm-lock.yaml
BIN
public/favicon.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -1,9 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||
<style>
|
||||
path { fill: #000; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path { fill: #FFF; }
|
||||
}
|
||||
</style>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 749 B |
BIN
src/assets/icons/facebook-icon.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
src/assets/icons/github-icon.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
src/assets/icons/instagram-icon.png
Normal file
|
After Width: | Height: | Size: 7 KiB |
1
src/assets/icons/linkedin-icon.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#444444" d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/></svg>
|
||||
|
After Width: | Height: | Size: 440 B |
BIN
src/assets/icons/twitter-icon.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/icons/vsco-icon.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/images/glossary-tester.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
src/assets/images/ninjavote.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
src/assets/images/portrait.jpg
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
src/assets/images/snipcast.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
src/assets/images/splitlist.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
18
src/components/Link.astro
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
interface Props {
|
||||
href: string;
|
||||
[attribute: string]: string;
|
||||
}
|
||||
|
||||
const { href, class: className, ...attributes } = Astro.props;
|
||||
---
|
||||
|
||||
<a
|
||||
class={`text-teal-600 duration-100 hover:text-teal-500 hover:underline ${
|
||||
className ?? ""
|
||||
}`}
|
||||
{href}
|
||||
{...attributes}
|
||||
>
|
||||
<slot />
|
||||
</a>
|
||||
117
src/components/Navbar.svelte
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
<script lang="ts">
|
||||
import { slide, fade } from "svelte/transition";
|
||||
|
||||
export let currentPath: string;
|
||||
|
||||
let scrollPosition = 0;
|
||||
$: isScrolled = scrollPosition > 0;
|
||||
|
||||
const navbarContent = [
|
||||
{ name: "👨💻 Projects", href: "/programming" },
|
||||
{ name: "📷 Photography", href: "/photography" },
|
||||
// { name: "📝 Articles", href: "/articles" },
|
||||
];
|
||||
|
||||
let collapsed = true;
|
||||
</script>
|
||||
|
||||
<svelte:window bind:scrollY={scrollPosition} />
|
||||
|
||||
<header
|
||||
class="sticky top-0 z-10 bg-gray-50 transition-shadow ease-in"
|
||||
class:shadow={isScrolled}
|
||||
>
|
||||
<nav
|
||||
class="mx-auto flex h-16 max-w-5xl flex-wrap items-center justify-between px-6"
|
||||
>
|
||||
<a
|
||||
href="/"
|
||||
data-sveltekit-preload-code="eager"
|
||||
class="text-lg tracking-wide text-gray-600 decoration-yellow-400 decoration-2 underline-offset-8 duration-100 hover:text-gray-400"
|
||||
class:underline={"/" === currentPath}
|
||||
>
|
||||
Mikkel Svartveit
|
||||
</a>
|
||||
|
||||
<ul class="hidden space-x-8 md:flex">
|
||||
{#each navbarContent as { name, href }}
|
||||
<li>
|
||||
<a
|
||||
{href}
|
||||
data-sveltekit-preload-code="eager"
|
||||
class="text-lg tracking-wide text-gray-600 decoration-yellow-400 decoration-2 underline-offset-8 duration-100 hover:text-gray-400"
|
||||
class:underline={href === currentPath}
|
||||
>
|
||||
{name}
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<button
|
||||
aria-label="Open menu"
|
||||
class="md:hidden"
|
||||
on:click={() => (collapsed = !collapsed)}
|
||||
>
|
||||
<svg
|
||||
class="h-10 w-10 stroke-yellow-500"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g id="Menu / Hamburger_MD">
|
||||
<path
|
||||
id="Vector"
|
||||
d="M5 17H19M5 12H19M5 7H19"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
{#if !collapsed}
|
||||
<div
|
||||
transition:fade={{ duration: 100 }}
|
||||
class="fixed left-0 top-0 z-20 h-full w-full bg-black opacity-50"
|
||||
/>
|
||||
<ul
|
||||
transition:slide={{ duration: 300, axis: "x" }}
|
||||
class="fixed right-0 top-0 z-30 block h-full bg-white p-4"
|
||||
>
|
||||
<button
|
||||
aria-label="Close menu"
|
||||
on:click={() => (collapsed = true)}
|
||||
class="ml-auto block h-10 w-10"
|
||||
>
|
||||
<svg
|
||||
class="stroke-gray-400"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16 8L8 16M8.00001 8L16 16"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{#each navbarContent as { name, href }}
|
||||
<li class="my-6 ml-2 mr-16">
|
||||
<a
|
||||
{href}
|
||||
on:click={() => (collapsed = true)}
|
||||
class="whitespace-nowrap text-lg tracking-wide text-gray-600 decoration-yellow-400 decoration-2 underline-offset-8"
|
||||
class:underline={href === currentPath}
|
||||
>
|
||||
{name}
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
14
src/components/Paragraph.astro
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
interface Props {
|
||||
[attribute: string]: any;
|
||||
}
|
||||
|
||||
const { class: className, ...attributes } = Astro.props;
|
||||
---
|
||||
|
||||
<p
|
||||
class={`my-4 font-serif text-lg text-gray-700 ${className ?? ""}`}
|
||||
{...attributes}
|
||||
>
|
||||
<slot />
|
||||
</p>
|
||||
50
src/components/SocialIcons.astro
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
import githubIcon from "../assets/icons/github-icon.png";
|
||||
import linkedinIcon from "../assets/icons/linkedin-icon.svg";
|
||||
import twitterIcon from "../assets/icons/twitter-icon.png";
|
||||
import facebookIcon from "../assets/icons/facebook-icon.png";
|
||||
import instagramIcon from "../assets/icons/instagram-icon.png";
|
||||
import vscoIcon from "../assets/icons/vsco-icon.png";
|
||||
import { Image } from "astro:assets";
|
||||
|
||||
const socialMedia = [
|
||||
{
|
||||
name: "GitHub",
|
||||
icon: githubIcon,
|
||||
url: "https://github.com/mikkelsvartveit",
|
||||
},
|
||||
{
|
||||
name: "LinkedIn",
|
||||
icon: linkedinIcon,
|
||||
url: "https://linkedin.com/in/mikkelsvartveit",
|
||||
},
|
||||
{
|
||||
name: "Twitter",
|
||||
icon: twitterIcon,
|
||||
url: "https://twitter.com/mikkelsvartveit",
|
||||
},
|
||||
{
|
||||
name: "Facebook",
|
||||
icon: facebookIcon,
|
||||
url: "https://facebook.com/profile.php?id=100006609016880",
|
||||
},
|
||||
{
|
||||
name: "Instagram",
|
||||
icon: instagramIcon,
|
||||
url: "https://instagram.com/mikkelsvartveit",
|
||||
},
|
||||
{
|
||||
name: "VSCO",
|
||||
icon: vscoIcon,
|
||||
url: "https://vsco.co/mikkelsvartveit",
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
{
|
||||
socialMedia.map(({ name, icon, url }) => (
|
||||
<a href={url} target="_blank">
|
||||
<Image src={icon} alt={name} class="inline-block h-8 w-8" />
|
||||
</a>
|
||||
))
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="description" content="Astro description" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
32
src/layouts/RootLayout.astro
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
import Navbar from "../components/Navbar.svelte";
|
||||
interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>{title}</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Hi, I'm Mikkel! I am a Computer Science student from Norway and this is my playground. Here you will find some programming projects, and a small collection of photos I'm proud of."
|
||||
/>
|
||||
</head>
|
||||
<body class="overflow-y-scroll bg-gray-50">
|
||||
<Navbar client:load currentPath={Astro.url.pathname} />
|
||||
<main>
|
||||
<slot />
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Nunito:wght@400;600&family=Source+Serif+Pro:wght@300;400;600&display=swap");
|
||||
</style>
|
||||
|
|
@ -1,9 +1,61 @@
|
|||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import { Image } from "astro:assets";
|
||||
import RootLayout from "../layouts/RootLayout.astro";
|
||||
import Link from "../components/Link.astro";
|
||||
import Paragraph from "../components/Paragraph.astro";
|
||||
import SocialIcons from "../components/SocialIcons.astro";
|
||||
|
||||
import portraitImage from "../assets/images/portrait.jpg";
|
||||
---
|
||||
|
||||
<Layout title="Mikkel Svartveit">
|
||||
<main>
|
||||
<h1>Hello World!</h1>
|
||||
</main>
|
||||
</Layout>
|
||||
<RootLayout title="Mikkel Svartveit">
|
||||
<div
|
||||
class="mx-auto flex max-w-5xl flex-col-reverse px-3 pb-8 pt-12 sm:px-6 md:flex-row"
|
||||
>
|
||||
<section class="w-full md:w-1/2">
|
||||
<h1
|
||||
class="mb-8 font-serif text-3xl font-light tracking-wide text-gray-600 sm:text-4xl"
|
||||
>
|
||||
Hi, I'm Mikkel 👋
|
||||
</h1>
|
||||
|
||||
<Paragraph>
|
||||
I am a Computer Science student from Norway and this is my playground.
|
||||
Thanks for stopping by!
|
||||
</Paragraph>
|
||||
|
||||
<Paragraph>
|
||||
Here you will find some
|
||||
<Link href="/programming">programming projects</Link>, and a small
|
||||
<Link href="/photography">collection of photos</Link>
|
||||
I'm proud of.
|
||||
</Paragraph>
|
||||
|
||||
<Paragraph>
|
||||
Want to get in touch?
|
||||
<Link href="mailto:hi@mikkelsvartveit.com">Contact me.</Link>
|
||||
</Paragraph>
|
||||
|
||||
<div class="mt-8 space-x-3">
|
||||
<SocialIcons />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<figure class="px-4 md:w-1/2">
|
||||
<Image
|
||||
class="mx-auto mb-12 block w-full max-w-sm rounded-full border-4 border-white bg-gray-100 text-transparent shadow-lg shadow-gray-400 md:mx-0 md:ml-auto md:w-5/6"
|
||||
src={portraitImage}
|
||||
alt="Portrait of Mikkel"
|
||||
/>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
<footer class="mb-12 mt-4 flex justify-center">
|
||||
<p class="text-xs text-gray-400">
|
||||
Built with
|
||||
<Link href="https://astro.build/" target="_blank">Astro</Link>
|
||||
and
|
||||
<Link href="https://tailwindcss.com/" target="_blank">Tailwind CSS</Link>.
|
||||
</p>
|
||||
</footer>
|
||||
</RootLayout>
|
||||
|
|
|
|||
5
svelte.config.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { vitePreprocess } from '@astrojs/svelte';
|
||||
|
||||
export default {
|
||||
preprocess: vitePreprocess(),
|
||||
};
|
||||
|
|
@ -2,7 +2,16 @@
|
|||
export default {
|
||||
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
|
||||
theme: {
|
||||
fontFamily: {
|
||||
sans: "'Nunito', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'",
|
||||
serif:
|
||||
"'Source Serif Pro', ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif",
|
||||
mono: "Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",
|
||||
},
|
||||
extend: {},
|
||||
},
|
||||
future: {
|
||||
hoverOnlyWhenSupported: true,
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
|
|
|
|||