Collapsible.svelte 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. <script lang="ts">
  2. import { getContext, createEventDispatcher } from 'svelte';
  3. const dispatch = createEventDispatcher();
  4. $: dispatch('change', open);
  5. import { slide } from 'svelte/transition';
  6. import { quintOut } from 'svelte/easing';
  7. import ChevronUp from '../icons/ChevronUp.svelte';
  8. import ChevronDown from '../icons/ChevronDown.svelte';
  9. export let open = false;
  10. export let className = '';
  11. export let buttonClassName = 'w-fit';
  12. export let title = null;
  13. export let disabled = false;
  14. export let hide = false;
  15. </script>
  16. <div class={className}>
  17. {#if title !== null}
  18. <!-- svelte-ignore a11y-no-static-element-interactions -->
  19. <!-- svelte-ignore a11y-click-events-have-key-events -->
  20. <div
  21. class={buttonClassName}
  22. on:pointerup={() => {
  23. if (!disabled) {
  24. open = !open;
  25. }
  26. }}
  27. >
  28. <div class=" w-fit font-medium transition flex items-center justify-between gap-2">
  29. <div>
  30. {title}
  31. </div>
  32. <div>
  33. {#if open}
  34. <ChevronUp strokeWidth="3.5" className="size-3.5" />
  35. {:else}
  36. <ChevronDown strokeWidth="3.5" className="size-3.5" />
  37. {/if}
  38. </div>
  39. </div>
  40. </div>
  41. {:else}
  42. <!-- svelte-ignore a11y-no-static-element-interactions -->
  43. <!-- svelte-ignore a11y-click-events-have-key-events -->
  44. <div
  45. class={buttonClassName}
  46. on:pointerup={() => {
  47. if (!disabled) {
  48. open = !open;
  49. }
  50. }}
  51. >
  52. <div
  53. class="flex items-center gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition"
  54. >
  55. <slot />
  56. </div>
  57. </div>
  58. {/if}
  59. {#if open && !hide}
  60. <div transition:slide={{ duration: 300, easing: quintOut, axis: 'y' }}>
  61. <slot name="content" />
  62. </div>
  63. {/if}
  64. </div>