All checks were successful
Deploy site (production) / build-and-deploy (push) Successful in 48s
- Scaffold packages/site with 11 Vue components: hero (animated terminal), features, showcase, work groups, how-it-works, security, FAQ accordion, footer - i18n EN/FR via vue-i18n with 82+ keys, autodetect navigator.language, toggle without reload - Animated timeline (terminal, dialog, toast) ported from design, scroll-reveal, copy buttons (2 instances) - Self-hosted JetBrains Mono fonts (@fontsource), optimized assets (mark 28KB, og-cover 1200×630) - SEO: canonical, og:image, theme-color, robots.txt, sitemap.xml for git-arboretum.com - Monorepo integration (decoupled from npm release): build:site / dev:site / preview:site scripts - CI: add build:site step to ci.yml for early detection; create .gitea/workflows/prod.yml for FTPS deploy (lftp mirror) to git-arboretum.com - Validated builds ✓ and UI rendering (EN/FR headless test) ✓
53 lines
2.2 KiB
Vue
53 lines
2.2 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { FAQS } from '../i18n/content';
|
|
import type { AppLocale } from '../i18n';
|
|
|
|
const { t, locale } = useI18n();
|
|
const open = ref(0);
|
|
const items = computed(() => FAQS[locale.value as AppLocale]);
|
|
|
|
function toggle(i: number): void {
|
|
open.value = open.value === i ? -1 : i;
|
|
}
|
|
|
|
function panelStyle(i: number) {
|
|
return {
|
|
maxHeight: open.value === i ? '300px' : '0px',
|
|
opacity: open.value === i ? 1 : 0,
|
|
overflow: 'hidden',
|
|
transition: 'max-height .4s ease, opacity .35s ease',
|
|
} as const;
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<section id="faq" class="mx-auto max-w-[780px] scroll-mt-[84px] px-6 pb-[100px]">
|
|
<div v-reveal class="mb-[38px] text-center">
|
|
<div class="mb-3.5 font-mono text-xs uppercase tracking-[0.14em] text-emerald-400">{{ t('navFaq') }}</div>
|
|
<h2 class="m-0 text-[clamp(28px,3.4vw,40px)] font-semibold tracking-[-0.025em] text-zinc-50">{{ t('faqTitle') }}</h2>
|
|
</div>
|
|
|
|
<div v-reveal>
|
|
<div v-for="(f, i) in items" :key="i" class="border-t" :class="open === i ? 'border-emerald-400/40' : 'border-zinc-800'">
|
|
<button
|
|
type="button"
|
|
:aria-expanded="open === i"
|
|
:aria-controls="`faq-panel-${i}`"
|
|
class="flex w-full cursor-pointer items-center justify-between gap-4 border-none bg-transparent px-1 py-5 text-left text-[clamp(16px,2vw,18px)] font-medium text-zinc-50 focus-visible:rounded-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-emerald-500/70"
|
|
@click="toggle(i)"
|
|
>
|
|
<span>{{ f.q }}</span>
|
|
<span class="flex flex-none text-emerald-400 transition-transform duration-300" :class="open === i ? 'rotate-180' : ''">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>
|
|
</span>
|
|
</button>
|
|
<div :id="`faq-panel-${i}`" :style="panelStyle(i)" :inert="open !== i" :aria-hidden="open !== i">
|
|
<p class="m-0 max-w-[640px] px-1 pb-5 text-[15.5px] leading-[1.6] text-zinc-400">{{ f.a }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|