Skip to content

Commit

Permalink
Add Day 15, improve responsive & switcher
Browse files Browse the repository at this point in the history
  • Loading branch information
WarningImHack3r committed May 1, 2024
1 parent b0ac473 commit e41bc40
Show file tree
Hide file tree
Showing 9 changed files with 267 additions and 30 deletions.
8 changes: 1 addition & 7 deletions src/lib/components/Snowflakes.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,4 @@

<svelte:window on:resize={debounceResize} />

<canvas
aria-hidden="true"
bind:this={snowflakes}
{width}
{height}
class="pointer-events-none fixed inset-0 -z-10 h-screen w-screen"
></canvas>
<canvas aria-hidden="true" bind:this={snowflakes} {width} {height} class={$$props.class}></canvas>
33 changes: 33 additions & 0 deletions src/lib/components/days/2023/Day15.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="160 110 170 220"
width="200"
height="230"
class={$$props.class}
{...$$props}
>
<ellipse
style="stroke: currentColor; fill: none; stroke-width: 5px;"
cx="250"
cy="200"
rx="85"
ry="85"
/>
<foreignObject x="163" y="112.5" width="174.5" height="175">
<slot />
</foreignObject>
<rect
x="180"
y="265"
width="140"
height="20"
style="stroke: currentColor; stroke-width: 5px; stroke-linejoin: round;"
/>
<rect
x="170"
y="285"
width="160"
height="35"
style="stroke: currentColor; stroke-width: 5px; stroke-linejoin: round;"
/>
</svg>
35 changes: 35 additions & 0 deletions src/lib/components/ui/checkbox/checkbox.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script lang="ts">
import { Checkbox as CheckboxPrimitive } from "bits-ui";
import Check from "lucide-svelte/icons/check";
import Minus from "lucide-svelte/icons/minus";
import { cn } from "$lib/utils.js";
type $$Props = CheckboxPrimitive.Props;
type $$Events = CheckboxPrimitive.Events;
let className: $$Props["class"] = undefined;
export let checked: $$Props["checked"] = false;
export { className as class };
</script>

<CheckboxPrimitive.Root
class={cn(
"peer box-content h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[disabled=true]:opacity-50",
className
)}
bind:checked
{...$$restProps}
on:click
>
<CheckboxPrimitive.Indicator
class={cn("flex h-4 w-4 items-center justify-center text-current")}
let:isChecked
let:isIndeterminate
>
{#if isChecked}
<Check class="h-3.5 w-3.5" />
{:else if isIndeterminate}
<Minus class="h-3.5 w-3.5" />
{/if}
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
6 changes: 6 additions & 0 deletions src/lib/components/ui/checkbox/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Root from "./checkbox.svelte";
export {
Root,
//
Root as Checkbox,
};
35 changes: 22 additions & 13 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
<title>Advent of Svelte {$page.route.id?.split("/")[1]} | WarningImHack3r</title>
</svelte:head>

<Snowflakes />
<Snowflakes class="pointer-events-none fixed inset-0 -z-10 h-screen w-screen" />
<ModeWatcher />
<Toaster closeButton />
<header
Expand All @@ -102,7 +102,7 @@
<!-- Left part -->
<a href="/" class="flex items-center gap-2">
<img src="https://advent.sveltesociety.dev/favicon.png" alt="Advent of Svelte" class="h-8" />
<div class="hidden xs:block">
<div class="hidden text-nowrap xs:block">
<h2 class="font-semibold xs:text-xl">Advent of Svelte</h2>
<h3 class="text-xs text-muted-foreground">by WarningImHack3r</h3>
</div>
Expand All @@ -129,27 +129,36 @@
<DropdownMenu.Content align="start">
<DropdownMenu.RadioGroup bind:value={selectedYear}>
{#each data.years as { year, components }}
{@const progressPercentage = (components / maxComponents) * 100}
<DropdownMenu.RadioItem
class={"flex cursor-pointer flex-col items-start [&>*:first-child]:top-2 [&>*:not(:nth-child(2))]:z-10" +
class={"group flex cursor-pointer flex-col items-start [&>*:first-child]:top-[0.7rem] [&>*:not(:nth-child(2))]:z-10" +
(components > 0 && components < maxComponents
? " transition-colors duration-300"
? " data-[highlighted]:bg-transparent"
: "")}
value={year}
on:click={() => goto(`/${year}`)}
>
<div
class={"absolute inset-0 rounded-sm" +
(components > 0 && components < maxComponents ? " bg-accent/75" : "")}
style="width: {(components / maxComponents) * 100}%"
></div>
<span>{year}</span>
<div class="absolute inset-0">
{#if components > 0 && components < maxComponents}
<div
class="h-full w-[var(--width)] rounded-sm bg-accent/75 transition-[width,_background-color] group-hover:w-full group-hover:bg-accent"
style="--width: {progressPercentage}%"
></div>
<div
class="absolute inset-0 flex items-center justify-end pr-1 text-4xl font-light text-muted-foreground/15 transition-opacity duration-300 group-hover:opacity-0"
>
{Math.ceil(progressPercentage)}%
</div>
{/if}
</div>
<span class="text-base font-semibold">{year}</span>
<span class="text-muted-foreground">
{#if components === maxComponents}
{#if components >= maxComponents}
Completed!
{:else if components === 0}
Not started
{:else}
Progress: {components} / {maxComponents}
<span class="font-semibold">Progress:</span> {components} / {maxComponents}
{/if}
</span>
</DropdownMenu.RadioItem>
Expand Down Expand Up @@ -241,7 +250,7 @@
target="_blank"
rel="noreferrer"
variant="ghost"
class="aspect-square p-0"
class="aspect-square p-0 max-sm:hidden"
>
<img src="/github.svg" alt="GitHub" class="size-5 dark:invert" />
<span class="sr-only">GitHub</span>
Expand Down
12 changes: 6 additions & 6 deletions src/routes/2023/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { page } from "$app/stores";
import ChevronRight from "lucide-svelte/icons/chevron-right";
import ScrollText from "lucide-svelte/icons/scroll-text";
import Paintbrush from "lucide-svelte/icons/paintbrush";
import { Button } from "$lib/components/ui/button";
import * as Tabs from "$lib/components/ui/tabs";
import Day1 from "$lib/components/days/2023/Day1.svelte";
Expand All @@ -24,15 +24,15 @@
let currentDashboard: keyof typeof dashboards = "santa";
</script>

<div class="container py-8">
<div class="flex flex-col items-start justify-between gap-4 xs:flex-row xs:items-center">
<div class="container my-8">
<div class="flex items-center justify-between gap-4">
<h2 class="text-3xl font-bold tracking-tight">
<span class="text-primary">{dashboards[currentDashboard]}</span>
Dashboard
</h2>
<Button href="{$page.route.id ?? ''}/card-creator" class="group ml-auto xs:ml-0">
<ScrollText class="mr-2 size-6" />
<span class="hidden sm:block">Create your Christmas card</span>
<Button href={$page.url + "/diy"} class="group ml-auto xs:ml-0">
<Paintbrush class="mr-2 size-6" />
<span class="hidden sm:block">DIYs</span>
<ChevronRight
class="ml-2 size-4 transition-transform duration-300 group-hover:translate-x-1"
/>
Expand Down
61 changes: 61 additions & 0 deletions src/routes/2023/diy/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<script lang="ts">
import { page } from "$app/stores";
import type { Component } from "lucide-svelte";
import ChevronRight from "lucide-svelte/icons/chevron-right";
import ScrollText from "lucide-svelte/icons/scroll-text";
import Snowflake from "lucide-svelte/icons/snowflake";
import { Button } from "$lib/components/ui/button";
import { Separator } from "$lib/components/ui/separator";
import * as Card from "$lib/components/ui/card";
type Diy = {
icon: typeof Component;
name: string;
description: string;
url: string;
};
const diys: Diy[] = [
{
icon: ScrollText,
name: "Christmas card creator",
description: "Create your own Christmas card and send it to Santa!",
url: "/card-creator"
},
{
icon: Snowflake,
name: "Snow globe creator",
description: "Create your snow globe you can share with your friends and family.",
url: "/snow-globe-creator"
}
];
</script>

<div class="container my-16 max-w-4xl">
<h2 class="text-3xl font-bold tracking-tight">
<span class="text-primary">DIY</span>s
</h2>
<Card.Root class="mt-4 pt-6">
<Card.Content>
<ul>
{#each diys as diy, index}
<li class="flex flex-col justify-between gap-4 sm:flex-row">
<div class="flex gap-6">
<svelte:component this={diy.icon} class="size-12 min-w-8 text-primary" />
<div class="flex flex-col">
<h4 class="text-lg font-semibold">{diy.name}</h4>
<p class="text-muted-foreground">{diy.description}</p>
</div>
</div>
<Button href={$page.url + diy.url} variant="outline" class="ml-auto self-center">
Visit
<ChevronRight class="ml-2 size-4" />
</Button>
</li>
{#if index < diys.length - 1}
<Separator class="my-6" />
{/if}
{/each}
</ul>
</Card.Content>
</Card.Root>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
element.innerHTML = `<img src="${data.item.image}" alt="${data.item.name}" class="h-full" />`;
break;
case "text":
element.innerHTML = `<textarea placeholder="Enter your text here" class="h-full w-full resize-none rounded-2xl bg-transparent p-2" />`;
element.innerHTML = `<textarea placeholder="Enter your text here" class="size-full resize-none rounded-2xl bg-transparent p-2" />`;
break;
}
}
Expand Down Expand Up @@ -232,7 +232,7 @@

<div class="container my-8">
<Card.Root>
<Card.Header class="flex flex-row items-center gap-4">
<Card.Header class="flex flex-row items-center gap-4 space-y-0">
<Tooltip.Root>
<Tooltip.Trigger asChild let:builder>
<Button builders={[builder]} size="icon" href="." class="mr-6">
Expand Down Expand Up @@ -337,12 +337,12 @@
textAreaFocused(target);
}}
on:focusout={textAreaUnfocused}
class="h-full w-full resize-none rounded-2xl bg-transparent p-2"
class="size-full resize-none rounded-2xl bg-transparent p-2"
/>
{/if}
<!--{:else}-->
<!-- DEBUG -->
<!-- <div class="h-full w-full rounded-full bg-black" />-->
<!-- <div class="size-full rounded-full bg-black" />-->
{/if}
</div>
{/each}
Expand Down
99 changes: 99 additions & 0 deletions src/routes/2023/diy/snow-globe-creator/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<script lang="ts">
import ChevronLeft from "lucide-svelte/icons/chevron-left";
import Snowflake from "lucide-svelte/icons/snowflake";
import Snowflakes from "$lib/components/Snowflakes.svelte";
import Day15 from "$lib/components/days/2023/Day15.svelte";
import { Button } from "$lib/components/ui/button";
import { Checkbox } from "$lib/components/ui/checkbox";
import { Label } from "$lib/components/ui/label";
import * as Card from "$lib/components/ui/card";
import * as Tooltip from "$lib/components/ui/tooltip";
type Image = {
src: string;
alt: string;
show: boolean;
};
const imagesToShow: Image[] = [
{
src: "https://www.freeiconspng.com/uploads/snowman-png-29.png",
alt: "Snowman",
show: true
},
{
src: "https://www.freeiconspng.com/uploads/christmas-tree-icon-0.png",
alt: "Christmas tree",
show: false
},
{
src: "https://www.freeiconspng.com/uploads/transparent-santa-claus-2.png",
alt: "Santa Claus",
show: false
}
];
let borderHex = "#000000";
let fillHex = "#ffffff";
</script>

<div class="container my-8">
<Card.Root>
<Card.Header class="flex flex-row items-center gap-4 space-y-0">
<Tooltip.Root>
<Tooltip.Trigger asChild let:builder>
<Button builders={[builder]} size="icon" href="." class="mr-6">
<ChevronLeft />
</Button>
</Tooltip.Trigger>
<Tooltip.Content>Back to the dashboard</Tooltip.Content>
</Tooltip.Root>
<Snowflake class="text-primary" />
<div class="flex flex-col">
<Card.Title>Snow Globe Creator</Card.Title>
<Card.Description
>Create your snow globe you can share with your friends and family.</Card.Description
>
</div>
</Card.Header>
<Card.Content class="flex flex-col gap-8">
<!-- Globe -->
<Day15 class="relative mx-auto h-96 w-[22rem]" fill={fillHex} color={borderHex}>
<Snowflakes class="size-full rounded-full" />
<div class="absolute inset-0 mb-6 flex items-end justify-center">
{#each imagesToShow as { src, alt, show }}
{#if show}
<img {src} {alt} class="h-12 align-bottom" />
{/if}
{/each}
</div>
</Day15>
<!-- Settings -->
<section class="flex flex-col gap-4">
<h2 class="text-2xl">Settings</h2>
<div class="flex flex-col gap-4">
<div class="flex items-center gap-4">
<span class="font-semibold">Figures to show:</span>
{#each imagesToShow as { alt, show }, index}
<div class="flex items-center space-x-2">
<Checkbox id={index.toString()} bind:checked={show} />
<Label for={index.toString()}>{alt}</Label>
</div>
{/each}
</div>
<div class="flex items-center gap-4">
<span class="font-semibold">Border color:</span>
{#if borderHex}
<input type="color" bind:value={borderHex} />
{/if}
</div>
<div class="flex items-center gap-4">
<span class="font-semibold">Fill color:</span>
{#if fillHex}
<input type="color" bind:value={fillHex} />
{/if}
</div>
</div>
</section></Card.Content
>
</Card.Root>
</div>

0 comments on commit e41bc40

Please sign in to comment.