mirror of
https://github.com/andy-stack/vaultkeeper-ai.git
synced 2026-07-22 16:30:27 +00:00
Replace auto-scroll interval logic with ResizeObserver-based dynamic padding system that maintains scroll position during streaming by adjusting container bottom padding based on message and thought bubble heights
258 lines
No EOL
5.8 KiB
Svelte
258 lines
No EOL
5.8 KiB
Svelte
<script lang="ts">
|
|
export let streamingElement: HTMLElement | undefined;
|
|
</script>
|
|
|
|
<div class="container" bind:this={streamingElement}>
|
|
<span class="📦"></span>
|
|
<span class="📦"></span>
|
|
<span class="📦"></span>
|
|
<span class="📦"></span>
|
|
<span class="📦"></span>
|
|
</div>
|
|
|
|
<style>
|
|
:root {
|
|
--duration: 1.5s;
|
|
--container-size: 100px;
|
|
--box-size: 12px;
|
|
--box-border-radius: 15%;
|
|
}
|
|
|
|
.container {
|
|
width: var(--container-size);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
position: relative;
|
|
margin-left: 4px;
|
|
padding-top: 12px;
|
|
}
|
|
|
|
.📦 {
|
|
width: var(--box-size);
|
|
height: var(--box-size);
|
|
position: relative;
|
|
display: block;
|
|
transform-origin: -50% center;
|
|
border-radius: var(--box-border-radius);
|
|
}
|
|
.📦:after {
|
|
content: "";
|
|
width: 100%;
|
|
height: 100%;
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
background-color: color-mix(in srgb, var(--interactive-accent) 85%, white 15%);
|
|
border-radius: var(--box-border-radius);
|
|
box-shadow: 0px 0px 8px 2px color-mix(in srgb, var(--interactive-accent) 40%, transparent 80%);
|
|
}
|
|
.📦:nth-child(1) {
|
|
animation: slide var(--duration) ease-in-out infinite alternate;
|
|
}
|
|
.📦:nth-child(1):after {
|
|
animation: color-change var(--duration) ease-in-out infinite alternate;
|
|
}
|
|
.📦:nth-child(2) {
|
|
animation: flip-1 var(--duration) ease-in-out infinite alternate;
|
|
}
|
|
.📦:nth-child(2):after {
|
|
animation: squidge-1 var(--duration) ease-in-out infinite alternate;
|
|
}
|
|
.📦:nth-child(3) {
|
|
animation: flip-2 var(--duration) ease-in-out infinite alternate;
|
|
}
|
|
.📦:nth-child(3):after {
|
|
animation: squidge-2 var(--duration) ease-in-out infinite alternate;
|
|
}
|
|
.📦:nth-child(4) {
|
|
animation: flip-3 var(--duration) ease-in-out infinite alternate;
|
|
}
|
|
.📦:nth-child(4):after {
|
|
animation: squidge-3 var(--duration) ease-in-out infinite alternate;
|
|
}
|
|
.📦:nth-child(5) {
|
|
animation: flip-4 var(--duration) ease-in-out infinite alternate;
|
|
}
|
|
.📦:nth-child(5):after {
|
|
animation: squidge-4 var(--duration) ease-in-out infinite alternate;
|
|
}
|
|
.📦:nth-child(2):after {
|
|
background-color: color-mix(in srgb, var(--interactive-accent) 75%, white 25%);
|
|
}
|
|
.📦:nth-child(3):after {
|
|
background-color: color-mix(in srgb, var(--interactive-accent) 80%, white 20%);
|
|
}
|
|
.📦:nth-child(4):after {
|
|
background-color: color-mix(in srgb, var(--interactive-accent) 90%, white 10%);
|
|
}
|
|
.📦:nth-child(5):after {
|
|
background-color: color-mix(in srgb, var(--interactive-accent) 95%, white 5%);
|
|
}
|
|
|
|
@keyframes slide {
|
|
0% {
|
|
background-color: color-mix(in srgb, var(--interactive-accent) 70%, white 30%);
|
|
transform: translatex(0vw);
|
|
}
|
|
100% {
|
|
background-color: color-mix(in srgb, var(--interactive-accent) 95%, white 5%);
|
|
transform: translatex(
|
|
calc(var(--container-size) - (var(--box-size) * 1.25))
|
|
);
|
|
}
|
|
}
|
|
|
|
@keyframes color-change {
|
|
0% {
|
|
background-color: color-mix(in srgb, var(--interactive-accent) 70%, white 30%);
|
|
}
|
|
100% {
|
|
background-color: color-mix(in srgb, var(--interactive-accent) 95%, white 5%);
|
|
}
|
|
}
|
|
|
|
@keyframes flip-1 {
|
|
0%,
|
|
15% {
|
|
transform: rotate(0);
|
|
}
|
|
35%,
|
|
100% {
|
|
transform: rotate(-180deg);
|
|
}
|
|
}
|
|
|
|
@keyframes squidge-1 {
|
|
5% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(1) scaley(1);
|
|
}
|
|
15% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(1.3) scaley(0.7);
|
|
}
|
|
25%,
|
|
20% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(0.8) scaley(1.4);
|
|
}
|
|
55%,
|
|
100% {
|
|
transform-origin: center top;
|
|
transform: scalex(1) scaley(1);
|
|
}
|
|
40% {
|
|
transform-origin: center top;
|
|
transform: scalex(1.3) scaley(0.7);
|
|
}
|
|
}
|
|
|
|
@keyframes flip-2 {
|
|
0%,
|
|
30% {
|
|
transform: rotate(0);
|
|
}
|
|
50%,
|
|
100% {
|
|
transform: rotate(-180deg);
|
|
}
|
|
}
|
|
|
|
@keyframes squidge-2 {
|
|
20% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(1) scaley(1);
|
|
}
|
|
30% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(1.3) scaley(0.7);
|
|
}
|
|
40%,
|
|
35% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(0.8) scaley(1.4);
|
|
}
|
|
70%,
|
|
100% {
|
|
transform-origin: center top;
|
|
transform: scalex(1) scaley(1);
|
|
}
|
|
55% {
|
|
transform-origin: center top;
|
|
transform: scalex(1.3) scaley(0.7);
|
|
}
|
|
}
|
|
|
|
@keyframes flip-3 {
|
|
0%,
|
|
45% {
|
|
transform: rotate(0);
|
|
}
|
|
65%,
|
|
100% {
|
|
transform: rotate(-180deg);
|
|
}
|
|
}
|
|
|
|
@keyframes squidge-3 {
|
|
35% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(1) scaley(1);
|
|
}
|
|
45% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(1.3) scaley(0.7);
|
|
}
|
|
55%,
|
|
50% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(0.8) scaley(1.4);
|
|
}
|
|
85%,
|
|
100% {
|
|
transform-origin: center top;
|
|
transform: scalex(1) scaley(1);
|
|
}
|
|
70% {
|
|
transform-origin: center top;
|
|
transform: scalex(1.3) scaley(0.7);
|
|
}
|
|
}
|
|
|
|
@keyframes flip-4 {
|
|
0%,
|
|
60% {
|
|
transform: rotate(0);
|
|
}
|
|
80%,
|
|
100% {
|
|
transform: rotate(-180deg);
|
|
}
|
|
}
|
|
|
|
@keyframes squidge-4 {
|
|
50% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(1) scaley(1);
|
|
}
|
|
60% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(1.3) scaley(0.7);
|
|
}
|
|
70%,
|
|
65% {
|
|
transform-origin: center bottom;
|
|
transform: scalex(0.8) scaley(1.4);
|
|
}
|
|
100%,
|
|
100% {
|
|
transform-origin: center top;
|
|
transform: scalex(1) scaley(1);
|
|
}
|
|
85% {
|
|
transform-origin: center top;
|
|
transform: scalex(1.3) scaley(0.7);
|
|
}
|
|
}
|
|
</style> |