78 lines
2.1 KiB
Svelte
78 lines
2.1 KiB
Svelte
<script lang="ts">
|
|
import { chats } from './lib/chats';
|
|
import { type TransitionConfig } from 'svelte/transition';
|
|
import { quadOut as easing } from 'svelte/easing';
|
|
import CommentRenderer from './components/CommentRenderer.svelte';
|
|
import { url } from './lib/url';
|
|
|
|
const child = new WeakMap<Node, number>();
|
|
let container: HTMLDivElement;
|
|
let queued = false;
|
|
|
|
$: top = $url.searchParams.get('layout') === 'top';
|
|
|
|
function queue() {
|
|
if (queued) return;
|
|
function fn() {
|
|
queued = false;
|
|
if (!container) return;
|
|
let n = 0;
|
|
container.childNodes.forEach((node) => {
|
|
n += child.get(node) ?? 0;
|
|
});
|
|
container.scrollTo({ top: top ? n : -n });
|
|
}
|
|
requestAnimationFrame(fn);
|
|
}
|
|
|
|
function scrollEffect(div: HTMLDivElement): TransitionConfig {
|
|
const rect = div.getBoundingClientRect();
|
|
child.set(div, rect.height);
|
|
return {
|
|
easing,
|
|
duration: 200,
|
|
tick(_, u) {
|
|
const rect = div.getBoundingClientRect();
|
|
child.set(div, u * rect.height);
|
|
queue();
|
|
}
|
|
};
|
|
}
|
|
</script>
|
|
|
|
<div
|
|
class="flex h-screen w-screen overflow-hidden px-3 py-2"
|
|
class:bottom={!top}
|
|
class:top
|
|
bind:this={container}
|
|
>
|
|
{#each [...$chats].reverse() as chat (`${chat.service}/${chat.data.id}`)}
|
|
<div class="origin-top-left" in:scrollEffect>
|
|
<CommentRenderer comment={chat} />
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
|
|
<style lang="postcss">
|
|
.bottom {
|
|
@apply flex-col-reverse;
|
|
mask-image: linear-gradient(
|
|
180deg,
|
|
rgba(0, 0, 0, 0) 0%,
|
|
rgba(0, 0, 0, 0.25) 15%,
|
|
rgba(0, 0, 0, 1) 30%,
|
|
rgba(0, 0, 0, 1) 100%
|
|
);
|
|
}
|
|
.top {
|
|
@apply flex-col;
|
|
mask-image: linear-gradient(
|
|
0deg,
|
|
rgba(0, 0, 0, 0) 0%,
|
|
rgba(0, 0, 0, 0.25) 15%,
|
|
rgba(0, 0, 0, 1) 30%,
|
|
rgba(0, 0, 0, 1) 100%
|
|
);
|
|
}
|
|
</style>
|