Merge branch 'antoine/70-73-phase-out-skeleton-ui'
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
<script lang="ts">
|
||||
// Reference: https://github.com/skeletonlabs/skeleton/tree/88844ffb67b7c9553c5245dd6d70146a3d6b8932/packages/skeleton-svelte/src/components/avatar
|
||||
import { Avatar } from '@skeletonlabs/skeleton-svelte';
|
||||
let { name, src }: { name: string; src: string } = $props();
|
||||
|
||||
function getInitials(name: string): string {
|
||||
@@ -10,14 +8,25 @@
|
||||
.map((word) => word.charAt(0).toUpperCase())
|
||||
.join('');
|
||||
}
|
||||
|
||||
let imageError = $state(false);
|
||||
|
||||
function handleImageError() {
|
||||
imageError = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<Avatar class="size-26 md:size-32">
|
||||
<Avatar.Image {src} class="h-full w-full rounded-full object-cover" />
|
||||
|
||||
<Avatar.Fallback>
|
||||
<div class="relative size-26 overflow-hidden rounded-full md:size-32">
|
||||
{#if src && !imageError}
|
||||
<img
|
||||
{src}
|
||||
alt={name}
|
||||
class="h-full w-full rounded-full object-cover"
|
||||
onerror={handleImageError}
|
||||
/>
|
||||
{:else if !src || imageError}
|
||||
<div class="bg-ecsess-400 flex h-full w-full items-center justify-center rounded-full">
|
||||
<span class="text-ecsess-black text-xl font-bold"> {getInitials(name)} </span>
|
||||
</div>
|
||||
</Avatar.Fallback>
|
||||
</Avatar>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,26 +1,47 @@
|
||||
<script lang="ts">
|
||||
import type { FAQ } from '$lib/schemas';
|
||||
import { Accordion } from '@skeletonlabs/skeleton-svelte';
|
||||
import { slide } from 'svelte/transition';
|
||||
|
||||
// Variable to be included into the component
|
||||
let { entries }: { entries: FAQ[] } = $props();
|
||||
|
||||
// Track which items are open (supports multiple)
|
||||
let openItems = $state<Set<number>>(new Set());
|
||||
|
||||
function toggleItem(index: number) {
|
||||
const newSet = new Set(openItems);
|
||||
if (newSet.has(index)) {
|
||||
newSet.delete(index);
|
||||
} else {
|
||||
newSet.add(index);
|
||||
}
|
||||
openItems = newSet;
|
||||
}
|
||||
|
||||
function isOpen(index: number): boolean {
|
||||
return openItems.has(index);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Accordion multiple class="space-y-3">
|
||||
<div class="space-y-3">
|
||||
{#each entries as entry, index}
|
||||
<Accordion.Item
|
||||
value={index.toString()}
|
||||
class="border-ecsess-300 hover:bg-ecsess-500/30 rounded-md border-2 transition-colors duration-200"
|
||||
>
|
||||
<div class="border-ecsess-300 rounded-md border-2 transition-colors duration-200">
|
||||
<!-- Question -->
|
||||
<Accordion.ItemTrigger
|
||||
class="flex w-full items-center gap-3 px-3 py-2 text-left text-lg font-bold"
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => toggleItem(index)}
|
||||
class="bg-ecsess-600/20 hover:bg-ecsess-500/40 flex w-full items-center gap-3 px-3 py-2 text-left text-lg font-bold transition-colors duration-200 {isOpen(
|
||||
index
|
||||
)
|
||||
? 'rounded-t-md'
|
||||
: 'rounded-md'}"
|
||||
>
|
||||
{entry.question}
|
||||
<Accordion.ItemIndicator class="group ml-auto">
|
||||
<span class="ml-auto">
|
||||
<svg
|
||||
class="size-5 shrink-0 transition-transform duration-200 group-data-[state=open]:rotate-90"
|
||||
class="size-5 shrink-0 transition-transform duration-200 {isOpen(index)
|
||||
? 'rotate-90'
|
||||
: ''}"
|
||||
width="20"
|
||||
height="20"
|
||||
fill="none"
|
||||
@@ -29,28 +50,24 @@
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
><path d="M9 5l7 7-7 7" />
|
||||
>
|
||||
<path d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</Accordion.ItemIndicator>
|
||||
</Accordion.ItemTrigger>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!-- Panel -->
|
||||
<Accordion.ItemContent class="border-t-ecsess-300 bg-ecsess-400/50 h-fit overflow-hidden">
|
||||
{#snippet element(attributes)}
|
||||
{#if !attributes.hidden}
|
||||
<div
|
||||
{...attributes}
|
||||
class="border-t-ecsess-300 overflow-hidden border-t-2 px-4 py-3
|
||||
text-base leading-relaxed transition-all duration-200"
|
||||
transition:slide={{ duration: 200 }}
|
||||
>
|
||||
{entry.answer}
|
||||
</div>
|
||||
{/if}
|
||||
{/snippet}
|
||||
</Accordion.ItemContent>
|
||||
</Accordion.Item>
|
||||
{#if isOpen(index)}
|
||||
<div
|
||||
class="border-t-ecsess-300 h-fit overflow-hidden border-t-2 bg-transparent px-4 py-3
|
||||
text-base leading-relaxed transition-all duration-200"
|
||||
transition:slide={{ duration: 200 }}
|
||||
>
|
||||
{entry.answer}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</Accordion>
|
||||
</div>
|
||||
|
||||
<!-- -->
|
||||
|
||||
Reference in New Issue
Block a user