chat-ui / src /lib /components /chat /BlockWrapper.svelte
victor's picture
victor HF Staff
New tools rendering (#2005)
72bda43 unverified
<script lang="ts">
import type { Snippet } from "svelte";
interface Props {
icon: Snippet;
iconBg?: string;
iconRing?: string;
hasNext?: boolean;
loading?: boolean;
children: Snippet;
}
let {
icon,
iconBg = "bg-gray-50 dark:bg-gray-800",
iconRing = "ring-gray-100 dark:ring-gray-700",
hasNext = false,
loading = false,
children,
}: Props = $props();
</script>
<div class="group flex gap-2 has-[+.prose]:mb-1.5 [.prose+&]:mt-3">
<!-- Left column: icon + connector line -->
<div class="flex w-[22px] flex-shrink-0 flex-col items-center">
<div
class="relative z-0 flex h-[22px] w-[22px] items-center justify-center rounded-md ring-1 {iconBg} {iconRing}"
>
{@render icon()}
{#if loading}
<svg
class="pointer-events-none absolute inset-0 h-[22px] w-[22px]"
viewBox="0 0 22 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect
x="0.5"
y="0.5"
width="21"
height="21"
rx="5.5"
class="loading-path stroke-current text-purple-500/20"
stroke-width="1"
fill="none"
/>
</svg>
{/if}
</div>
{#if hasNext}
<div class="my-1 w-px flex-1 bg-gray-200 dark:bg-gray-700"></div>
{/if}
</div>
<!-- Right column: content -->
<div class="min-w-0 flex-1 pb-2 pt-px">
{@render children()}
</div>
</div>
<style>
@keyframes loading {
to {
stroke-dashoffset: -100;
}
}
.loading-path {
stroke-dasharray: 60 40;
animation: loading 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
</style>