- {#each data.whisper.messages as message, i (message.id)}
- {@const prev = data.whisper.messages[i - 1]}
- {@const isNewDay =
- !prev || prev.createdAt.toDateString() !== message.createdAt.toDateString()}
-
- {#if isNewDay}
-
-
-
- {/if}
-
-
+
+ {#key data.whisper}
+
message.id}
+ lazy={data.whisper.hasOlder}
+ onloadmore={() => data.whisper.loadOlder()}
>
-
-
-
-
-
- {message.user.displayName}
-
-
-
+ {#snippet children(message, i)}
+ {@const prev = data.whisper.messages[i - 1]}
+ {@const isNewDay =
+ !prev || prev.createdAt.toDateString() !== message.createdAt.toDateString()}
+
+ {#if isNewDay}
+
+
+
+ {/if}
+
+
+

+
+
+
+
+ {message.user.displayName}
+
+
+
+
+
+
{message.text}
+
-
-
{message.text}
-
-
- {/each}
+ {/snippet}
+
+ {/key}
diff --git a/src/styles/app.css b/src/styles/app.css
index 89bd4729..f984cae5 100644
--- a/src/styles/app.css
+++ b/src/styles/app.css
@@ -4,6 +4,24 @@
@import "./positioning.css";
+@layer properties {
+ @property --scroll-fade {
+ syntax: "";
+ inherits: false;
+ initial-value: 0;
+ }
+}
+
+@keyframes scroll-fade {
+ from {
+ --scroll-fade: min(12%, calc(var(--spacing) * 10));
+ }
+
+ to {
+ --scroll-fade: 0;
+ }
+}
+
@layer {
:root {
--radius: 0.625rem;
@@ -157,7 +175,7 @@
-moz-osx-font-smoothing: grayscale;
}
- button:hover {
+ button {
cursor: pointer;
}
@@ -217,4 +235,20 @@
@apply animate-out zoom-out-95 fade-out;
}
}
+
+ .scroll-fade {
+ --scroll-fade: 0;
+
+ mask-image: linear-gradient(
+ to bottom,
+ #000 0,
+ #000 calc(100% - var(--scroll-fade)),
+ transparent 100%
+ );
+ mask-composite: intersect;
+ mask-repeat: no-repeat;
+ animation: 1ms ease-in-out scroll-fade both;
+ animation-timeline: scroll(self y);
+ animation-range: calc(100% - calc(var(--spacing) * 24));
+ }
}