Skip to content

Commit fd5ae2c

Browse files
authored
feat: accordion module (#9)
- **feat: accordion module** - **feat: add SEO title**
1 parent 540dbec commit fd5ae2c

7 files changed

Lines changed: 127 additions & 0 deletions

File tree

app/assets/css/_animation.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,29 @@
3131
transform: translateY(0);
3232
}
3333
}
34+
35+
@utility animate-slideDown {
36+
animation: slideDown var(--duration-default) var(--ease-default);
37+
}
38+
39+
@utility animate-slideUp {
40+
animation: slideUp var(--duration-default) var(--ease-default);
41+
}
42+
43+
@keyframes slideDown {
44+
from {
45+
height: 0;
46+
}
47+
to {
48+
height: var(--reka-accordion-content-height);
49+
}
50+
}
51+
52+
@keyframes slideUp {
53+
from {
54+
height: var(--reka-accordion-content-height);
55+
}
56+
to {
57+
height: 0;
58+
}
59+
}

app/components/PageStandard.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ if (error.value) {
2525
});
2626
}
2727
28+
useHead({
29+
title: data.value?.seoTitle || undefined,
30+
});
31+
2832
const contentModules = computed(
2933
() => data.value?.contentModulesCollection?.items || [],
3034
);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<template>
2+
<ContentContainer
3+
as="section"
4+
grid
5+
class="mb-vertical md:mb-vertical-lg gap-y-7"
6+
>
7+
<div class="col-span-12 md:col-span-5 max-w-copy flex flex-col gap-y-6">
8+
<Heading as="h2">{{ data.heading }}</Heading>
9+
<RichTextRenderer :json="data?.copy?.json" />
10+
</div>
11+
12+
<div class="col-span-12 md:col-span-6 md:col-start-7">
13+
<AccordionRoot type="multiple" class="flex flex-col">
14+
<AccordionItem
15+
v-for="(item, index) in items"
16+
:key="index"
17+
:value="`item-${index}`"
18+
class="border-b-2 border-accent"
19+
>
20+
<AccordionHeader as="h3">
21+
<AccordionTrigger
22+
class="group flex gap-x-4 w-full items-center justify-between py-6 text-left type-h4 cursor-pointer"
23+
>
24+
<span>{{ item.title }}</span>
25+
<IconChevronDown
26+
aria-hidden
27+
class="size-5 shrink-0 transition-transform duration-default ease-default group-data-[state=open]:rotate-180"
28+
/>
29+
</AccordionTrigger>
30+
</AccordionHeader>
31+
<AccordionContent
32+
class="overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp"
33+
>
34+
<div class="pb-4 type-body">
35+
<RichTextRenderer :json="item.copy?.json" />
36+
</div>
37+
</AccordionContent>
38+
</AccordionItem>
39+
</AccordionRoot>
40+
</div>
41+
</ContentContainer>
42+
</template>
43+
44+
<script setup lang="ts">
45+
import {
46+
AccordionContent,
47+
AccordionHeader,
48+
AccordionItem,
49+
AccordionRoot,
50+
AccordionTrigger,
51+
} from "reka-ui";
52+
import type { ModuleProps } from "~/types/module";
53+
import type { AccordionFragment } from "~~/shared/types/graphql";
54+
55+
const { data } = defineProps<ModuleProps<AccordionFragment>>();
56+
57+
const items = computed(
58+
() => data.itemsCollection?.items.filter((item) => item !== null) ?? [],
59+
);
60+
</script>

app/components/render/ModuleRenderer.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<script setup lang="ts">
66
import HomepageHero from "~/components/modules/HomepageHero.vue";
77
import FiftyFifty from "~/components/modules/FiftyFifty.vue";
8+
import Accordion from "~/components/modules/Accordion.vue";
89
import type { Component } from "vue";
910
import type { PageStandardFragment } from "~~/shared/types/graphql";
1011
@@ -19,6 +20,7 @@ const { data } = defineProps<{
1920
const modules: Record<string, Component> = {
2021
HomepageHero: HomepageHero,
2122
ModuleFiftyfifty: FiftyFifty,
23+
ModuleAccordion: Accordion,
2224
};
2325
2426
const component = computed(() => {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<template>
2+
<svg
3+
xmlns="http://www.w3.org/2000/svg"
4+
viewBox="0 -960 960 960"
5+
fill="currentColor"
6+
>
7+
<path d="M480-344 240-584l56-56 184 184 184-184 56 56-240 240Z" />
8+
</svg>
9+
</template>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { gql } from "graphql-request";
2+
3+
export const ACCORDION_FRAGMENT = gql`
4+
fragment Accordion on ModuleAccordion {
5+
heading
6+
copy {
7+
json
8+
}
9+
itemsCollection(limit: 15) {
10+
items {
11+
... on ComponentTitleCopy {
12+
title
13+
copy {
14+
json
15+
}
16+
}
17+
}
18+
}
19+
}
20+
`;

server/graphql/queries/page-standard.query.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { HOMEPAGE_HERO_FRAGMENT } from "../modules/homepage-hero.fragment";
33
import { IMAGE_FRAGMENT } from "../fragments/Image.fragment";
44
import { FIFTY_FIFTY_FRAGMENT } from "../modules/fifty-fifty.fragment";
55
import { LINK_FRAGMENT } from "../fragments/Link.fragment";
6+
import { ACCORDION_FRAGMENT } from "../modules/accordion.fragment";
67

78
export const PAGE_STANDARD_QUERY = gql`
89
query PageStandard($slug: String!) {
@@ -17,6 +18,7 @@ export const PAGE_STANDARD_QUERY = gql`
1718
fragment PageStandard on PageStandard {
1819
cmsName
1920
slug
21+
seoTitle
2022
contentModulesCollection(limit: 15) {
2123
items {
2224
__typename
@@ -26,11 +28,15 @@ export const PAGE_STANDARD_QUERY = gql`
2628
... on ModuleFiftyfifty {
2729
...FiftyFifty
2830
}
31+
... on ModuleAccordion {
32+
...Accordion
33+
}
2934
}
3035
}
3136
}
3237
${HOMEPAGE_HERO_FRAGMENT}
3338
${FIFTY_FIFTY_FRAGMENT}
39+
${ACCORDION_FRAGMENT}
3440
${IMAGE_FRAGMENT}
3541
${LINK_FRAGMENT}
3642
`;

0 commit comments

Comments
 (0)