Update description

This commit is contained in:
Andras Schmelczer 2026-05-24 21:00:03 +01:00
parent f863588060
commit 79638d5fa4
5 changed files with 254 additions and 59 deletions

5
assets/icons/close.svg Normal file
View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path
d="M6.4 5 12 10.6 17.6 5 19 6.4 13.4 12 19 17.6 17.6 19 12 13.4 6.4 19 5 17.6 10.6 12 5 6.4z"
/>
</svg>

After

Width:  |  Height:  |  Size: 179 B

View file

@ -11,7 +11,7 @@
<meta name="author" content="Andras Schmelczer" />
<meta
name="description"
content="Tend it while you can. The garden returns to weather either way. A WebGPU drawing toy in your browser."
content="Plant colour, fold gestures with mirrors, and watch small agents turn each brushstroke into a shifting WebGPU garden."
/>
<link rel="canonical" href="https://schmelczer.dev/fleeting/" />
@ -22,7 +22,7 @@
<meta property="og:locale" content="en_US" />
<meta
property="og:description"
content="Tend it while you can. The garden returns to weather either way. A WebGPU drawing toy in your browser."
content="Plant colour, fold gestures with mirrors, and watch small agents turn each brushstroke into a shifting WebGPU garden."
/>
<meta property="og:url" content="https://schmelczer.dev/fleeting/" />
<meta property="og:image" content="https://schmelczer.dev/fleeting/og-image.jpg" />
@ -35,7 +35,7 @@
<meta name="twitter:title" content="Fleeting Garden" />
<meta
name="twitter:description"
content="Tend it while you can. The garden returns to weather either way. A WebGPU drawing toy in your browser."
content="Plant colour, fold gestures with mirrors, and watch small agents turn each brushstroke into a shifting WebGPU garden."
/>
<meta name="twitter:image" content="https://schmelczer.dev/fleeting/og-image.jpg" />
<meta name="twitter:image:alt" content="Fleeting Garden social preview image." />
@ -46,7 +46,7 @@
"@type": "WebApplication",
"name": "Fleeting Garden",
"url": "https://schmelczer.dev/fleeting/",
"description": "Tend it while you can. The garden returns to weather either way. A WebGPU drawing toy in your browser.",
"description": "Plant colour, fold gestures with mirrors, and watch small agents turn each brushstroke into a shifting WebGPU garden.",
"image": "https://schmelczer.dev/fleeting/og-image.jpg",
"applicationCategory": "DesignApplication",
"operatingSystem": "Any",
@ -118,35 +118,47 @@
id="info-panel"
class="hidden info-page"
role="region"
aria-label="About panel"
aria-labelledby="info-panel-title"
aria-hidden="true"
tabindex="-1"
inert
>
<section>
<h1>Fleeting Garden</h1>
<p>
<div class="info-page__content">
<header class="info-page__header">
<span class="info-page__mark" aria-hidden="true"></span>
<div class="info-page__heading">
<p class="info-page__eyebrow">About</p>
<h2 id="info-panel-title">Fleeting Garden</h2>
</div>
<button
class="info-page__close"
data-control="info-close"
type="button"
aria-label="Close about panel"
title="Close"
></button>
</header>
<p class="info-page__lede">
A garden is what we tend; the wild is what we get the moment we look away.
Both happen here at once. Your strokes plant colour, small agents follow them,
branch off, and slowly rewrite the patch you laid down into something you
didn't quite plan.
</p>
<p>
Three swatches plant the line. The eraser carves a clearing. The mirror folds
one gesture into many, like footpaths around a hidden well.
</p>
<p>
Switch vibes to change the season; your shapes stay, the light moves. Add or
quiet the piano. Restart when you want a fresh field. Take a snapshot if you
want to keep one particular instant of weather.
</p>
<p>
<ul class="info-page__notes">
<li>Three swatches plant the line; the eraser carves a clearing.</li>
<li>The mirror folds one gesture into many.</li>
<li>The arrows change the season.</li>
</ul>
<p class="info-page__meta">
Built with WebGPU, running locally in your browser. More of my work at
<a href="https://schmelczer.dev" target="_blank" rel="noopener"
>schmelczer.dev</a
>.
</p>
</section>
</div>
</section>
<div class="toolbar-row" role="toolbar" aria-label="Garden toolbar">

View file

@ -22,7 +22,7 @@ export const appConfig = {
audio: createGardenAudioConfig(),
analytics: {
autoCapturePageviews: true,
domain: 'fleeting.garden',
domain: 'schmelczer.dev/fleeting',
endpoint: 'https://stats.schmelczer.dev/status',
logging: import.meta.env.DEV,
},

View file

@ -71,6 +71,10 @@ const main = async () => {
HTMLButtonElement
);
const infoButton = queryRequiredElement('[data-control="info"]', HTMLButtonElement);
const infoCloseButton = queryRequiredElement(
'[data-control="info-close"]',
HTMLButtonElement
);
const infoElement = queryRequiredElement('.info-page', HTMLElement);
const fullScreenButton = queryRequiredElement(
'[data-control="full-screen"]',
@ -113,6 +117,7 @@ const main = async () => {
};
const infoPageHandler = new CollapsiblePanelAnimator(infoButton, infoElement, aside);
infoCloseButton.addEventListener('click', () => infoPageHandler.close());
new MenuHider(
aside,
() =>

View file

@ -1,24 +1,28 @@
@use 'mixins' as *;
html > body > aside.control-dock > .info-page {
width: min(calc(100vw - 1rem), 560px);
max-height: min(58vh, 520px);
max-height: min(58dvh, 520px);
width: min(100%, 520px);
max-height: min(62vh, 480px);
max-height: min(62dvh, 480px);
margin: 0 auto 10px;
overflow-x: hidden;
overflow-y: auto;
border: 1px solid rgb(255 255 255 / 78%);
overscroll-behavior: contain;
touch-action: pan-y;
border: 1px solid rgb(255 255 255 / 46%);
border-radius: 8px;
background:
linear-gradient(180deg, rgb(255 255 255 / 97%), rgb(243 247 239 / 96%)),
rgb(255 255 255);
color: rgb(24 30 27);
linear-gradient(180deg, rgb(252 255 249 / 94%), rgb(234 241 232 / 91%)),
rgb(249 252 247 / 92%);
color: rgb(18 28 24);
box-shadow:
0 20px 54px rgb(0 0 0 / 38%),
0 2px 12px rgb(0 0 0 / 22%);
backdrop-filter: blur(12px);
inset 0 1px 0 rgb(255 255 255 / 58%),
0 16px 42px rgb(0 0 0 / 30%),
0 2px 10px rgb(0 0 0 / 18%);
backdrop-filter: blur(16px) saturate(118%);
scrollbar-width: thin;
scrollbar-color: var(--main-color) transparent;
scrollbar-color: rgb(69 98 88 / 62%) transparent;
-webkit-overflow-scrolling: touch;
transition:
max-height var(--transition-time-long),
opacity var(--transition-time-long),
@ -32,47 +36,181 @@ html > body > aside.control-dock > .info-page {
}
&::-webkit-scrollbar-thumb {
background-color: var(--main-color);
background-color: rgb(69 98 88 / 62%);
border-radius: 8px;
}
&:focus-visible {
outline: 2px solid white;
outline: 2px solid rgb(17 56 45);
outline-offset: 3px;
box-shadow:
0 0 0 5px rgb(255 255 255 / 68%),
inset 0 1px 0 rgb(255 255 255 / 58%),
0 16px 42px rgb(0 0 0 / 30%),
0 2px 10px rgb(0 0 0 / 18%);
}
> section {
.info-page__content {
display: flex;
flex-direction: column;
gap: 0.85rem;
padding: var(--normal-margin);
h1 {
margin-bottom: 0;
color: rgb(16 24 20);
font-size: 2rem;
line-height: 1.1;
padding: 18px 20px 16px;
}
p {
max-width: 54ch;
.info-page__header {
display: flex;
align-items: center;
gap: 0.7rem;
padding-bottom: 0.1rem;
}
.info-page__heading {
min-width: 0;
}
.info-page__mark {
display: grid;
flex: 0 0 auto;
place-items: center;
width: 1.8rem;
height: 1.8rem;
border: 1px solid rgb(42 74 65 / 24%);
border-radius: 8px;
background:
linear-gradient(180deg, rgb(255 255 255 / 74%), rgb(217 231 222 / 70%)),
rgb(232 240 235);
box-shadow:
inset 0 1px 0 rgb(255 255 255 / 76%),
0 5px 14px rgb(21 44 39 / 12%);
&::before {
content: '';
width: 1rem;
height: 1rem;
background: rgb(19 57 48);
mask: url('../../assets/icons/info.svg') center / contain no-repeat;
}
}
.info-page__close {
position: relative;
flex: 0 0 auto;
width: 2rem;
height: 2rem;
margin-left: auto;
border: 1px solid rgb(34 57 50 / 18%);
border-radius: 8px;
background: rgb(255 255 255 / 36%);
cursor: pointer;
transition:
background-color var(--transition-time),
border-color var(--transition-time),
transform var(--transition-time);
&::before {
content: '';
position: absolute;
inset: 0;
width: 0.9rem;
height: 0.9rem;
margin: auto;
background: rgb(28 45 39);
mask: url('../../assets/icons/close.svg') center / contain no-repeat;
}
&:hover {
border-color: rgb(34 57 50 / 30%);
background: rgb(255 255 255 / 64%);
transform: translateY(-1px);
}
&:focus-visible {
outline: 2px solid rgb(17 56 45);
outline-offset: 2px;
box-shadow: 0 0 0 4px rgb(255 255 255 / 72%);
}
}
.info-page__eyebrow {
margin-bottom: 0.12rem;
color: rgb(73 91 85);
font-size: 0.68rem;
font-weight: 700;
line-height: 1.2;
letter-spacing: 0;
text-transform: uppercase;
}
h2 {
overflow-wrap: break-word;
margin-bottom: 0;
color: rgb(9 21 17);
font-size: 1.12rem;
font-weight: 700;
line-height: 1.18;
}
.info-page__lede,
.info-page__notes,
.info-page__meta {
max-width: 56ch;
overflow-wrap: break-word;
color: rgb(25 35 32);
font-size: 0.95rem;
line-height: 1.56;
}
.info-page__lede,
.info-page__meta {
margin-bottom: 0;
color: rgb(42 48 45);
font-size: 1.1rem;
line-height: 1.65;
hyphens: auto;
}
.info-page__notes {
display: grid;
gap: 0.45rem;
margin: 0.1rem 0;
padding-left: 1.1rem;
list-style: disc;
li {
padding-left: 0.1rem;
}
li::marker {
color: rgb(25 108 82);
font-size: 0.85em;
}
}
.info-page__meta {
display: flex;
flex-wrap: wrap;
gap: 0.35rem;
align-items: baseline;
margin-top: 0.2rem;
padding-top: 0.75rem;
border-top: 1px solid rgb(43 66 57 / 16%);
color: rgb(67 82 77);
font-size: 0.8rem;
line-height: 1.45;
}
a {
color: rgb(0 84 120);
font-weight: 400;
color: rgb(0 83 105);
font-weight: 700;
text-decoration-color: rgb(0 83 105 / 34%);
text-underline-offset: 0.18em;
&:hover {
text-decoration-color: currentColor;
}
&:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}
}
}
&.hidden {
max-height: 0;
@ -81,16 +219,51 @@ html > body > aside.control-dock > .info-page {
opacity: 0;
pointer-events: none;
box-shadow: none;
transform: translateY(8px);
transform: translateY(6px) scale(0.985);
visibility: hidden;
}
@include on-small-screen {
max-height: min(54vh, 500px);
max-height: min(54dvh, 500px);
width: min(100%, 520px);
max-height: min(58vh, 500px);
max-height: min(58dvh, 500px);
> section {
padding: var(--small-margin);
.info-page__content {
gap: 0.75rem;
padding: 14px;
}
.info-page__lede,
.info-page__notes {
font-size: 0.95rem;
line-height: 1.52;
}
.info-page__meta {
font-size: 0.875rem;
line-height: 1.45;
}
}
@media (max-height: 420px) {
max-height: min(
58vh,
max(
10rem,
calc(
100vh - 168px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px)
)
)
);
max-height: min(
58dvh,
max(
10rem,
calc(
100dvh -
168px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px)
)
)
);
}
}