Compare commits

...

2 Commits

@ -4,6 +4,7 @@
type Props = {
color?: string;
title?: string;
titleElement?: Snippet;
margin?: "slim" | "medium" | "wide";
children: Snippet;
};
@ -11,6 +12,7 @@
const {
color = "primary",
title,
titleElement,
margin = "medium",
children,
}: Props = $props();
@ -18,14 +20,16 @@
<div
class={["box", `margin-${margin}`].join(" ")}
class:with-title={title}
class:with-title={title || titleElement}
style={`--box-color: var(--color-${color})`}
>
{#if title}
{#if title || titleElement}
<div class="box-title">
<div class="border-left"></div>
<div class="left-end-cap"></div>
<span class="title-label">{title}</span>
<span class="title-label">
{#if title}{title}{:else if titleElement}{@render titleElement()}{/if}
</span>
<div class="right-end-cap"></div>
<div class="border-right"></div>
</div>
@ -101,6 +105,7 @@
text-shadow: 0 0 20px var(--box-color);
z-index: 99;
white-space: nowrap;
display: inline;
}
.border-left {

@ -0,0 +1,62 @@
<script lang="ts">
import type { Snippet } from "svelte";
type Props = {
children?: Snippet;
onclick?: (...args: any) => void;
color?: string;
pageBackground?: string;
label?: string;
};
const {
label,
children,
onclick,
color = "primary",
pageBackground = "background",
}: Props = $props();
</script>
<button
class="button"
{onclick}
style={`--button-color: var(--color-${color}); --button-page-background: var(--color-${pageBackground})`}
>
<span class="button-label">{label}</span>
{#if children}
{@render children()}
{/if}
</button>
<style lang="scss">
@import "$lib/styles/mixins.scss";
@layer component {
.button {
@include lighten-color(--button-border-color, var(--button-color));
color: transparent;
border: none !important;
background: var(--button-color) !important;
border-radius: 7.5px;
padding: 0.25em 0.5em;
color: black;
mix-blend-mode: screen;
box-shadow: 0 0 10px var(--button-color);
text-shadow: inset 0 0 10px var(--button-color);
transition-duration: 0.25s;
&:hover {
cursor: pointer;
box-shadow: 0 0 20px var(--button-color);
color: #222;
}
}
.button-label {
font-size: 1.5em;
font-weight: bold;
}
}
</style>

@ -0,0 +1,109 @@
<script lang="ts">
import type { Snippet } from "svelte";
import Box from "../atoms/Box.svelte";
import Heading from "../atoms/Heading.svelte";
type Props = {
children: Snippet;
title: string;
};
const { children, title }: Props = $props();
let expanded = $state(false);
function toggleExpanded() {
expanded = !expanded;
}
</script>
{#if expanded}
<Box color="cyan">
{#snippet titleElement()}
<button class="hidden-button info-collapse" onclick={toggleExpanded}>
<span class="arrow up-arrow"></span><span class="info-text">Info</span>
</button>
{/snippet}
<Heading depth={2}>{title}</Heading>
{@render children()}
</Box>
{:else}
<button class="hidden-button info-expand" onclick={toggleExpanded}>
<span class="arrow collapsed-arrow">&gt;</span><span class="info-text">
Info: {title}
</span>
</button>
{/if}
<style lang="scss">
@layer component {
.hidden-button {
border: none !important;
background: inherit !important;
color: inherit !important;
margin: none !important;
padding: none !important;
}
.arrow {
font-family: var(--font-monospace);
font-weight: bold;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: cubic-bezier();
}
.info-expand {
font-size: 1.5em;
cursor: pointer;
.info-text {
font-family: var(--font-primary);
margin: 0.2em 0;
text-decoration: underline 0.2em var(--color-cyan);
}
.collapsed-arrow {
margin-right: 0.5em;
position: relative;
transition-duration: 1s;
color: var(--color-cyan);
}
}
.info-collapse {
transform: translateY(-0.1em);
display: inline !important;
cursor: pointer;
font-size: 1.2em;
.up-arrow {
position: relative;
top: 0.1em;
margin-right: 0.5em;
}
.info-text {
font-family: var(--font-primary);
margin: 0.2em 0;
}
&:hover {
.up-arrow {
animation-name: pull-up;
}
}
}
}
@keyframes pull-up {
0% {
top: 0.1em;
}
50% {
top: -0.3em;
}
100% {
top: 0.1em;
}
}
</style>

@ -4,6 +4,7 @@
import Box from "../atoms/Box.svelte";
import Markdown from "../molecules/Markdown.svelte";
import Image from "../molecules/Image.svelte";
import Infobox from "../molecules/Infobox.svelte";
type Props = {
content: BlogPostContentEntry;
@ -13,16 +14,14 @@
</script>
<div class="post-content">
{#if content.__component === "content.text-markdown"}
{#if content.type === "paragraph"}
<Box>
<Markdown markdown={content.value} />
</Box>
{:else if content.type === "infobox"}
<Box color="cyan" title="Info">
<Markdown markdown={content.value} />
</Box>
{/if}
{#if content.__component === "content.paragraph" || content.__component === "content.text-markdown"}
<Box>
<Markdown markdown={content.value} />
</Box>
{:else if content.__component === "content.infobox"}
<Infobox title={content.title}>
<Markdown markdown={content.value} />
</Infobox>
{:else if content.__component === "content.image"}
{@const imageData = content.value.data.attributes}
<Image

@ -37,9 +37,10 @@ type BlogPostContentTemplate<S, T> = {
export type BlogPostContentEntry =
| BlogPostContentTemplate<
"content.text-markdown",
{ value: string; type: "paragraph" | "infobox" }
"content.paragraph" | "content.text-markdown",
{ value: string }
>
| BlogPostContentTemplate<"content.infobox", { value: string; title: string }>
| BlogPostContentTemplate<"content.image", { value: { data: StrapiImage } }>;
export async function getPosts(locale = "all"): Promise<BlogPostTeaser[]> {

@ -34,7 +34,6 @@ export default async function fetchApi<T>({
if (query) {
url.search = qs.stringify(query);
}
console.log({ url });
const res = await fetch(url.toString(), {
headers: {
Authorization: `Bearer ${STRAPI_CMS_API_KEY}`,

Loading…
Cancel
Save