203 lines
4.1 KiB
Plaintext
203 lines
4.1 KiB
Plaintext
---
|
|
import CommonLayout from "./CommonLayout.astro";
|
|
import slideColors from "../content/slide-colors.json"
|
|
|
|
export interface Props {
|
|
title: string;
|
|
numberOfSlides?: number;
|
|
}
|
|
|
|
const { title, numberOfSlides } = Astro.props;
|
|
|
|
const prefixedSlideColors = Object.entries(slideColors).reduce<Record<string, any>>((acc, [key, values]) => {
|
|
Object.entries(values).forEach(([subKey, value]) => {
|
|
acc[`${key.toString()}-${subKey.toString()}`] = value;
|
|
});
|
|
return acc;
|
|
}, {});
|
|
---
|
|
|
|
<CommonLayout title={title}>
|
|
<body>
|
|
<aside id="scroll-indicator" role="contentinfo">
|
|
<div id="scroll-indicator-container">
|
|
<span class="indicator"></span>
|
|
{ [...Array(numberOfSlides ?? 4)].map(() => (<span class="shadow"></span>)) }
|
|
</div>
|
|
</aside>
|
|
<slot name="head" />
|
|
<slot />
|
|
</body>
|
|
</CommonLayout>
|
|
|
|
<style is:global>
|
|
@property --text-color {
|
|
syntax: "<color>";
|
|
inherits: true;
|
|
initial-value: #ddd;
|
|
}
|
|
|
|
@property --text-color-dark {
|
|
syntax: "<color>";
|
|
inherits: true;
|
|
initial-value: oklch(from var(--text-color) l c h / 0.8);
|
|
}
|
|
|
|
@property --glass-color {
|
|
syntax: "<color>";
|
|
inherits: true;
|
|
initial-value: hsl(283, 86%, 20%);
|
|
}
|
|
|
|
@property --background-color {
|
|
syntax: "<color>";
|
|
inherits: true;
|
|
initial-value: #0d0117;
|
|
}
|
|
|
|
@property --accent-color {
|
|
syntax: "<color>";
|
|
inherits: true;
|
|
initial-value: hsl(282deg 67% 85%);
|
|
}
|
|
|
|
body {
|
|
--text-color: var(--default-text-color);
|
|
--text-color-dark: oklch(from var(--text-color) l c h / 0.8);
|
|
--background-color: #0d0117;
|
|
--accent-color: hsl(282deg 67% 85%);
|
|
--glass-color: hsl(from var(--accent-color) h s 20%);
|
|
}
|
|
</style>
|
|
|
|
<style lang="scss" define:vars={prefixedSlideColors}>
|
|
html {
|
|
height: 100dvh;
|
|
width: 100dvw;
|
|
overflow-y: hidden;
|
|
background: #000;
|
|
}
|
|
|
|
body {
|
|
overflow-y: scroll;
|
|
height: 100%;
|
|
min-height: 100dvh;
|
|
width: 100dvw;
|
|
min-width: max-content;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: start;
|
|
justify-content: start;
|
|
scroll-snap-type: y mandatory;
|
|
scroll-snap-align: start;
|
|
scroll-timeline: --root-scroll-timeline;
|
|
|
|
scrollbar-width: none; /* Firefox */
|
|
&::-webkit-scrollbar {
|
|
width: 0; /* Chrome, Safari, Opera */
|
|
}
|
|
|
|
& > :global(*):not(#scroll-indicator) {
|
|
flex-shrink: 0;
|
|
scroll-snap-align: start;
|
|
width: 100dvw;
|
|
height: 100dvh;
|
|
}
|
|
}
|
|
|
|
#scroll-indicator {
|
|
z-index: 1000;
|
|
position: absolute;
|
|
right: 5px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
display: none;
|
|
|
|
#scroll-indicator-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
|
|
.shadow, .indicator {
|
|
display: inline-block;
|
|
height: 1em;
|
|
aspect-ratio: 1 / 1;
|
|
background: rgba(255, 255, 255, 0.2);
|
|
border-radius: 50%;
|
|
filter: blur(0.1em);
|
|
}
|
|
|
|
.indicator {
|
|
position: absolute;
|
|
top: calc(100% - 1em);
|
|
background: rgba(255, 255, 255, 0.7);
|
|
}
|
|
}
|
|
}
|
|
|
|
@supports (animation-timeline: scroll()) {
|
|
#scroll-indicator {
|
|
display: block;
|
|
|
|
& .indicator {
|
|
animation: scroll-indicator-animation linear;
|
|
animation-timeline: --root-scroll-timeline;
|
|
animation-duration: 1ms;
|
|
|
|
@keyframes scroll-indicator-animation {
|
|
0% {
|
|
top: 0;
|
|
}
|
|
100% {
|
|
top: calc(100% - 1em);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
@supports (animation-timeline: scroll()) {
|
|
body {
|
|
animation: color-fade linear;
|
|
animation-timeline: --root-scroll-timeline;
|
|
animation-duration: 1ms;
|
|
|
|
@keyframes color-fade {
|
|
0%,100% {
|
|
--accent-color: #ddd;
|
|
--text-color: #ddd;
|
|
}
|
|
8.33%,
|
|
16.67%,
|
|
33.33%,
|
|
41.67%,
|
|
58.33%,
|
|
66.67%,
|
|
83.33%,
|
|
91.67% {
|
|
--accent-color: #000;
|
|
--glass-color: #000;
|
|
--text-color: #000;
|
|
}
|
|
25% {
|
|
--accent-color: hsl(191, 88%, 81%);
|
|
--glass-color: hsl(191, 88%, 20%);
|
|
--text-color: #ddd;
|
|
}
|
|
50% {
|
|
--accent-color: hsl(31deg 100% 85%);
|
|
--glass-color: hsl(31deg 100% 20%);
|
|
--text-color: #ddd;
|
|
}
|
|
75% {
|
|
--accent-color: hsl(347deg 89% 85%);
|
|
--glass-color: hsl(347deg 89% 20%);
|
|
--text-color: #ddd;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|