Files
ClickerZ/Frontend/src/lib/components/CollapsiblePanel.svelte
Tetardtek f6bff6e389
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 22s
feat: migrate frontend React 18 → Svelte 5 + SvelteKit
Core logic portable (economy, balance, cosmetics, migrateSave) — zero rewrite.
136 tests green, identiques. Backend inchangé.

- Svelte 5 runes stores (game, auth, toast) remplacent Zustand
- SvelteKit adapter-static SPA (dist/ output, fallback index.html)
- Tailwind v4 conservé, design system .gp-* porté
- Transitions natives : slide, fly, scale, fade sur toute l'UI
- Sidebar tabbée (Production/Evolution/Collection) + CollapsiblePanel
- Mobile bottom sheet avec FAB toggle + backdrop blur
- Click particles réactifs Svelte (plus de DOM impératif)
- TadpoleSprite bounce + glow ring au clic
- Guide refait en accordéon, Achievements avec filtres
- a11y : focus-visible, Escape modals, aria-current, aria-labels
- CI/CD adapté (tests + build + rsync)
- Build 504K (vs ~1.2MB React)
2026-03-28 20:03:21 +01:00

52 lines
1.2 KiB
Svelte

<script lang="ts">
import { slide } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
import type { Snippet } from 'svelte';
interface Props {
title: string;
badge?: string;
accentClass?: string;
defaultOpen?: boolean;
children: Snippet;
}
let { title, badge = '', accentClass = '', defaultOpen = true, children }: Props = $props();
let open = $state(defaultOpen);
</script>
<div class="gp overflow-hidden">
<button
class="flex items-center justify-between w-full cursor-pointer group"
onclick={() => open = !open}
>
<div class="flex items-center gap-2">
<svg
class="w-3 h-3 transition-transform duration-200 text-white/50 group-hover:text-white/80"
class:rotate-90={open}
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="9 18 15 12 9 6" />
</svg>
<span class="gp-title {accentClass}">{title}</span>
</div>
{#if badge}
<span class="gp-label">{badge}</span>
{/if}
</button>
{#if open}
<div transition:slide={{ duration: 250, easing: quintOut }}>
<div class="flex flex-col gap-[var(--spacing-gp-gap)] pt-1">
{@render children()}
</div>
</div>
{/if}
</div>