54 lines
1.2 KiB
Svelte
54 lines
1.2 KiB
Svelte
<script lang="ts">
|
||
import { fly, scale, fade } from 'svelte/transition';
|
||
import { cubicOut } from 'svelte/easing';
|
||
import { tick } from 'svelte';
|
||
|
||
let expanded = false;
|
||
let formContainer: HTMLDivElement;
|
||
|
||
async function toggle() {
|
||
expanded = !expanded;
|
||
|
||
if (expanded) {
|
||
// Wait for DOM to update
|
||
await tick();
|
||
|
||
// Scroll smoothly into view
|
||
formContainer?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<div data-testid="expand-container" class="flex flex-col items-center">
|
||
<!-- + / × button -->
|
||
<button
|
||
class="flex items-center justify-center w-12 h-12 rounded-full bg-blue-600 text-white text-2xl font-bold hover:bg-blue-700 transition"
|
||
on:click={toggle}
|
||
aria-expanded={expanded}
|
||
aria-label="Add item"
|
||
>
|
||
{#if expanded}
|
||
✕
|
||
{:else}
|
||
+
|
||
{/if}
|
||
</button>
|
||
|
||
<!-- Expandable content below button -->
|
||
{#if expanded}
|
||
<div
|
||
bind:this={formContainer}
|
||
class="w-full mt-4 flex justify-center"
|
||
transition:fade
|
||
>
|
||
<div
|
||
in:fly={{ y: 10, duration: 200, easing: cubicOut }}
|
||
out:scale={{ duration: 150 }}
|
||
class="w-full max-w-2xl"
|
||
>
|
||
<slot />
|
||
</div>
|
||
</div>
|
||
{/if}
|
||
</div>
|