Merge pull request #17 from mcgill-ecsess/melissa

FAQ accordion component
This commit is contained in:
Mel
2025-06-18 21:35:01 -04:00
committed by GitHub
4 changed files with 142 additions and 13 deletions

View File

@@ -9,6 +9,7 @@
--color-ecsess-600: #3B6A3A; --color-ecsess-600: #3B6A3A;
--color-ecsess-800: #0A3D2A; --color-ecsess-800: #0A3D2A;
--color-ecsess-black: #1F1F1F; --color-ecsess-black: #1F1F1F;
--color-ecsess-black-hover:#2c2c2c;
} }
* { * {

View File

@@ -0,0 +1,114 @@
<script>
// import { slide } from 'svelte/transition';
import { Accordion } from '@skeletonlabs/skeleton-svelte';
// FAQ closed by default
let isOpen = $state(false);
// const toggle = () => (isOpen = !isOpen);
// Variable to be included into the component
let { /** @type {String} */ entries } = $props();
</script>
<Accordion classes="w-[500px] max-w-[500px] transition-all ease-in-out" multiple>
{#snippet iconClosed()}
<svg
width="20"
height="20"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
stroke="currentColor"
><path d="M9 5l7 7-7 7" />
</svg>
{/snippet}
{#snippet iconOpen()}
<svg
class="rotate-90"
width="20"
height="20"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
stroke="currentColor"
><path d="M9 5l7 7-7 7" />
</svg>
{/snippet}
{#each entries as entry, index}
<Accordion.Item
value={index.toString()}
classes="border-ecsess-200 mb-4 overflow-hidden rounded-xl border-2"
leadClasses="text-xl font-bold"
controlClasses="hover:bg-ecsess-black-hover
flex w-inherit cursor-pointer items-center justify-between
py-4 transition-colors ease-in-out"
panelClasses=" border-t-ecsess-200 max-h-fit border-t-2 bg-transparent p-4 bg-ecsess-400"
>
<!-- Control -->
{#snippet lead()}
{entry.question}
{/snippet}
{#snippet control()}{/snippet}
<!-- Panel -->
{#snippet panel()}{entry.answer}{/snippet}
</Accordion.Item>
{/each}
</Accordion>
<!--
<div class="accordion-wrapper w-full max-w-[500px]">
<div
class="accordion-item
border-ecsess-200 mb-4 overflow-hidden rounded-xl border-2
{isOpen ? '' : 'open'}"
>
<button
class="accordion-header hover:bg-ecsess-black-hover
flex h-16 w-full cursor-pointer items-center justify-between
px-4 transition-colors ease-in-out"
onclick={toggle}
aria-expanded={isOpen}
>
<span class="text-xl font-bold">{question}</span>
<svg
class="accordion-icon transform-cpu transition-all ease-in-out"
width="20"
height="20"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path d="M9 5l7 7-7 7" />
</svg>
</button>
{#if isOpen}
<div
class="accordion-content border-t-ecsess-200 max-h-fit border-t-2 bg-transparent p-4 transition-all ease-in"
transition:slide={{ duration: 300 }}
>
<p>{answer}</p>
</div>
{/if}
</div>
</div> -->
<!-- <style>
[aria-expanded='true'] .accordion-icon {
transform: rotate(90deg);
}
.accordion-item.open .accordion-header,
.accordion-item.open .accordion-content {
background-color: var(--color-ecsess-black-hover);
}
</style> -->

View File

@@ -2,7 +2,8 @@ import { getFromCMS } from 'utils/utils.js';
const homepageQuery = `*[_type == "homepage"]{ const homepageQuery = `*[_type == "homepage"]{
"description": description[], "description": description[],
"councilPhoto": councilPhoto.asset->url "councilPhoto": councilPhoto.asset->url,
"faqs": faqs[]{ question, answer },
}[0]`; }[0]`;
const ohQuery = `*[_type=="oh"].schedule[]{ const ohQuery = `*[_type=="oh"].schedule[]{
@@ -13,12 +14,26 @@ const ohQuery = `*[_type=="oh"].schedule[]{
}`; }`;
export const load = async () => { export const load = async () => {
/**
* @description Response data type based on the `homepageQuery` above.
* Note that `description` is a rich/portable text type
*
* @type {{
* description: import('@portabletext/svelte').InputValue,
* councilPhoto: string,
* faqs: [{
* question: string,
* answer: string
* }],
* }}
*
*/
let CMSresponse = await getFromCMS(homepageQuery); let CMSresponse = await getFromCMS(homepageQuery);
return { return {
description: CMSresponse.description, description: CMSresponse.description,
councilPhoto: CMSresponse.councilPhoto councilPhoto: CMSresponse.councilPhoto,
faqs: CMSresponse.faqs
// ohs: await getFromCMS(ohQuery), // ohs: await getFromCMS(ohQuery),
// FAQs: "",
}; };
}; };

View File

@@ -1,6 +1,8 @@
<script> <script>
import FaqAccordion from 'components/FAQAccordion.svelte';
import Section from 'components/Section.svelte'; import Section from 'components/Section.svelte';
import { PortableText } from '@portabletext/svelte'; import { PortableText } from '@portabletext/svelte';
/** loading things from the server side */ /** loading things from the server side */
let { data } = $props(); let { data } = $props();
</script> </script>
@@ -19,20 +21,17 @@
<!-- Picture, FAQ --> <!-- Picture, FAQ -->
<Section black> <Section black>
<h1>Our student council</h1> <div>
<div class="flex justify-around gap-12"> <h1>Our Student Council</h1>
<div> <img src={data.councilPhoto} alt="ECSESS Council" />
<img src={data.councilPhoto} alt="ECSESS Council" />
</div>
</div> </div>
</Section>
<!-- Office Hours Calendar -->
<Section>
<div> <div>
<h1>FAQ</h1> <h1>FAQ</h1>
<p>Under development</p> <FaqAccordion entries={data.faqs} />
</div> </div>
</Section>
<!-- Office Hours Calendar -->
<Section>
<div> <div>
<h1 class="text-2xl">Office Hours</h1> <h1 class="text-2xl">Office Hours</h1>
<p>Under development</p> <p>Under development</p>