Unify workspace dropdowns; Update layouts (#458)

Unified Account and Workspace drop-downs; Layout updates, now header lives within the PageBody component; Sidebars now use floating variant
This commit is contained in:
Giancarlo Buomprisco
2026-03-11 14:45:42 +08:00
committed by GitHub
parent ca585e09be
commit 4bc8448a1d
530 changed files with 14398 additions and 11198 deletions

View File

@@ -0,0 +1,139 @@
import Link from 'next/link';
import { ArrowRight, ChevronDown } from 'lucide-react';
import { getTranslations } from 'next-intl/server';
import { Button } from '@kit/ui/button';
import { Trans } from '@kit/ui/trans';
import { SitePageHeader } from '~/(marketing)/_components/site-page-header';
export const generateMetadata = async () => {
const t = await getTranslations('marketing');
return {
title: t('faq'),
};
};
async function FAQPage() {
const t = await getTranslations('marketing');
// replace this content with translations
const faqItems = [
{
// or: t('faq.question1')
question: `Do you offer a free trial?`,
// or: t('faq.answer1')
answer: `Yes, we offer a 14-day free trial. You can cancel at any time during the trial period and you won't be charged.`,
},
{
question: `Can I cancel my subscription?`,
answer: `You can cancel your subscription at any time. You can do this from your account settings.`,
},
{
question: `Where can I find my invoices?`,
answer: `You can find your invoices in your account settings.`,
},
{
question: `What payment methods do you accept?`,
answer: `We accept all major credit cards and PayPal.`,
},
{
question: `Can I upgrade or downgrade my plan?`,
answer: `Yes, you can upgrade or downgrade your plan at any time. You can do this from your account settings.`,
},
{
question: `Do you offer discounts for non-profits?`,
answer: `Yes, we offer a 50% discount for non-profits. Please contact us to learn more.`,
},
];
const structuredData = {
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: faqItems.map((item) => {
return {
'@type': 'Question',
name: item.question,
acceptedAnswer: {
'@type': 'Answer',
text: item.answer,
},
};
}),
};
return (
<>
<script
key={'ld:json'}
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
/>
<div className={'flex flex-col space-y-4 xl:space-y-8'}>
<SitePageHeader title={t('faq')} subtitle={t('faqSubtitle')} />
<div className={'container flex flex-col items-center space-y-8 pb-16'}>
<div className="divide-border flex w-full max-w-xl flex-col divide-y divide-dashed rounded-md border">
{faqItems.map((item, index) => {
return <FaqItem key={index} item={item} />;
})}
</div>
<div>
<Button
nativeButton={false}
render={<Link href={'/contact'} />}
variant={'link'}
>
<span>
<Trans i18nKey={'marketing.contactFaq'} />
</span>
<ArrowRight className={'ml-2 w-4'} />
</Button>
</div>
</div>
</div>
</>
);
}
export default FAQPage;
function FaqItem({
item,
}: React.PropsWithChildren<{
item: {
question: string;
answer: string;
};
}>) {
return (
<details
className={
'hover:bg-muted/70 [&:open]:bg-muted/70 [&:open]:hover:bg-muted transition-all'
}
>
<summary
className={'flex items-center justify-between p-4 hover:cursor-pointer'}
>
<h2 className={'cursor-pointer font-sans text-base'}>
<Trans i18nKey={item.question} defaults={item.question} />
</h2>
<div>
<ChevronDown
className={'h-5 transition duration-300 group-open:-rotate-180'}
/>
</div>
</summary>
<div className={'text-muted-foreground flex flex-col gap-y-2 px-4 pb-2'}>
<Trans i18nKey={item.answer} defaults={item.answer} />
</div>
</details>
);
}