Compare commits

...

6 commits

Author SHA1 Message Date
Mihkel Martin Kasterpalu
65d11655a0 Bump Packages 2025-01-31 20:26:54 +02:00
Mihkel Martin Kasterpalu
d692f50ade Add email to footer 2025-01-31 20:20:45 +02:00
Mihkel Martin Kasterpalu
aa70f3d509 Adjust mobile styling 2025-01-31 20:20:01 +02:00
Mihkel Martin Kasterpalu
dad4698a0a Adjust heading spacing and title styling 2025-01-31 20:08:32 +02:00
Mihkel Martin Kasterpalu
196a046567 Adjust heading spacing 2025-01-31 19:52:08 +02:00
Mihkel Martin Kasterpalu
efdb203ac8 Revert "Bump packages, migrate to tailwind 4"
This reverts commit fd0e12b665.
2025-01-31 19:51:25 +02:00
16 changed files with 768 additions and 543 deletions

View file

@ -21,10 +21,9 @@
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/postcss": "^4.0.1",
"@tailwindcss/vite": "^4.0.1",
"@types/spotify-web-api-node": "^5.0.11",
"bits-ui": "1.0.0-next.80",
"autoprefixer": "^10.4.20",
"bits-ui": "1.0.0-next.82",
"clsx": "^2.1.1",
"eslint": "^9.19.0",
"eslint-config-prettier": "^10.0.1",
@ -33,13 +32,13 @@
"lucide-svelte": "^0.474.0",
"prettier": "^3.4.2",
"prettier-plugin-svelte": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.11",
"svelte": "^5.19.6",
"prettier-plugin-tailwindcss": "^0.6.10",
"svelte": "^5.19.1",
"svelte-check": "^4.1.4",
"svelte-dnd-action": "^0.9.56",
"tailwind-merge": "^3.0.1",
"svelte-dnd-action": "^0.9.55",
"tailwind-merge": "^2.6.0",
"tailwind-variants": "^0.3.1",
"tailwindcss": "^4.0.1",
"tailwindcss": "^3.4.17",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.7.3",
"typescript-eslint": "^8.22.0",

1093
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
export default {
plugins: {
'@tailwindcss/postcss': {}
tailwindcss: {},
autoprefixer: {}
}
};

View file

@ -1,42 +1,6 @@
@import 'tailwindcss';
@config '../tailwind.config.ts';
/*
The default border color has changed to `currentColor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
@utility shadow-sharp {
box-shadow: hsl(var(--primary)) 4px 3px 0px;
&:hover {
box-shadow: hsl(var(--primary)) 2px 1px 0px;
translate: 2px 1px;
}
&.pressed {
box-shadow: hsl(var(--primary)) 2px 1px 0px;
translate: 2px 1px;
}
}
@utility container {
margin-inline: auto;
padding-inline: 2rem;
}
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
@ -109,3 +73,20 @@
@apply bg-background text-foreground;
}
}
@layer components {
.shadow-sharp {
box-shadow: hsl(var(--primary)) 4px 3px 0px;
}
button.shadow-sharp,
a.shadow-sharp {
&:hover {
box-shadow: hsl(var(--primary)) 2px 1px 0px;
translate: 2px 1px;
}
&.pressed {
box-shadow: hsl(var(--primary)) 2px 1px 0px;
translate: 2px 1px;
}
}
}

View file

@ -18,7 +18,7 @@
<AlertDialogPrimitive.Content
bind:ref
class={cn(
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:rounded-lg',
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
className
)}
{...restProps}

View file

@ -1,14 +1,14 @@
<script lang="ts" module>
import { type VariantProps, tv } from 'tailwind-variants';
export const badgeVariants = tv({
base: 'focus:ring-ring inline-flex select-none items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-hidden focus:ring-2 focus:ring-offset-2',
base: 'focus:ring-ring inline-flex select-none items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2',
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/80 border-transparent shadow-sm',
default: 'bg-primary text-primary-foreground hover:bg-primary/80 border-transparent shadow',
secondary:
'bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent',
destructive:
'bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent shadow-sm',
'bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent shadow',
outline: 'text-foreground'
}
},

View file

@ -4,14 +4,14 @@
import { type VariantProps, tv } from 'tailwind-variants';
export const buttonVariants = tv({
base: 'focus-visible:ring-ring inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
base: 'focus-visible:ring-ring inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-xs',
default: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm',
outline:
'border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-xs',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-xs',
'border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-sm',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-sm',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline'
},

View file

@ -13,7 +13,7 @@
<div
bind:this={ref}
class={cn('rounded-xl border bg-card text-card-foreground shadow-sm', className)}
class={cn('rounded-xl border bg-card text-card-foreground shadow', className)}
{...restProps}
>
{@render children?.()}

View file

@ -20,7 +20,7 @@
{sideOffset}
{align}
class={cn(
"bg-popover text-popover-foreground z-50 w-64 rounded-md border p-4 shadow-md outline-hidden",
"bg-popover text-popover-foreground z-50 w-64 rounded-md border p-4 shadow-md outline-none",
className
)}
{...restProps}

View file

@ -1,6 +1,7 @@
export const site = {
name: 'Mihkel Martin Kasterpalu',
author: 'Mihkel Martin Kasterpalu',
email: 'mihkel@kasterpalu.ee',
description: 'Portfoolio - Arendaja, Disainer, Muusik, DJ, Ettevõtja.',
image: '/web-app-manifest-512x512.png'
};
@ -8,6 +9,7 @@ export const site = {
export const stuffSite = {
name: 'Kasterpalu Stuff',
author: 'Mihkel Martin Kasterpalu',
email: 'mihkel@kasterpalu.ee',
description:
'Minimängud ja muud huvitavat. Kui mul tekkis lahe idee ja suutsin sellest midagi lahedat arendada siis näed seda ka siin.',
image: '/web-app-manifest-512x512.png'

View file

@ -10,10 +10,12 @@
import Moon from 'lucide-svelte/icons/moon';
import LaptopMinimal from 'lucide-svelte/icons/laptop-minimal';
import { site } from '$lib/config';
import { onMount } from 'svelte';
let { children } = $props();
let theme: string = $state('system');
let email: string | undefined = $state(undefined);
const cycleTheme = () => {
if (theme === 'dark') {
@ -27,6 +29,10 @@
setMode('dark');
}
};
onMount(() => {
email = site.email;
});
</script>
<svelte:head>
@ -45,28 +51,42 @@
<Button onclick={() => cycleTheme()} variant="ghost" size="icon" class="h-12 w-12">
{#if theme === 'dark'}
<Moon class="h-6! w-6!" />
<Moon class="!h-6 !w-6" />
{:else if theme === 'light'}
<Sun class="h-6! w-6!" />
<Sun class="!h-6 !w-6" />
{:else}
<LaptopMinimal class="h-6! w-6!" />
<LaptopMinimal class="!h-6 !w-6" />
{/if}
<span class="sr-only">Toggle theme</span>
</Button>
</header>
<div class="container relative mt-8 flex flex-col items-center">
<div class="container relative mt-16 flex flex-col items-center">
{@render children()}
</div>
<footer class="container flex w-full justify-center px-8 py-6 text-center">
<footer class="container flex w-full justify-between px-9 py-6">
<a
href="https://koodi.lenn.uk/mihkelmk/minigames"
target="_blank"
class="text-muted-foreground underline underline-offset-4"
class="text-sm text-muted-foreground underline underline-offset-4"
>
saidi kood
</a>
{#if email}
<a
href="mailto://{email}"
target="_blank"
class="text-right text-sm text-muted-foreground underline underline-offset-4"
>
{email}
</a>
{:else}
<p class="text-sm text-muted-foreground">
{'<email_protected>'}
</p>
{/if}
</footer>
</div>

View file

@ -16,8 +16,8 @@
tags: Tag[],
link: string
)}
<div class="mb-16 w-80 space-y-3 md:w-64">
<Image {image} {tags} class="aspect-4/5 object-cover" />
<div class="mb-10 w-72 space-y-3 md:w-60">
<Image {image} {tags} class="aspect-[4/5] object-cover" />
<div class="grid grid-cols-[1fr_auto] items-center text-sm">
<div class="mt-1 pr-4">
<h3 class="text-lg font-medium leading-none">{name}</h3>
@ -40,11 +40,11 @@
<meta property="og:image" content={baseURL + site.image} />
</svelte:head>
<header class="mb-24 flex flex-col items-center text-center font-title">
<header class="mb-16 flex flex-col items-center text-center font-title">
<h1 class="mb-1 scroll-m-20 text-5xl font-extrabold tracking-tight lg:text-6xl">
Hei! Mina olen Mihkel
</h1>
<p class="font-sans text-base text-muted-foreground">
<p class="text-xl font-semibold leading-7 text-muted-foreground">
Peale selle toreda saidi on mul veel palju hobisid
</p>
</header>

View file

@ -16,24 +16,24 @@
<meta property="og:image" content={baseURL + site.image} />
</svelte:head>
<header class="mb-24 flex flex-col items-center text-center font-title">
<header class="flex flex-col items-center text-center font-title">
<h1 class="mb-1 scroll-m-20 text-5xl font-extrabold tracking-tight lg:text-6xl">Vinge värk</h1>
<p class="font-sans text-base leading-7 text-muted-foreground">
<p class="text-xl font-semibold leading-7 text-muted-foreground">
Minu loodud minimängud ja muud huvitavat.
</p>
<p class="font-sans text-base leading-7 text-muted-foreground">
<p class="text-xl font-semibold leading-7 text-muted-foreground">
Aitäh
<a href="https://neal.fun" class="font-medium underline underline-offset-4">neal.fun</a> inspo eest
<a href="https://neal.fun" class="font-bold underline underline-offset-4">neal.fun</a> inspo eest
:)
</p>
</header>
<div
class="mx-auto mb-24 flex w-full flex-wrap items-center justify-center justify-items-center gap-4 gap-x-8 gap-y-8 lg:grid-cols-2"
class="mx-auto mt-20 flex w-full flex-wrap items-center justify-center justify-items-center gap-4 gap-x-8 gap-y-8 lg:grid-cols-2"
>
{#each Object.entries(games) as [href, { image, name }]}
<a
class="shadow-sharp flex aspect-4/1 min-h-20 max-w-sm items-center justify-center rounded-xl border-2 border-current bg-contain bg-no-repeat transition-all {href ===
class="shadow-sharp flex aspect-[4/1] h-16 max-w-sm items-center justify-center rounded-xl border-2 border-current bg-contain bg-no-repeat transition-all md:h-20 {href ===
''
? 'pressed pointer-events-none'
: ''}"

View file

@ -22,13 +22,14 @@
{#snippet clockStage(count: number, index: number, title: string, divider = true)}
<div class="flex flex-col items-center gap-2">
<div
class="card bg-muted ring-foreground/25 h-[2.75rem] overflow-hidden rounded-xl font-mono text-xl ring-3 drop-shadow-md"
class="card h-[2.75rem] overflow-hidden rounded-xl bg-muted font-mono text-xl ring ring-foreground/25 drop-shadow-md"
>
<div
style="translate: 0 calc({index} * -2rem); transition-duration: {index === count - 1
style="translate: 0 calc({index} * -2rem); transition-timing-function: cubic-bezier(.65,.01,.04,.97); transition-duration: {index ===
count - 1
? '600ms'
: '300ms'};"
class="ease-bouncy flex flex-col gap-1 px-4 py-2 transition-transform"
class="flex flex-col gap-1 px-4 py-2 transition-all"
>
{#each { length: count } as _, i}
{@render clockDigit(i)}
@ -36,24 +37,26 @@
</div>
</div>
<p class="text-muted-foreground text-sm">{title}</p>
<p class="text-sm text-muted-foreground">{title}</p>
</div>
{#if divider}
<p class="text-muted-foreground mb-7 block text-center text-lg font-semibold">:</p>
<p class="mb-7 block text-center text-lg font-semibold text-muted-foreground">:</p>
{:else}
<p
class="text-muted-foreground invisible hidden text-center text-lg font-semibold md:visible md:block"
class="invisible hidden text-center text-lg font-semibold text-muted-foreground md:visible md:block"
></p>
{/if}
{/snippet}
<header class="font-title mb-24 flex flex-col items-center text-center">
<header class="mb-24 flex flex-col items-center text-center font-title">
<h1 class="mb-1 scroll-m-20 text-5xl font-extrabold tracking-tight lg:text-6xl">Epochalypse</h1>
<p class="text-muted-foreground text-xl font-semibold">Ära muretse! Sul on veel aega:</p>
<p class="text-xl font-semibold leading-7 text-muted-foreground">
Ära muretse! Sul on veel aega:
</p>
</header>
<main class="w-full max-w-4xl">
<div
class="bg-muted mx-auto grid w-full grid-cols-[auto_auto_auto] items-center justify-center gap-4 rounded-md p-12 md:flex"
class="mx-auto grid w-full grid-cols-[auto_auto_auto] items-center justify-center gap-4 rounded-md bg-muted p-12 md:flex"
>
{@render clockStage(13, timeUntil.years, 'aastat')}
{@render clockStage(13, timeUntil.months, 'kuud', false)}
@ -67,45 +70,45 @@
<Accordion.Item value="item-1">
<Accordion.Trigger>Mis asi see on??</Accordion.Trigger>
<Accordion.Content class="text-md">
<p class="leading-7 not-first:mt-6">
<p class="leading-7 [&:not(:first-child)]:mt-6">
Epochalypse nimeline probleem on sarnane 1990 lõpus toimunud <a
href="https://en.wikipedia.org/wiki/Year_2000_problem"
class="text-primary font-medium underline underline-offset-4">Y2K</a
class="font-medium text-primary underline underline-offset-4">Y2K</a
>-le <br />
Laialdaselt kasutatud süsteem aja ja kuupäeva märkimiseks <strong>saab otsa.</strong>
</p>
<p class="leading-7 not-first:mt-6">
<p class="leading-7 [&:not(:first-child)]:mt-6">
Enamus Linuxi baasiga Operatsioonisüsteeme kasutab aja märkimiseks <a
href="https://en.wikipedia.org/wiki/Unix_time"
class="text-primary font-medium underline underline-offset-4">UNIX aega</a
class="font-medium text-primary underline underline-offset-4">UNIX aega</a
>
- mitu sekundit on möödunud UNIX <i>epoch</i>-ist 00:00:00 19.01.1970 UTC.
</p>
<p class="leading-7 not-first:mt-6">
<p class="leading-7 [&:not(:first-child)]:mt-6">
Neid sekundeid hoitaks <i>signed 32-bit</i> täisarvuna. Selle andmetüübi maksimaalne
väärtus on
<code
class="bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold"
class="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold"
>2<sup>31</sup>-1</code
>. Viimane kuupäev (<code
class="bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold"
class="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold"
>UNIX epoch + 2<sup>31</sup>-1</code
>) on 03:14:07 19.01.2038 UTC.
</p>
<p class="leading-7 not-first:mt-6">
<p class="leading-7 [&:not(:first-child)]:mt-6">
Sekund pärast seda, kui arvutid lisavad ajale sekundi juurde, juhtub <a
href="https://en.wikipedia.org/wiki/Integer_overflow"
class="text-primary font-medium underline underline-offset-4">täisarvu ületäitumine</a
class="font-medium text-primary underline underline-offset-4">täisarvu ületäitumine</a
>
ja aja väärtuseks saab
<code
class="bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold"
class="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold"
>-2<sup>31</sup></code
>. <br />
Arvutid loevad seda kui 20:45:52 13.12.1901 UTC, ehk varaseim võimalik aeg
<a
href="https://en.wikipedia.org/wiki/Unix_time"
class="text-primary font-medium underline underline-offset-4">UNIX aja</a
class="font-medium text-primary underline underline-offset-4">UNIX aja</a
> järgi.
</p>
</Accordion.Content>

View file

@ -41,7 +41,7 @@
>
{#each { length: 3 }}
{#if i < 2}
<Skeleton class="border-primary/5 h-[5rem] w-full rounded-xl border" />
<Skeleton class="h-[5rem] w-full rounded-xl border border-primary/5" />
{:else}
<Skeleton class="aspect-square h-auto max-w-full rounded-xl object-cover" />
{/if}
@ -86,9 +86,9 @@
</AlertDialog.Content>
</AlertDialog.Root>
<header class="font-title mb-12 flex flex-col items-center text-center">
<header class="mb-16 flex flex-col items-center text-center font-title">
<h1 class="mb-1 scroll-m-20 text-5xl font-extrabold tracking-tight lg:text-6xl">Paku biiti</h1>
<p class="text-muted-foreground text-xl font-semibold">
<p class="text-xl font-semibold leading-7 text-muted-foreground">
Lohista kokku õiged albumi <span class="text-red-600 dark:text-red-400">nimed</span>,
<span class="text-purple-600 dark:text-purple-400">artistid</span> ja
<span class="text-blue-600 dark:text-blue-400">pildid</span>.

View file

@ -3,9 +3,17 @@ import type { Config } from 'tailwindcss';
import tailwindcssAnimate from 'tailwindcss-animate';
const config: Config = {
darkMode: ['class', 'dark'],
darkMode: ['class'],
content: ['./src/**/*.{html,js,svelte,ts}'],
safelist: ['dark'],
theme: {
container: {
center: true,
padding: '1rem',
screens: {
'2xl': '1400px'
}
},
extend: {
colors: {
border: 'hsl(var(--border) / <alpha-value>)',
@ -83,11 +91,7 @@ const config: Config = {
'caret-blink': 'caret-blink 1.25s ease-out infinite'
},
transitionTimingFunction: {
default: 'cubic-bezier(0.16, 1, 0.3, 1)',
in: 'cubic-bezier(0.7, 0, 0.84, 0)',
out: 'cubic-bezier(0.16, 1, 0.3, 1)',
'in-out': 'cubic-bezier(0.87, 0, 0.13, 1)',
bouncy: 'cubic-bezier(.65,.01,.04,.97)'
default: 'cubic-bezier(0.16, 1, 0.3, 1)'
}
}
},