Skip to content

Commit a415053

Browse files
authored
Merge pull request #32 from nsandoya/11-faqs-rebasement
- Refactored `Faqs.astro` to implement a collapsible component (`Accordion.astro`) for each question. - Implemented Alpine.js basic directives and minimalistic logic for interactivity, ensuring one accordion is open at a time. - Closes #11
2 parents 7dd94bb + 697a4bb commit a415053

File tree

4 files changed

+105
-7
lines changed

4 files changed

+105
-7
lines changed

public/icons/downIcon.svg

Lines changed: 1 addition & 0 deletions
Loading

src/components/Accordion.astro

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
import downIcon from "../../public/icons/downIcon.svg?raw";
3+
const { title, description, id, last } = Astro.props;
4+
---
5+
<!--
6+
Child component: Alpine.js logic
7+
8+
1. Each accordion receives a unique `id` that identifies it.
9+
2. When clicking on an accordion:
10+
2.1 The `toggle(id)` method defined in the parent component is called.
11+
2.2 The global state `activeId` is updated with the new ID.
12+
3. Each accordion checks if its ID matches `activeId` using the `isVisible` method:
13+
- If it matches, the accordion expands (`isVisible` is `true`).
14+
- If it doesn't match, it remains collapsed (`isVisible` is `false`).
15+
16+
This way, each child component can respond reactively to the `activeId` global state.
17+
-->
18+
<div
19+
class:list={[
20+
"bg-white py-6 accordion-transition overflow-hidden",
21+
{"border-b-0": last === id},
22+
{"border-b-2": last != id}
23+
]}
24+
>
25+
<div
26+
@click=`toggle(${id})`
27+
class="flex flex-row items-center text-lg font-semibold cursor-pointer"
28+
:class=`isVisible(${id}) && 'text-blue-500'`
29+
>
30+
<div class="w-[95%] px-4">
31+
{title}
32+
</div>
33+
<div
34+
x-transition
35+
class="w-fit"
36+
:class=`isVisible(${id}) ? 'transform rotate-180 accordion-transition' : 'transform rotate-0 accordion-transition'`
37+
>
38+
<Fragment set:html={downIcon} />
39+
</div>
40+
</div>
41+
42+
<div
43+
x-transition
44+
class="accordion-transition overflow-hidden"
45+
:class=`isVisible(${id}) ? 'max-h-72 opacity-100' : 'max-h-0 opacity-0'`
46+
>
47+
<p class="w-[90%] text-gray-600 text-base mt-2 px-4 overflow-hidden">
48+
{description}
49+
</p>
50+
</div>
51+
</div>

src/components/Faq.astro

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,54 @@
11
---
22
import commonQuestions from "../assets/common-questions.json";
3+
import Accordion from "./Accordion.astro";
34
---
5+
<!--
46
5-
<section class="py-16 bg-gray-50">
7+
Father component: Alpine.js logic
8+
9+
1. `activeId` is a global state that stores the ID of the last accordion opened by the user.
10+
2. When clicking on a child component (an accordion), the `toggle` method updates the `activeId`:
11+
- If the clicked accordion's ID matches the current `activeId`, it collapses (resets to `null`).
12+
- If it's different, the new ID is set as `activeId`.
13+
3. Every accordion checks if its ID matches `activeId` by using the `isVisible` method. This way, accordion opens or closes.
14+
15+
This ensures only one accordion is open at a time.
16+
17+
-->
18+
<section
19+
x-data="{
20+
activeId: null,
21+
22+
setActiveId(id) {
23+
this.activeId = id;
24+
},
25+
26+
isVisible(id) {
27+
return this.activeId === id;
28+
},
29+
30+
toggle(id){
31+
if (this.activeId === id) {
32+
this.setActiveId(null)
33+
} else {
34+
this.setActiveId(id)
35+
};
36+
}
37+
}"
38+
39+
class="py-16 bg-white">
640
<div class="container mx-auto px-4">
741
<h2 class="text-3xl font-bold text-center mb-12">Preguntas frecuentes</h2>
8-
<div class="container mx-auto space-y-6">
42+
<div
43+
class="container faqs-container "
44+
>
945
{
10-
commonQuestions.map((question) => (
11-
<div class="bg-white p-6 rounded-lg shadow-md">
12-
<h3 class="text-lg font-semibold mb-2">{question.title}</h3>
13-
<p class="text-gray-600">{question.description}</p>
14-
</div>
46+
commonQuestions.map((question, index) => (
47+
<Accordion
48+
{...question}
49+
id={++index}
50+
last={commonQuestions.length}
51+
/>
1552
))
1653
}
1754
</div>

src/styles/globals.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,13 @@
3636
svg {
3737
@apply text-sm;
3838
}
39+
40+
/* Components custom styles */
41+
.faqs-container {
42+
@apply mx-auto shadow-md p-6 pt-0 rounded-xl;
43+
}
44+
45+
.accordion-transition {
46+
transition: all 400ms ease-in-out;
47+
}
3948
}

0 commit comments

Comments
 (0)