Skip to content

Commit

Permalink
Add custom Accordion component
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronbrethorst committed Nov 25, 2024
1 parent edbcaa7 commit eb3cbce
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/components/containers/Accordion.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script>
import { setContext } from 'svelte';
import { writable, derived } from 'svelte/store';
// Create a store to track the active item
const activeItem = writable(null);
// Create dispatch for activeChanged event
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
// Watch for changes to activeItem and dispatch event
$: {
dispatch('activeChanged', { activeItem: $activeItem });
}
// Provide context for child AccordionItems
setContext('accordion', {
registerItem: (id) => {
const isActive = derived(activeItem, ($activeItem) => $activeItem === id);
return {
isActive,
activate: () => {
activeItem.set($activeItem === id ? null : id);
}
};
}
});
</script>

<div
class="divide-y divide-gray-200 border-y border-gray-200 dark:divide-gray-700 dark:border-gray-700"
>
<slot />
</div>
43 changes: 43 additions & 0 deletions src/components/containers/AccordionItem.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script>
import { getContext } from 'svelte';
import { slide } from 'svelte/transition';
const id = crypto.randomUUID();
const { registerItem } = getContext('accordion');
const { isActive, activate } = registerItem(id);
function toggle() {
activate();
}
</script>

<div class="relative">
<div class="sticky top-0 z-10 bg-white dark:bg-gray-800">
<button
type="button"
class="flex w-full items-center justify-between py-3 text-left text-base font-medium text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white"
class:text-gray-900={$isActive}
class:dark:text-white={$isActive}
on:click={toggle}
aria-expanded={$isActive}
>
<slot name="header" />
<svg
class="h-6 w-6 shrink-0 transition-transform"
class:rotate-180={$isActive}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
</div>

{#if $isActive}
<div transition:slide|local>
<div class="py-3">
<slot />
</div>
</div>
{/if}
</div>

0 comments on commit eb3cbce

Please sign in to comment.